找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3910|回复: 3
打印 上一主题 下一主题
收起左侧

我的这个万年历为什么不好用,哪里有错误啊,请大神指点

[复制链接]
跳转到指定楼层
楼主
ID:69465 发表于 2014-11-26 12:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include<reg52.h>
#include<intrins.h>

#define uint unsigned int
#define uchar unsigned char

uchar a,b,miao,shi,fen,ri,yue,nian,week,key1n,temp,aa,flag;//flag用于读取头文件中的温度值

#define yh 0x80      //LCD 第一行的初始位置
#define er 0x80+0x40//LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)
//液晶屏的与C51之间的引脚连接定义(显示数据线接C51的P0口)
sbit rs=P2^4;
sbit rw=P2^5;
sbit en=P2^6;

//DS1302时钟芯片与C51之间的引脚连接定义
sbit IO=P1^5;
sbit SCLK=P1^4;
sbit RST=P1^6;
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
/**********************************
ACC累加器=A
ACC.0=EOH
ACC.就是ACC的第0位。Acc可以位寻址。
累加器ACC是一个8位的存储单元,是用来放数据的。但是,这个存储单元有其特殊的地位,
是单片机中一个非常关键的单元,很多运算都要通过ACC来进行。以后在学习指令时,常用A来表示累加器。但有一些地方例外,比如在PUSH指令中,就必须用ACC这样的名字。
一般的说法,A代表了累加器中的内容、而ACC代表的是累加器的地址。
*****************************************/

//DS18B20的数据输出
sbit DQ=P1^3;

//校时按键与C51的引脚连接定义
sbit key1=P2^0;//设置键
sbit key2=P2^1;//加键
sbit key3=P2^2;//减键
//蜂鸣器
sbit buzzer=P1^0;//通过三极管8005驱动,端口低电平响
/*************************************/

//延时函数,后面经常调用
void delay(uint xms)//延时函数,有参函数
{
        uint x,y;
        for(x=xms;x>0;x--)
          for(y=110;y>0;y--);
}

/*****液晶写入指令函数与写入数据函数,以后可调用**********/
/*在这个程序中,液晶写入有关函数会在DS1302的函数中调用,所以液晶程序要放在前面
*/
void write_1602com(uchar com)//******液晶写入指令函数
{
        rs=0;//数据/指令选择置位置位指令
        rw=0;//读写选择置位写
        P0=com;//送入数据
        delay(1);
        en=1;//拉高使能端,为制造有效的下降沿做准备
        delay(1);
        en=0;//en由高变低,产生下降沿,液晶指示命令
       
}
void write_1602dat(uchar dat)//***液晶写入数据函数***
{
        rs=1;//数据/指令选择置位数据
        rw=0;//读写选择置位写
        P0=dat;//送入数据
        delay(1);
        en=1;//en置高电平,为制造下降沿做准备
        delay(1);
        en=0;//en由高变低,产生下降沿,液晶执行命令
}
void lcd_init()//***液晶初始函数****
{

   write_1602com(0x38);    /*显示模式设置*/
   delay(5);
   write_1602com(0x01);    /*显示清屏*/
   write_1602com(0x06);    /*显示光标移动设置*/
   delay(5);
   write_1602com(0x0C);    /*显示开及光标设置*/
}

void print(uchar a3,uchar *str)//写字符串函数(没有延时)
{
        write_1602com(a3|0x80);
        while(*str!='\0')
        {
                //delay(100);//延时一下
                write_1602dat(*str++);
        }
        *str=0;
}

