最近花了近一个星期做了个时钟,又花了近半月写了个程序代码,但还不是很完美,等待再一次升级。MCU采用AT89S52,clock采用DS12887,LCD12864自定义大数字显示字符,温度传感器DS18B20,无农历显示。完整程序代码如下:
- #include<reg52.h>
- #include<intrins.h> //库文件,_nop_指令用
- #define uint unsigned int
- #define uchar unsigned char
- #define lcddata P0 //宏定义lcddata为P0口数据
- sbit busy=P0^7;
- sbit rs=P2^7; //定义数据,命令端
- sbit rw=P2^6; //定义读写端
- sbit en=P2^5; //定义使能端
- sbit scl=P2^2;
- sbit sda=P2^1;
- sbit dscs=P2^0; //DS12887
- sbit dsas=P2^1;
- sbit dsrw=P2^2;
- sbit dsds=P2^3;
- sbit dq=P3^1;
- sbit set=P3^2;
- sbit jia=P3^3;
- sbit jian=P3^4;
- sbit enter=P3^5;
- uchar miao,fen,shi,nian,yue,ri,week,bw,sw,gw,xiao,num1,m1,f1,s1;
- uchar a1,a2,a3,a4,baiw,shiw,gew;
- bit bdata flag,flag1,flag2;
- uchar code tab0[]=//自定义数字0
- {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x0F,0xF0,0x1F,0xF0,0x3F,0xF8,0x3E,0xF8,
- 0x3E,0x7C,0x3C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7E,0x7C,0x3E,0x7C,0x3E,
- 0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x3C,0x7C,
- 0x3E,0x7C,0x3E,0xF8,0x1F,0xF8,0x0F,0xF0,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,};
- uchar code tab1[]=//自定义数字1
- {0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xF0,0x03,0xF0,0x07,0xF0,0x0F,0xF0,0x1F,0xF0,
- 0x1F,0xF0,0x1F,0xF0,0x1D,0xF0,0x19,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,
- 0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,
- 0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,};
- uchar code tab2[]=//自定义数字2
- {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xF0,0x1F,0xF8,0x3F,0xFC,0x3F,0xFE,0x7E,0x7E,
- 0x7E,0x3E,0x7C,0x3E,0x00,0x3E,0x00,0x3E,0x00,0x7E,0x00,0x7E,0x00,0xFC,0x01,0xFC,
- 0x01,0xF8,0x03,0xF0,0x07,0xF0,0x0F,0xE0,0x1F,0xC0,0x1F,0x80,0x3F,0x00,0x7E,0x00,
- 0x7C,0x00,0x7F,0xFE,0x7F,0xFE,0x7F,0xFE,0x7F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,};
- uchar code tab3[]=//自定义数字3
- {0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x1F,0xF8,0x3F,0xFC,0x3F,0xFC,0x7E,0x7E,
- 0x7C,0x3E,0x7C,0x3E,0x00,0x3E,0x00,0x3E,0x00,0x7C,0x00,0xFC,0x07,0xF8,0x07,0xF0,
- 0x07,0xF8,0x07,0xFC,0x00,0xFC,0x00,0x7E,0x00,0x3E,0x00,0x3E,0x7C,0x3E,0x7C,0x3E,
- 0x7E,0x7E,0x7E,0xFC,0x3F,0xFC,0x3F,0xF8,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,};
- uchar code tab4[]=//自定义数字4
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x01,0xF0,0x01,0xF0,0x03,0xF0,0x03,0xF0,
- 0x07,0xF0,0x07,0xF0,0x0F,0xF0,0x0F,0xF0,0x1F,0xF0,0x1E,0xF0,0x3E,0xF0,0x3C,0xF0,
- 0x7C,0xF0,0x78,0xF0,0xF8,0xF0,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0x00,0xF0,
- 0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,};
- uchar code tab5[]=//自定义数字5
- {0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7C,0x00,
- 0x7C,0x00,0x7C,0x00,0x7C,0x00,0x7C,0x00,0x7F,0xF0,0x7F,0xF8,0x7F,0xFC,0x7F,0xFE,
- 0x7E,0x7E,0x7C,0x3E,0x3C,0x3E,0x00,0x3E,0x00,0x3E,0x00,0x3E,0x00,0x3E,0x7C,0x3E,
- 0x7E,0x7E,0x7E,0xFC,0x3F,0xFC,0x1F,0xF8,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,};
- uchar code tab6[]=//自定义数字6
- {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x0F,0xF8,0x1F,0xFC,0x1F,0xFC,0x3E,0x7C,
- 0x3E,0x7C,0x3C,0x3C,0x7C,0x00,0x7C,0x00,0x7D,0xC0,0x7F,0xF0,0x7F,0xF8,0x7F,0xFC,
- 0x7E,0xFC,0x7E,0x7E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,
- 0x3E,0x7C,0x3E,0xFC,0x3F,0xF8,0x1F,0xF8,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,};
- uchar code tab7[]=//自定义数字7
- {0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,
- 0x00,0x7C,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,
- 0x01,0xE0,0x03,0xE0,0x03,0xE0,0x03,0xE0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0x80,
- 0x0F,0x80,0x0F,0x80,0x0F,0x80,0x0F,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};
- uchar code tab8[]=//自定义数字8
- {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x1F,0xF8,0x3F,0xF8,0x3F,0xFC,0x7C,0x7C,
- 0x7C,0x3C,0x7C,0x3E,0x7C,0x3C,0x7C,0x3C,0x3C,0x7C,0x3F,0xF8,0x1F,0xF8,0x0F,0xE0,
- 0x1F,0xF8,0x3F,0xFC,0x7E,0x7C,0x7C,0x7C,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,
- 0x7C,0x7C,0x7E,0xFC,0x3F,0xF8,0x1F,0xF8,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,};
- uchar code tab9[]=//自定义数字9
- {0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x1F,0xF0,0x3F,0xF8,0x3F,0xF8,0x7C,0x7C,
- 0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7F,0xFC,
- 0x3F,0xFC,0x3F,0xFC,0x0F,0xFC,0x00,0x7C,0x00,0x7C,0x00,0x7C,0x00,0x7C,0x7C,0x7C,
- 0x7C,0x78,0x7E,0xF8,0x3F,0xF8,0x3F,0xF0,0x1F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,};
- uchar code tab10[]=//自定义摄氏度图标图标
- {0x00,0x00,0x00,0x30,0x00,0x48,0x00,0x58,0x00,0x48,0x00,0x58,0x00,0x48,0x00,0x58,
- 0x00,0x48,0x00,0xFC,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x00,0xFC,0x00,0x78,};
- uchar code tab11[]=//自定义摄氏度
- {0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x3E,0x12,0x60,0x12,0xC0,0x0C,0xC0,0x00,0xC0,
- 0x00,0xC0,0x00,0xC0,0x00,0x60,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
- uchar code tabm[]=//自定义:号
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x0F,0xC0,
- 0x1F,0xE0,0x1F,0xE0,0x1F,0xE0,0x1F,0xE0,0x0F,0xC0,0x07,0x80,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x07,0x80,0x0F,0xC0,0x1F,0xE0,0x1F,0xE0,0x1F,0xE0,0x1F,0xE0,
- 0x0F,0xC0,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};
- void delay(uint aa)//延时
- {
- uchar bb;
- while(aa--)
- {
- for(bb=0;bb<115;bb++) //1ms基准延时程序
- {;}
- }
- }
- void dsdelay(uint t) //1us基准延时程序
- {
- for (;t>0;t--);
- }
- void lcd_busy(void)//查忙子程序
- {
- busy=1; //把忙标志位置1
- en=0; //把使能端置0
- rs=0; //把rs端置0,为指令操作
- rw=1; //为读操作
- en=1; //拉高使能端
- _nop_(); //等待
- while(busy==1); //检测忙标志位,
- en=0; //忙标志位为0,则把使能拉低
- }
- void lcd_addr(addr)//写入地址及命令
- {
- lcd_busy(); //忙标志检测
- rs=0; //指令操作
- rw=0; //写入操作
- en=1; //拉高使能端
- lcddata=addr; //放上数据
- _nop_(); //等待
- en=0; //拉低使能端,数据写入液晶
- }
- void lcd_data(dat)//写入要显示的数据
- {
- lcd_busy(); //忙标志检测
- rs=1; //数据操作
- rw=0; //写入操作
- en=1; //拉高使能端
- lcddata=dat; //放上数据
- _nop_(); //等待
- en=0; //拉低使能端,数据写入液晶
- }
- void lcd_init(void)//LCD初始化
- {
- lcd_addr(0x30); //基本指令集
- delay(1);
- lcd_addr(0x01); //清屏,地址指针指向00H
- delay(20); //等待>10ms
- lcd_addr(0x06); //光标右移,整体不移
- delay(1);
- lcd_addr(0x0c); //开显示,关游标,关游标位置
- delay(1);
- }
- void lcd_clear()//清除GDROM,否则花屏
- {
- uchar a,b,c;
- lcd_addr(0x34);//扩充指令集
- for(a=0;a<2;a++)//分上下两屏写入
- {
- for(b=0;b<32;b++)//每半屏32行
- {
- lcd_addr(0x80+b);//写y坐标
- if(a==0) //写x坐标
- lcd_addr(0x80); //上半屏
- else
- lcd_addr(0x88);//下半屏
- for(c=0;c<16;c++)//一整行
- lcd_data(0x00); //写入0,清除GDROM
- }
- }
- lcd_addr(0x30);//基本指令集
- }
- //LCD12864显示自定义字符程序(字符显示在屏中间两行,每个字符16*32点阵)
- void lcd_disp(uchar add1,uchar add2,uchar add3,uchar add4,uchar code *P)
- {
- uchar j,k;
- lcd_addr(0x34);//扩充指令集
- lcd_addr(0x36);//打开绘图
- for(j=0;j<16;j++) //显示上16行,字符上半截显示
- {
- lcd_addr(add2+j);//写y坐标
- lcd_addr(add1); //写x坐标
- for(k=0;k<2;k++)//每行显示二个字节
- {lcd_data(*P++);} //写入编码数据
- }
- for(j=0;j<16;j++) //显示下16行,字符下半截显示
- {
- lcd_addr(add4+j);//写y坐标
- lcd_addr(add3); //写x坐标
- for(k=0;k<2;k++)//每行显示二个字节
- {lcd_data(*P++);} //写入编码数据
- }
- lcd_addr(0x30);//基本指令集
- }
- /****************DS18B20复位函数************************/
- void ds1820_int()
- {
- uchar ds_flag=1;
- while(ds_flag)
- {
- dq=1;
- _nop_();
- _nop_();
-
- dq=0; //从高拉倒低
- dsdelay(50); //550 us
- dq=1;
- dsdelay(6); //66 us
- ds_flag=dq; //ds_flag=0 复位成功,继续下一步
- }
- dsdelay(45); //延时500 us
- ds_flag=~dq;
- dq=1; //拉高电平
- }
-
- /****************DS18B20写命令函数************************/
- //向1-WIRE 总线上写1个字节
- void write_byte(uchar val)
- {
- uchar i;
- for(i=8;i>0;i--)
- {
- dq=1;
- _nop_();
- _nop_(); //从高拉倒低
- dq=0;
- _nop_();
- _nop_();
- _nop_();
- _nop_(); //5 us
- dq=val&0x01; //写入一位数据
- dsdelay(6); //66 us
- val=val/2; //右移1位
- }
- dq=1;
- dsdelay(1);
- }
- /****************DS18B20读1字节函数************************/
- //从总线上取1个字节
- uchar read_byte()
- {
- uchar i;
- uchar num2=0;
- for(i=8;i>0;i--)
- {
- dq=1;
- _nop_();
- _nop_();
- num2>>=1;
- dq=0;
- _nop_();
- _nop_();
- _nop_();
- _nop_(); //4 us
- dq=1 ; //释放总线
- _nop_();
- _nop_();
- _nop_();
- _nop_(); //4 us
- if(dq) //如果dq=1;则把num的最高位置1
- {
- num2|=0x80; //如果dq=0;则越过num|=0x80执行延时
- }
- dsdelay(6); //66 us
- }
- dq=1;
- return(num2); //读出的原始值
- }
-
- /****读出DS18B20温度数据并转换成显示用的BCD码*********/
- void read_temp()
- {
- uchar tem,num,low,high;
- uint temp;
- ds1820_int();
- dsdelay(1);
- write_byte(0xcc); //跳过ROM命令
- write_byte(0xbe); //读18B20暂存器命令(0xBE)
- low=read_byte(); //读温度值的低字节
- high=read_byte(); //读温度值的高字节
- tem=high&0xf8; //分离出温度符号
- temp=high;
- temp<<=8; //把高八位左移到高位
- temp=temp|low; //分离出16位的温度数据(包括符号及小数)
- flag=0; //符号标志位清0
- if(tem>16) //符号判断
- {
- temp=65536-temp;//负温度求补码
- flag=1; //符号标志位置1 (表示是负数)
- }
- num=temp&0x0f; //分离出小数
- num=num*6; //小数乘系数
- xiao=num/10; //分离并保存小数第一个字符
- num=num%10; //分离并保存小数第二个字符
- if(num>5) //小数进行四舍五入
- {
- xiao++; //小数第二位如大于5就加1
- }
- temp=temp>>4; //右移四位,得到温度整数部分数据
- baiw=temp/100; //分离出百位
- shiw=temp%100/10;//分离出十位
- gew=temp%10; //分离出个位
- }
- void temp_disp()//温度显示程序
- {
- read_temp() ;//读出温度数据并转换成显示数据
- if(flag==1)//如为1表示是负温度值,在百位显示负号
- {
- lcd_addr(0x9c);
- lcd_data(0x20);//显示空白
- lcd_data(0x2d);//显示负号
- }
- if(flag==0)//如为0表示是正温度值,显示百位温度
- {
- lcd_addr(0x9c);//百位地址
- lcd_data(0x20);//显示百位
- lcd_data(0x30+baiw);
- }
- lcd_addr(0x9d);
- lcd_data(0x30+shiw);
- lcd_data(0x30+gew);
-
- lcd_addr(0x9e);
- lcd_data(0x2e);
- lcd_data(0x30+xiao);
- }
- //******************DS12887读写程序*************************************
- void write_ds(uchar add,uchar date)//往DS12887内写数据(add地址,date数据)
- {
- dscs=0;
- dsas=1;
- dsds=1;
- dsrw=1;
- P1=add; //先送地址
- dsas=0;
- dsrw=0;
- P1=date; //后写入数据
- dsrw=1;
- dsas=1;
- dscs=1;
- }
- uchar read_ds(uchar add)//读DS12887内部数据(带返回值的)
- {
- uchar ds_date;
- dsas=1;
- dsds=1;
- dsrw=1;
- dscs=0;
- P1=add; //先送地址
- dsas=0;
- dsds=0;
- P1=0xff;
- ds_date=P1;//后读出数据
- dsds=1;
- dsas=1;
- dscs=1;
- return ds_date;//带返回值语句
- }
- void ds_init() //DS12887初始化
- {
- dscs=0;
- write_ds(0x0a,0x20);//启动DS12887
- write_ds(0x0b,0x86);//禁止更新,接下来初始化数据,即写入时间,日期等
- write_ds(0x0b,0x06);//正常更新,二进制格式,24进制小时
-
- }
- //***************数据转换及显示程序**************************************
- void lcd_disdata(uchar bcd)//送显示地址及显示数据
- {
- switch(bcd)//a1,a2,a3,a4为自定义字符上半截XY及下半截XY地址,tab*为自定义字符码
- {
- case 0:lcd_disp(a1,a2,a3,a4,tab0);//把地址及字符数据送到LCD显示程序
- break;
- case 1:lcd_disp(a1,a2,a3,a4,tab1);
- break;
- case 2:lcd_disp(a1,a2,a3,a4,tab2);
- break;
- case 3:lcd_disp(a1,a2,a3,a4,tab3);
- break;
- case 4:lcd_disp(a1,a2,a3,a4,tab4);
- break;
- case 5:lcd_disp(a1,a2,a3,a4,tab5);
- break;
- case 6:lcd_disp(a1,a2,a3,a4,tab6);
- break;
- case 7:lcd_disp(a1,a2,a3,a4,tab7);
- break;
- case 8:lcd_disp(a1,a2,a3,a4,tab8);
- break;
- case 9:lcd_disp(a1,a2,a3,a4,tab9);
- break;
- default://lcd_disp(a1,a2,a3,a4,tab0);
- break;
- }
- }
- //分离个位和十位子程序
- void datafl(uchar dafl)
- {
- gw=dafl%10;//取余
- sw=dafl/10;//取模
- }
- void sfm_data()//读出DS12887数据及LCD12864显示地址赋值
- {
- a2=0x90;//自定义字符上半截Y轴地址(因为Y地址固定不变,所以先写入)
- a4=0x80;//自定义字符下半截Y轴地址(因为Y地址固定不变,所以先写入)
- if(flag1==0)
- {
- miao=read_ds(0);//指定DS12887秒地址,读出秒的值
- fen=read_ds(2); //指定DS12887分地址,读出分的值
- shi=read_ds(4); //指定DS12887时地址,读出时的值
- week=read_ds(6); //指定DS12887周地址,读出周的值
- ri=read_ds(7); //指定DS12887日地址,读出日的值
- yue=read_ds(8); //指定DS12887月地址,读出月的值
- nian=read_ds(9); //指定DS12887年地址,读出年的值
- }
- datafl(miao); //把DS12887读出的数据分离出个位和十位
- if(miao!=m1) //如秒值变化就进入刷新显示
- {
- m1=miao;
- a1=0x97;//自定义字符(秒个位)上半截X轴地址
- a3=0x8f;//自定义秒字符(秒个位)下半截X轴地址
- lcd_disdata(gw);//秒个位送地址转换再送LCD显示
- a1=0x96;//自定义字符(秒十位)上半截X轴地址
- a3=0x8e;//自定义字符(秒十位)下半截X轴地址
- lcd_disdata(sw);//秒十位送地址转换再送LCD显示
- }
- if(fen!=f1)////如分值变化就进入刷新显示
- {
- f1=fen;
- datafl(fen); //把DS12887读出的数据分离出个位和十位
- a1=0x94;
- a3=0x8c;
- lcd_disdata(gw);//分个位送地址转换再送LCD显示
- a1=0x93;
- a3=0x8b;
- lcd_disdata(sw);//分十位送地址转换再送LCD显示
- }
- if(shi!=s1)////如时值变化就进入刷新显示
- {
- s1=shi;
- datafl(shi); //把DS12887读出的数据分离出个位和十位
- a1=0x91;
- a3=0x89;
- lcd_disdata(gw);//时个位送地址转换再送LCD显示
- a1=0x90;
- a3=0x88;
- lcd_disdata(sw);//时十位送地址转换再送LCD显示
- }
- }
-
- void xstb(uchar code *p1,uchar code *p2)//自定义图标及符号显示程序(16*16点阵)
- {
- uchar j,k;
- lcd_addr(0x34);//扩充指令集
- lcd_addr(0x36);//打开绘图
- for(j=0;j<16;j++)
- {
- lcd_addr(0x90+j);
- lcd_addr(0x9b);
- for(k=0;k<2;k++)//每行显示二个字节
- {lcd_data(*p1++);} //写入编码数据
- }
- for(j=0;j<16;j++)
- {
- lcd_addr(0x90+j);
- lcd_addr(0x9f);
- for(k=0;k<2;k++)//每行显示二个字节
- {lcd_data(*p2++);} //写入编码数据
- }
-
- }
-
- void nyrhz()//固定年月日周汉字显示
- {
- uchar *p;
- p="20 年 月 日";
- lcd_addr(0x80);
- while(*p!='\0')
- {
- lcd_data(*p);
- p++;
- }
- p="星期";
- lcd_addr(0x98);
- while(*p!='\0')
- {
- lcd_data(*p);
- p++;
- }
- xstb(tab10,tab11);
- }
- void week_disp()
- {
- lcd_addr(0x9a);//周地址
- switch(week)
- {
- case 1:lcd_data(0xd2);lcd_data(0xbb);//显示一
- break;
- case 2:lcd_data(0xb6);lcd_data(0xfe);//显示二
- break;
- case 3:lcd_data(0xc8);lcd_data(0xfd);//显示三
- break;
- case 4:lcd_data(0xcb);lcd_data(0xc4);//显示四
- break;
- case 5:lcd_data(0xce);lcd_data(0xe5);//显示五
- break;
- case 6:lcd_data(0xc1);lcd_data(0xf9);//显示六
- break;
- case 7:lcd_data(0xc8);lcd_data(0xd5);//显示日
- break;
- default://lcd_data(0xb4);lcd_data(0xed);//显示错
- break;
- }
- }
- void lyr_disp()//年月日周数据处理及显示程序
- {
- uchar n1,y1,r1;
-
- datafl(nian);//年显示数据分离成个位和十位
- if(nian!=n1)
- {
- n1=nian;
- datafl(nian);
- lcd_addr(0x81); //指定年的显示地址
- lcd_data(0x30+sw);
- lcd_data(0x30+gw);
- }
- if(yue!=y1)
- {
- y1=yue;
- datafl(yue);
- lcd_addr(0x83);
- lcd_data(0x30+sw);
- lcd_data(0x30+gw);
- }
- if(ri!=r1)
- {
- r1=ri;
- datafl(ri);
- lcd_addr(0x85);
- lcd_data(0x30+sw);
- lcd_data(0x30+gw);
- }
- week_disp();//周数据处理及显示
- }
- void sfm_rst(uchar add1,uchar add2,uchar add3,uchar add4)//时分秒清零程序
- {//在时分秒调整时自定义字符会闪烁就会调用此程序
- uchar j,k;
- lcd_addr(0x34);//扩充指令集
- lcd_addr(0x36);//打开绘图
- for(j=0;j<16;j++) //显示上16行,字符上半截显示
- {
- lcd_addr(add2+j);//写y坐标
- lcd_addr(add1); //写x坐标
- for(k=0;k<2;k++)//每行显示二个字节
- {lcd_data(0);} //写入编码数据
- }
- for(j=0;j<16;j++) //显示下16行,字符下半截显示
- {
- lcd_addr(add4+j);//写y坐标
- lcd_addr(add3); //写x坐标
- for(k=0;k<2;k++)//每行显示二个字节
- {lcd_data(0);} //写入编码数据
- }
- }
-
- void jiajian()
- {
- if(num1!=0) //如果不等于0表示有键按下进入程序
- {
- if(jia==0) //加键按下进入
- {
- delay(5);
- if(jia==0) //再次确认加键按下进入
- {
- while(!jia); //松手进入
- if(num1==1) //如果=1就表明光标在秒的位置
- {
- miao++; //秒+1
- if(miao>59)//秒加到60进入
- miao=0; //秒清0
-
- }
- if(num1==2) //确定光标在分位置进入
- {
- fen++; //
- if(fen>59)
- fen=0;
-
- }
- if(num1==3) //确定光标在时位置进入
- {
- shi++;
- if(shi>23)
- shi=0;
- }
-
- if(num1==4) //确定光标在日位置进入
- {
- ri++;
- if(ri>31)
- ri=1;
- }
- if(num1==5) //确定光标在月位置进入
- {
- yue++;
- if(yue>12)
- yue=1;
- }
- if(num1==6) //确定光标在年位置进入
- {
- nian++;
- if(nian>99)
- nian=0;
- }
- if(num1==7) //确定光标在周位置进入
- {
- week++;
- if(week>7)
- week=1;
- }
- }
- }
- if(jian==0) //减键按下进入
- {
- delay(5);
- if(jian==0)
- {
- while(!jian);
- if(num1==1)
- {
- miao--;
- if(miao==-1)
- miao=59;
-
- }
- if(num1==2)
- {
- fen--;
- if(fen==-1)
- fen=59;
- }
- if(num1==3)
- {
- shi--;
- if(shi==-1)
- shi=23;
- }
- if(num1==4)
- {
- ri--;
- if(ri<1)
- ri=31;
- }
- if(num1==5) //
- {
- yue--;
- if(yue<1)
- yue=12;
- }
- if(num1==6)
- {
- nian--;
- if(nian<0)
- nian=99;
- }
- if(num1==7)
- {
- week--;
- if(week<1)
- week=7;
- }
- }
- }
- }
- }
-
- /**********************按键扫描程序******************************/
- void key()//按键扫描程序
- {
- uchar n1,n2;
- if(set==0)
- {
- num1++;
- flag1=1;
- }
- if(flag1==1)
- {
- if(num1==1)//秒闪烁
- {
- sfm_rst(0x97,0x90,0x8f,0x80); //清除秒位置字符
- sfm_rst(0x96,0x90,0x8e,0x80);
- for(n1=0;n1<250;n1++)
- {
- delay(1);
- jiajian();
- }
-
- datafl(miao);
- a1=0x96;
- a3=0x8e;
- lcd_disdata(sw);
- a1=0x97;
- a3=0x8f;
- lcd_disdata(gw);
- for(n2=0;n2<250;n2++)
- {
- delay(1);
- jiajian();
- }
- }
- if(num1==2)//分闪烁
- {
- sfm_rst(0x94,0x90,0x8c,0x80);
- sfm_rst(0x93,0x90,0x8b,0x80);
- for(n1=0;n1<250;n1++)
- {
- delay(1);
- jiajian();
- }
-
- datafl(fen);
- a1=0x93;
- a3=0x8b;
- lcd_disdata(sw);
- a1=0x94;
- a3=0x8c;
- lcd_disdata(gw);
- for(n2=0;n2<250;n2++)
- {
- delay(1);
- jiajian();
- }
- }
- if(num1==3)//时闪烁
- {
- sfm_rst(0x91,0x90,0x89,0x80);
- sfm_rst(0x90,0x90,0x88,0x80);
- for(n1=0;n1<250;n1++)
- {
- delay(1);
- jiajian();
- }
-
- datafl(shi);
- a1=0x90;
- a3=0x88;
- lcd_disdata(sw);
- a1=0x91;
- a3=0x89;
- lcd_disdata(gw);
- for(n2=0;n2<250;n2++)
- {
- delay(1);
- jiajian();
- }
- }
-
- if(num1==4)//日闪烁
- {
- lcd_addr(0x85);
- lcd_data(0xa1);
- lcd_data(0xa0);
- for(n1=0;n1<250;n1++)
- {
- delay(1);
- jiajian();
- }
-
- datafl(ri);
- lcd_addr(0x85);
- lcd_data(0x30+sw);
- lcd_data(0x30+gw);
- for(n2=0;n2<250;n2++)
- {
- delay(1);
- jiajian();
- }
- }
- if(num1==5)//月闪烁
- {
- lcd_addr(0x83);
- lcd_data(0xa1);
- lcd_data(0xa0);
- for(n1=0;n1<250;n1++)
- {
- delay(1);
- jiajian();
- }
-
- datafl(yue);
- lcd_addr(0x83);
- lcd_data(0x30+sw);
- lcd_data(0x30+gw);
- for(n2=0;n2<250;n2++)
- {
- delay(1);
- jiajian();
- }
- }
- if(num1==6)//年闪烁
- {
- lcd_addr(0x81);
- lcd_data(0xa1);
- lcd_data(0xa0);
- for(n1=0;n1<250;n1++)
- {
- delay(1);
- jiajian();
- }
-
- datafl(nian);
- lcd_addr(0x81);
- lcd_data(0x30+sw);
- lcd_data(0x30+gw);
- for(n2=0;n2<250;n2++)
- {
- delay(1);
- jiajian();
- }
- }
- if(num1==7)//周闪烁
- {
- lcd_addr(0x9a);
- lcd_data(0xa1);
- lcd_data(0xa0);
- for(n1=0;n1<250;n1++)
- {
- delay(1);
- jiajian();
- }
-
- datafl(week);
- week_disp();
- for(n2=0;n2<250;n2++)
- {
- delay(1);
- jiajian();
- }
- }
- if(num1>7)
- {
- if(set==1)
- {
- write_ds(0,miao); //秒数据写入DS12887
- write_ds(2,fen); //分数据写入DS12887
- write_ds(4,shi); //时数据写入DS12887
- write_ds(6,week);
-
- write_ds(7,ri);
- write_ds(8,yue);
- write_ds(9,nian);
- num1=0;
- flag1=0;
- }
- }
- }
- }
-
- void main(void)//主程序入口
- {
- lcd_init(); //LCD初始化
- lcd_clear(); //清除LCD绘图寄存器,解决花屏。
- ds_init(); //DS12887初始化
- lcd_disp(0x92,0x90,0x8a,0x80,tabm);//显示分前面的:号
- lcd_disp(0x95,0x90,0x8d,0x80,tabm);//显示分后面的:号
- nyrhz();//固定年月日汉字及自定义图标显示
- while(1)//调用显示
- {
- sfm_data();//调用时分秒数据处理及显示
- lyr_disp();//调用年月日周数据处理及显示
- ds1820_int(); //18B20初始化
- write_byte(0xcc);//写入跳过ROM指令(0xcc)
- write_byte(0x44); //发转换命令
- temp_disp();//读取温度值进行转换再显示程序
- key();//设置按键扫描
- }
- }
复制代码
|