源碼預覽:
- //#include <at89x52.h>
- #include <intrins.h>
- #include <STC89C5xRC.H>
- #define DataPort P0
- unsigned char code one[] = "20 / / "; //固定字符
- unsigned char code two[] = " : : "; //固定字符
- unsigned char code wendu[] = {0x18, 0x1a, 0x05, 0x04, 0x04, 0x05, 0x02, 0x00};//溫度符號
- unsigned char code week_char[] = "MON TUE WED THU FRI STA SUN"; //星期字符串
- unsigned char miao, fen, shi, ri, yue, nian, week;
- unsigned int tp;
- bit time_flag, temp_flag;
- /******************************
- LCD1602
- 4PIN----RS
- 5PIN----RW
- 6PIN----EN
- *****************************/
- sbit beep = P1^0; //蜂鳴器
- sbit DQ = P3^7; //18B20端口
- sbit RS = P2^4; //1602寄存器選擇
- sbit RW = P2^5; //1602讀寫控制
- sbit EN = P2^6; //1602使能端
- sbit key1 = P3^1; //菜單鍵
- sbit key2 = P3^2; //加
- sbit key3 = P3^3; //減
- sbit RST = P3^5; //1302復位
- sbit SDA = P3^4; //1302數據
- sbit SCK = P3^6; //1302時鐘
- void delay_us(unsigned char t)
- {
- while(--t);
- }
- /***********ms延時程序***********/
- void delay_ms(unsigned int ms)
- {
- unsigned int a, b;
- for(a = ms; a > 0; a--)
- for(b = 110; b > 0; b--);
- }
- /********蜂鳴器響一聲**********/
- void beepplay()
- {
- beep = 0;
- delay_ms(60);
- beep = 1;
- }
- /*********LCD判忙*************/
- void lcd_busy()
- {
- DataPort = 0xff;
- RS = 0;
- RW = 1;
- EN = 1;
- delay_ms(1);
- while(DataPort & 0x80);
- EN = 0;
- }
- /**********LCD寫數據************/
- void write_date(unsigned char dat)
- {
- lcd_busy();
- RS = 1;
- RW = 0;
- DataPort = dat;
- delay_ms(2);
- EN = 1;
- delay_ms(2);
- EN = 0;
- }
- /*********LCD寫指令***********/
- void write_com(unsigned char com)
- {
- lcd_busy();
- RS = 0;
- RW = 0;
- DataPort = com;
- delay_ms(2);
- EN = 1;
- delay_ms(2);
- EN = 0;
- }
- /*********LCD初始化*************/
- void initLCD()
- {
- unsigned char i;
- delay_ms(5); //延時啟動,等待電壓穩定
- write_com(0x38); //設置16*2顯示,5*7點陣,8位數據口
- write_com(0x0c); //設置開顯示,不顯示光標
- write_com(0x06); //寫一個字符地址指針加1
- write_com(0x01); //清屏
- delay_ms(1); //第一行起始地址0x80,第二行起始地址0xc0
- write_com(0x81); //第一行首空一個字符,開始寫入第一行固定字符
-
- for(i = 0; i < 10; i++)
- write_date(one[ i]);
- delay_ms(1);
- write_com(0xc2); //第二行首空兩個字符,開始寫入第二行的固定字符
-
- for(i = 0; i < 8; i++)
- write_date(two[ i]);
- write_com(0xcd); //顯示地址
- write_date('.'); //顯示"."
- write_date(0x20); //0x20顯示就是空
- // write_date('C'); //顯示C
-
- write_com(0x40);
- for(i = 0; i < 8; i++)
- write_date(wendu[ i]);
- write_com(0xcf);
- write_date(0x00);
- }
- /*********10轉BCD**********/
- unsigned char toBCD(unsigned char dat)
- {
- unsigned char tmp;
- tmp=(((dat / 10) * 16)+(dat % 10));
- return(tmp);
- }
- /**********DS1302寫一個字節*********/
- void writebyte(unsigned char dat)
- {
- unsigned char i;
- for(i = 0; i < 8; i++)
- {
- SDA = dat & 0x01;
- SCK = 1;
- _nop_();_nop_();
- SCK = 0;
- dat >>= 1;
- }
- }
- /********寫DS1302寄存器********/
- void write1302(unsigned char dizhi,shuju)
- {
- RST = 0;
- SCK = 0;
- RST = 1;
- writebyte(dizhi); //寫入的地址
- writebyte(shuju); //寫入的數據
- SCK = 1;
- RST = 0;
- }
- /*******讀取DS1302寄存器********/
- unsigned char read1302(unsigned char dizhi)
- {
- unsigned char i, dat, tmp;
- RST = 0;
- SCK = 0;
- RST = 1;
- writebyte(dizhi | 0x01);
- for(i = 8; i > 0; i--)
- {
- dat >>= 1;
- if(SDA)
- dat |= 0x80;
- SCK=1;
- _nop_();_nop_();
- SCK=0;
- }
- RST = 0;
- tmp = dat >> 4;
- tmp = ((tmp * 10)+(dat &= 0x0f));
- return(tmp);
- }
- /*******DS18B20初始化*********/
- void init1820()
- {
- DQ = 1;
- _nop_();_nop_();
- DQ = 0;
- delay_us(200);
- delay_us(200);
- DQ = 1;
- delay_us(80);
- DQ = 1;
- }
- /*******向DS18B20中讀出一個字節*********/
- unsigned char readonebyte_18b20()
- {
- unsigned char i=0, dat=0;
- for(i = 8; i > 0; i--)
- {
- DQ = 0;
- dat >>= 1;
- DQ = 1;
- if(DQ)
- dat |= 0x80;
- delay_us(25);
- }
- return(dat);
- }
- /******向DS18B20中寫入一個字節*******/
- void writeonebyte_18b20(unsigned char dat)
- {
- unsigned char i=0;
- for(i = 8; i > 0; i--)
- {
- DQ = 0;
- DQ = dat & 0x01;
- delay_us(25);
- DQ = 1;
- dat >>= 1;
- }
- delay_us(25);
- }
- /*********讀取溫度*********/
- unsigned int readtemp(void)
- {
- unsigned int xx, tempL=0, tempH=0;
- init1820();
- writeonebyte_18b20(0xcc);
- writeonebyte_18b20(0x44);
- delay_us(100);
- init1820();
- writeonebyte_18b20(0xcc);
- writeonebyte_18b20(0xbe);
- tempL = readonebyte_18b20();
- tempH = readonebyte_18b20();
- tempH <<= 8;
- xx = tempL | tempH;
- return(xx);
- }
- /********顯示函數*********/
- void display(unsigned char dizhi, dat)
- {
- unsigned char a, b;
- a = dat / 10; //取得十位數字
- b = dat % 10; //取得個位數字
- write_com(dizhi); //設定顯示的地址
- write_date(a + 0x30); //數字+0x30得到該數字的LCD1602顯示碼
- write_date(b + 0x30);
- }
- /***********溫度顯示函數**************/
- void display_wendu(unsigned char dizhi, dat)
- {
- write_com(dizhi);
- write_date(dat);
- }
- /**********顯示周字符**********/
- void display_week(unsigned char week)
- {
- unsigned char i;
- write_com(0x8d); //設置星期顯示地址
- switch(week)
- {
- case 1: for(i = 0; i < 3; i++)
- write_date(week_char[ i]);break;
- case 2: for(i = 4; i < 7; i++)
- write_date(week_char[ i]);break;
- case 3: for(i = 8; i < 11; i++)
- write_date(week_char[ i]);break;
- case 4: for(i = 12; i < 15; i++)
- write_date(week_char[ i]);break;
- case 5: for(i = 16; i < 19; i++)
- write_date(week_char[ i]);break;
- case 6: for(i = 20; i < 23; i++)
- write_date(week_char[ i]);break;
- case 7: for(i = 24; i < 27; i++)
- write_date(week_char[ i]);break;
- }
- }
- /*********按鍵掃描********/
- void keyscan()
- {
- unsigned char num;
- if(key1 == 0) //判斷key1是不是按下
- {
- delay_ms(20); //按鍵消抖
- if(key1 == 0) //再次檢測key1是否按下
- {
- beepplay();
- while(!key1); //等待key1釋放
- num++;
- switch(num)
- {
- case 1: TR0 = 0; //關閉中斷
- temp_flag = 0;
- time_flag = 0;
- write1302(0x8e, 0x00); //允許寫入DS1302
- write1302(0x80, 0x80); //時間暫停
- write_com(0x0f); //設置光標閃爍
- write_com(0xc9);break; //秒鐘閃爍地址
- case 2: write_com(0xc6);break; //分閃爍地址
- case 3: write_com(0xc3);break; //時閃爍地址
- case 4: write_com(0x8f);break; //星期閃爍地址
- case 5: write_com(0x8a);break; //日閃爍地址
- case 6: write_com(0x87);break; //月閃爍地址
- case 7: write_com(0x84);break; //年閃爍地址
- case 8: write_com(0x0c); //設置光標不閃爍
- write1302(0x90,0xa9); //充電
- write1302(0x8c, toBCD(nian));
- write1302(0x86, toBCD(ri));
- write1302(0x88, toBCD(yue));
- write1302(0x8a, toBCD(week));
- write1302(0x84, toBCD(shi));
- write1302(0x82, toBCD(fen));
- write1302(0x80, toBCD(miao)); //寫入秒
- write1302(0x8e, 0x80); //禁止寫入DS1302
- num = 0;TR0 = 1;break; //定時器打開計數清零
- }
- }
- }
- if(num != 0) //i>0,按鍵key2,key3無效
- {
- if(key2 == 0)
- {
- delay_ms(20);
- if(key2 == 0)
- {
- beepplay();
- while(!key2); //等待釋放
- switch(num)
- {
- case 1: miao++;if(miao >= 60)miao = 0; //秒++
- display(0xc8, miao); //顯示秒
- write_com(0xc9);break; //因為顯示地址指針自動加1,重新定義秒的地址
- case 2: fen++;if(fen == 60)fen = 0; //分++
- display(0xc5, fen); //顯示當前調入分數據
- write_com(0xc6);break;
- case 3: shi++;if(shi == 24)shi = 0;
- display(0xc2, shi);
- write_com(0xc3);break;
- case 4: week++;if(week == 8)week = 1;
- display_week(week);
- write_com(0x8f);break;
- case 5: ri++;if(ri == 32)ri = 1;
- display(0x89, ri);
- write_com(0x8a);break;
- case 6: yue++;if(yue == 13)yue = 1;
- display(0x86, yue);
- write_com(0x87);break;
- case 7: nian++;if(nian == 100)nian = 0;
- display(0x83, nian);
- write_com(0x84);break;
- }
- }
- }
- if(key3==0) //按鍵0有效,判斷key3按下是不是0
- {
- delay_ms(20); //按鍵消抖
- if(key3==0)
- {
- beepplay(); //調用蜂鳴器響一聲
- while(!key3); //等待釋放key3
- switch(num)
- {
- case 1: miao--;if(miao == 255 | miao > 60)miao = 59; //減1,減到0再減1就是255
- display(0xc8, miao);
- write_com(0xc9);break;
- case 2: fen--;if(fen == 255)fen = 59;
- display(0xc5, fen);
- write_com(0xc6);break;
- case 3: shi--;if(shi == 255)shi = 23;
- display(0xc2, shi);
- write_com(0xc3);break;
- case 4: week--;if(week == 0)week = 7;
- display_week(week);
- write_com(0x8f);break;
- case 5: ri--;if(ri == 0)ri = 31;
- display(0x89, ri);
- write_com(0x8a);break;
- case 6: yue--;if(yue == 0)yue = 12;
- display(0x86, yue);
- write_com(0x87);break;
- case 7: nian--;if(nian == 255)nian = 99;
- display(0x83, nian);
- write_com(0x84);break;
- }
- }
- }
- }
- }
- /***********更新時間***********/
- void update_time()
- {
- if(time_flag == 1)
- {
- time_flag = 0;
- miao = read1302(0x81); //讀秒
- fen = read1302(0x83); //讀分
- shi = read1302(0x85); //讀時
- ri = read1302(0x87); //讀日
- yue = read1302(0x89); //讀月
- week = read1302(0x8b); //讀周
- nian = read1302(0x8d); //讀年
- display(0xc8, miao); //更新秒
- display(0xc5, fen); //更新分
- display(0xc2, shi); //更新時
- display(0x89, ri); //更新日
- display(0x86, yue); //更新月
- display(0x83, nian); //更新年
- display_week(week); //更新周
- }
- }
- /**********更新溫度*********/
- void update_temp()
- {
- unsigned int temp;
- if(temp_flag == 1)
- {
- temp_flag = 0;
- temp = readtemp();
- tp = temp;
- if(tp & 0x8000)
- tp = (~tp)+1;
- tp = ((tp * 5) >> 3);
- if(temp & 0x8000)
- {
- display_wendu(0xcb, '-');
- display_wendu(0xcc, (tp % 100 / 10) + 0x30);
- display_wendu(0xce, (tp % 10) + 0x30);
- }
- else
- {
- if((tp / 100 % 10) == 0)
- display_wendu(0xcb, 0x20);
- else
- display_wendu(0xcb, (tp / 100 % 10) + 0x30);
- display_wendu(0xcc, (tp % 100 / 10) + 0x30);
- display_wendu(0xce, (tp % 10) + 0x30);
- }
- }
- }
- /********定時器初始化************/
- void init_Time0()
- {
- TMOD = 0x01; //設置定時器工作模式
- TH0 = 0;
- TL0 = 0;
- EA = 1; //開總中斷
- ET0 = 1; //開定時器0中斷
- TR0 = 1; //啟動定時器
- }
- /**********主函數*************/
- void main()
- {
- initLCD(); //初始化LCD
- init_Time0(); //初始化定時器
- while(1)
- {
- keyscan(); //鍵盤掃描
- update_time(); //更新時間
- update_temp(); //更新溫度
- }
- }
- /************中斷程序***************/
- void Time0()interrupt 1 //中斷程序不易過多
- {
- static unsigned char x, y;
- TH0 = (65536-10000) / 256; //賦值10ms
- TL0 = (65536-10000) % 256;
- x++;
- if(x == 10)
- {
- x = 0; y++;
- time_flag = 1;
- if(y == 5)
- {
- y = 0;
- temp_flag = 1;
- }
- }
- }
復制代碼 |