/******************DS1302数***************/
void write_byte(uchar dat)//写入一个字节
{
        ACC=dat;
        RST=1;
        for(a=8;a>0;a--)
        {
                IO=ACC0;
                SCLK=1;
                SCLK=0;
                ACC=ACC>>1;
  }
}
uchar read_byte()//读一个字节
{
        RST=1;
        for(a=8;a>0;a--)
  {
                ACC7=IO;
                SCLK=1;
                SCLK=0;
                ACC=ACC>>1;
               
  }
        return(ACC);
}
//-------------------------
void write_1302(uchar add,uchar dat)//向1302芯片些函数,指定写入地址,数据
{
        RST=0;
        SCLK=0;
        RST=1;
        write_byte(add);
        write_byte(dat);
        SCLK=1;
        RST=0;
}
uchar read_1302(uchar add)//从1302读数据函数,指定读取数据来源地址
{
        uchar temp;
        RST=0;
        SCLK=0;
        RST=1;
        write_byte(add);
        temp=read_byte();
        SCLK=1;
        RST=0;
        return(temp);
}
uchar BCD_Decimal(uchar bcd)//BCD码转十进制函数,输入BCD,返回十进制
{
        uchar Decimal;
        Decimal=bcd>>4;
        return(Decimal=Decimal*10+(bcd&=0x0f));//返回十进制数
}
//--------------------
void ds1302_init()//1302芯片初始化函数(2014/11/20 12:00:00 week4)
{
        RST=0;
        SCLK=0;
       
        write_1302(0x8e,0x00);//允许写,禁止写保护
       
        write_1302(0x8e,0x80);//打开写保护
}
/************DS18B20*************/
void delay2(uint s)//延时,用于温度程序部分
{
        while(s--);//区分i,用s表示
}
void Init_DS18B20(void)//初始化DS18b20
{
        uchar w=0;//注意是w
        DQ=1;
        delay2(8);
        DQ=0;//拉低
        delay2(29);//延时大于480us(此处延时时间不确定,实际时修改)
        DQ=1;//拉高
        delay2(3);//(时间不确定)
        w=DQ;//稍作延时后如W=0则初始化成功
        delay2(20);
}
uchar ReadOneChar(void)//DS18b20读一个字节函数
{
        uchar i=0;
        uchar dat=0;
        for(i=8;i>0;i--)
        {
                DQ=0;//给脉冲信号
                dat>>=1;//右移一位
                DQ=1;//给脉冲信号
                if(DQ)
                dat|=0x80;
                delay2(4);
        }
        return(dat);
}
void WriteOneChar(uchar dat)//写一个字节函数
{
        uchar i=0;
        for(i=8;i>0;i--)
        {
                DQ=0;
                DQ=dat&0x01;
                delay2(5);
                DQ=1;
                dat>>=1;
        }
}
uint ReadTemperature(void)//读取温度
{
        uchar a1=0;//用于合并
        uchar b1=0;
        uint t=0;
        float tt=0;
        Init_DS18B20();
        WriteOneChar(0xCC);//跳过读取序列号的操作
        WriteOneChar(0x44);//启动温度转换
        Init_DS18B20();//再次初始化
        WriteOneChar(0xCC);//跳过读取序列号
        WriteOneChar(0xBE);//读取温度寄存器
        a1=ReadOneChar();//先读取低位
        b1=ReadOneChar();//后读取高位
        t=b1;
        t<<=8;
        t=t|a1;
        tt=t*0.0625;
        t=tt*10+0.5;//放大10倍并四舍五入
        return(t);
}

//-----------------
//温度显示子函数
void write_temp(uchar add,uchar dat)//向LCD写温度数据,并指定显示位置
{
  uchar gw,sw,xw;
        gw=dat%100/10;//取得个位数字
        sw=dat/100;//取得十位数字
        xw=dat%10;
        write_1602com(er+add);//er是头文件规定的值0x80+0x40
        write_1602dat(0x30+sw);//数字+30得倒该数字的LCD1602显示码
        write_1602dat(0x30+gw);//数字+30得倒该数字的LCD1602显示码
        write_1602dat(0x2e);//小数点
        write_1602dat(0x30+xw);//小数位
        write_1602dat(0xdf);//显示“°”(度)
        write_1602dat(0x43);//显示“C”符号,为液晶字符的地址码
}
//-----------------------
//时分秒显示子函数
void write_sfm(uchar add,uchar dat)//向LCD写时分秒,有显示位置加、显示数据,两个参数
{
        uchar gw,sw;
        gw=dat%10;//取得个位数字
        sw=dat/10;//取得十位数字
        write_1602com(er+add);//er是头文件规定的值0x80+0x40
        write_1602dat(0x30+sw);//数字+30得倒该数字的LCD1602显示码
        write_1602dat(0x30+gw);//数字+30得倒该数字的LCD1602显示码
}
//-------------------
//年月日显示子函数
void write_nyr(uchar add,uchar dat)//向LCD写年月日,有显示位置加数、显示数据,两个参数
{
        uchar gw,sw;
        gw=dat%10;//取得个位数字
        sw=dat/10;//取得十位数字
        write_1602com(yh+add);//设定显示位置为第一个位置+add
        write_1602dat(0x30+sw);//数字+30得倒该数字的LCD1602显示码
        write_1602dat(0x30+gw);//数字+30得倒该数字的LCD1602显示码
}
//-------------------
void write_week(uchar week)//写星期函数
{
        write_1602com(yh+0x0e);//星期字符的显示位置
        switch(week)
        {
                case 1:write_1602dat('1');//括号内写入1        注意是单引号
                break;
                case 2:write_1602dat('2');
                break;
                case 3:write_1602dat('3');
                break;
                case 4:write_1602dat('4');
                break;
                case 5:write_1602dat('5');
                break;
                case 6:write_1602dat('6');
                break;
                case 7:write_1602dat('7');
                break;
                                       
  }
}

