源码预览:
- //#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;
- }
- }
- }
复制代码 |