最近花了近一個星期做了個時鐘,又花了近半月寫了個程序代碼,但還不是很完美,等待再一次升級。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();//設置按鍵掃描
- }
- }
復制代碼
|