/**************键盘扫描有关函数*********/


void keyscan()
{
         if(key1==0)//---------key1为功能键(设置键)------
         {
                 delay(9);//延时,用于消除抖动
                if(key1==0)//延时后再次确认按键按下
                {
                   buzzer=0;//蜂鸣器短响一次
                   delay(20);
                   buzzer=1;
                   while(!key1);
                   key1n++;
                   if(key1n==9)
                               key1n=1;//设置按键共有秒、分、时、星期、日、月、年、返回,8个功能循环
                  switch(key1n)
                  {
                          case 1:TR0=0;//关闭定时器
                                   write_1602com(er+0x07);//秒的位置
                                   write_1602com(0x0f);//设置为光标闪烁
//                                   temp=(miao)/10*16+(miao)%10;//秒化为bcd码
//                                   write_1302(0x8e,0x00);
//                                   write_1302(0x80,0x80|temp);//秒数据写入
//                                   write_1302(0x8e,0x80);
                                   break;
                        case 2:write_1602com(er+0x04);//分的位置
                                   break;//不用再次设置为闪烁状态了
                        case 3:write_1602com(er+0x01);//时的位置
                                   break;
                        case 4:write_1602com(yh+0x0e);//星期的位置
                                   break;
                        case 5:write_1602com(yh+0x09);//日的位置
                                   break;
                        case 6:write_1602com(yh+0x06);//月的位置
                                  break;
                        case 7:write_1602com(yh+0x03);//年的位置
                                  break;
                        case 8:write_1602com(0x0c);//第8次,光标不闪烁                                  
                                  TR0=1;//重新打开定时器
//                                  temp=(miao)/10*16+(miao)%10;
//                                  write_1302(0x8e,0x00);
//                                  write_1302(0x80,0x00|temp);//写入秒
//                                  write_1302(0x8e,0x80);
                                  break;
                  }
                  
                }
         }
/************加键key2****************/
    if(key1n!=0)//当key1按下以后,再按一下键才有效(按键次数不等于零)
        {
          if(key2==0)//上调键
          {
                    delay(10);
                  if(key2==0)
                  {
                             buzzer=0;
                           delay(20);
                           buzzer=1;
                           while(!key2);
                           switch(key1n)
                           {
                                      case 1:miao++;//
                                                   if(miao==60)        miao=0;
                                                   write_sfm(0x06,miao);/*在十位的位置写入,因为为两位数,个位数自动再后面显示*/
                                                   temp=(miao)/10*16+(miao)%10;//转换为bcd码
                                                   write_1302(0x8e,0x00);//允许写
                                                   write_1302(0x80,temp);// 写入秒
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(er+0x07);//液晶模式为写入后自动右移,在此返回原来位置
                                                   break;
                                        case 2:fen++;
                                                   if(fen==60) fen=0;
                                                   write_sfm(0x03,fen);//在十位数位置开始写入
                                                   temp=(fen)/10*16+(fen)%10;//转换为bcd码
                                                   write_1302(0x8e,0x00);//允许写
                                                   write_1302(0x82,temp);//写入分
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(er+0x04);//返回个位数的位置
                                                   break;
                                        case 3:shi++;
                                                   if(shi==24) shi=0;
                                                   write_sfm(0,shi);//在0位开始写入
                                                   temp=(shi)/10*16+(shi)%10;//转换为bcd码
                                                   write_1302(0x8e,0x00);//允许写
                                                   write_1302(0x84,temp);//写入时
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(er+0x01);//返回到个位位置
                                                   break;
                                        case 4:week++;
                                                   if(week==8) week=1;
                                                   write_1602com(yh+0x0e);//显示位置
                                                   write_week(week);//写入星期
                                                   temp=(week)/10*16+(week)%10;
                                                   write_1302(0x8e,0x00);//允许写入
                                                   write_1302(0x8a,temp);//写入周
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(yh+0x0e);
                                                   break;
                                        case 5:ri++;
                                                   if(ri==32) ri=1;
                                                   write_nyr(0x08,ri);//注意是在十位开始写入
                                                   temp=(ri)/10*16+(ri)%10;//转换为bcd码
                                                   write_1302(0x8e,0x00);//允许写
                                                   write_1302(0x86,temp);//写入日
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(yh+0x09);//返回个位数
                                                   break;
                                        case 6:yue++;
                                                   if(yue==13) yue=1;
                                                   write_nyr(0x05,yue);//在十位开始写入
                                                   temp=(yue)/10*16+(yue)%10;//转换为bcd码
                                                   write_1302(0x8e,0x00);//允许写
                                                   write_1302(0x88,temp);//写入月
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(yh+0x06);//返回个位位置
                                                   break;
                                        case 7:nian++;
                                                   if(nian==100) nian=0;
                                                   write_nyr(0x02,nian);//在第一行第三个字符开始写入
                                                   temp=(nian)/10*16+(nian)%10;//转换为bcd码
                                                   write_1302(0x8e,0x00);//允许写
                                                   write_1302(0x8c,temp);//写入年
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(yh+0x03);//返回个位位置
                                                   break;
                           }
                  }
          }
        }
/****************减键******************/
    if(key3==0)
        {
                delay(10);
                if(key3==0)
                {
                        buzzer=0;
                        delay(20);
                        buzzer=1;
                        while(!key3);
                        switch(key1n)
                        {
                                case 1:miao--;/*此处有疑问:无符号数据是否要修改*/
                                                   if(miao==-1) miao=59;//减到-1返回59
                                                   write_sfm(0x06,miao);//在十位数写入
                                                   temp=(miao)/10*16+(miao)%10;//转换为bcd码
                                                   write_1302(0x8e,0x00);//允许写
                                                   write_1302(0x80,temp);//写入秒
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(er+0x07);//返回个位位置
                                                   break;
                                        case 2:fen--;
                                                   if(fen==-1) fen=59;
                                                   write_sfm(0x03,fen);//在十位数位置写入
                                                   temp=(fen)/10*16+(fen)%10;//转换为bcd码
                                                   write_1302(0x8e,0x00);//允许写入
                                                   write_1302(0x82,temp);//写入分
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(er+0x04);//返回个位数位置
                                                   break;
                                    case 3:shi--;
                                                   if(shi==-1) shi=23;
                                                   write_sfm(0,shi);//在0位开始写入
                                                   temp=(shi)/10*16+(shi)%10;//转换为bcd码
                                                   write_1302(0x8e,0x00);//允许写入
                                                   write_1302(0x84,temp);//写入时
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(er+0x01);//返回到个位位置
                                                   break;
                                        case 4:week--;
                                                   if(week==0) week=7;
                                                   write_1602com(yh+0x0e);//显示位置
                                                   write_week(week);//写入星期
                                                   temp=(week)/10*16+(week)%10;//转换为bcd码
                                                   write_1302(0x8e,0x00);//允许写入
                                                   write_1302(0x8a,temp);//写入周
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(yh+0x0e);//返回原来位置
                                                   break;
                                        case 5:ri--;
                                                   if(ri==0) ri=31;
                                                   write_nyr(0x08,ri);//在十位开始显示
                                                   temp=(ri)/10*16+(ri)%10;//转换为bcd码
                                                   write_1302(0x8e,0x00);//允许写入
                                                   write_1302(0x86,temp);//写入日
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(yh+0x09);//返回个位数
                                                   break;
                                        case 6:yue--;
                                                   if(yue==0) yue=12;
                                                   write_nyr(0x05,yue);//在十位数位置开始写入
                                                   temp=(yue)/10*16+(yue)%10;//转换为bcd码
                                                   write_1302(0x8e,0x00);//允许写入
                                                   write_1302(0x88,temp);//写入月
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(yh+0x06);//返回到个位位置
                                                   break;
                                        case 7:nian--;
                                                   if(nian==-1) nian=99;
                                                   write_nyr(0x02,nian);//第一行第三个字符开始写入
                                                   temp=(nian)/10*16+(nian)%10;//转换为bcd码
                                                   write_1302(0x8e,0x00);//允许写入
                                                   write_1302(0x8c,temp);//写入年
                                                   write_1302(0x8e,0x80);//打开保护
                                                   write_1602com(yh+0x03);//返回在年的尾数位置
                                                   break;
                        }
                }
        }
}
//-----------------
//按键初始化时间函数
void chushihua()//初始化时间函数
{
                     RST=0;
                     SCLK=0;
                     write_1302(0x8e,0x00);//允许写
                     write_1302(0x80,0x00);//秒:00
                     write_1302(0x82,0x00);//分:00
                     write_1302(0x84,0x12);//时:12       
                     write_1302(0x8a,0x04);//周:4
                     write_1302(0x86,0x20);//日:20
                      write_1302(0x88,(11)/10*16+(11)%10);//月:11
                     write_1302(0x8c,(14)/10*16+(14)%10);//年:14
                        write_1302(0x8e,0x80);//打开保护

}
////}
//----------
//初始化的函数
void init_timer0(void)//定时器0初始化函数
{
        TMOD|=0x01;//设置为定时器0的工作方式1
        TH0=(65536-20000)/256;
        TL0=(65536-20000)%256;
        EA=1;
        ET0=1;//允许T0中断
        TR0=1;//启动中断       
}

//void init_timer1(void)//定时器1初始化函数
//{
//        TMOD|=0x01;//设置为定时器0的工作方式1
//        TH1=(65536-20000)/256;
//        TL1=(65536-20000)%256;
//        EA=1;
//        ET1=1;//允许T0中断
//        TR1=1;//启动中断       
//}
/*************************************************
                               主函数
*************************************************/
void main()
{
      uint temp1;
          lcd_init();
          ds1302_init();
          init_timer0();
          buzzer=0;
          delay(80);
          buzzer=1;
          chushihua();//初始化时间函数

          while(1)
          {
                     if(flag==1)
                   {
                             flag=0;
                          temp1=ReadTemperature();
                   }
                          
                    keyscan();                                                                                  
                  
                   print(0x40,"  :  :          ");
                   write_temp(10,temp1);//显示温度,从第二行第11个字符今后开始显示
                   write_sfm(6,miao);//秒,从第二行第7个字符开始显示
                   write_sfm(3,fen);//分,从第二行第6个字符开始显示
                   write_sfm(0,shi);//时,从第二行第1个字符开始显示

                   print(0x80,"20  /  /   W < >");
               write_1602com(yh+0x0c);
                   write_1602dat(0x7e);//→右箭头
                   write_nyr(8,ri);//日期,从第一行第9个字符
                   write_nyr(5,yue);//月份,从第一行第6个字符
                   write_nyr(2,nian);//年,从第一行第3个字符
                   write_week(week);
                  
          }
}
void timer0_isr(void) interrupt 1
{
         TH0=(65536-20000)/256;
         TL0=(65536-20000)%256;
           miao=BCD_Decimal(read_1302(0x81));
           fen =BCD_Decimal(read_1302(0x83));
           shi =BCD_Decimal(read_1302(0x85));
           ri  =BCD_Decimal(read_1302(0x87));
           yue =BCD_Decimal(read_1302(0x89));
           nian=BCD_Decimal(read_1302(0x8d));
          aa++;
         if(aa==30)                
         {
                  aa=0;
                 flag=1;
         }
}
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1 发表于 2014-11-26 13:10 来自触屏版 | 只看该作者
硬件图呢,另外现在这个程序的现象是什么
回复

使用道具 举报

板凳
ID:69706 发表于 2014-11-30 19:10 | 只看该作者
我这有个类似的链接:http://pan.baidu.com/s/1jGED8RO 密码:o83c
回复

使用道具 举报

地板
ID:70118 发表于 2014-12-8 01:20 | 只看该作者
你这也太长了吧,看来你的C待充血了

评分

参与人数 1黑币 +10 收起 理由
admin + 10 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表