- #include<reg52.h> //包含头文件
- #include<math.h>
- #define ui unsigned int
- #define uc unsigned char //宏定义
- sbit DQ =P3^7; //定义DS18B20总线I/O
- sbit LEDR=P1^2;
- sbit LEDG=P1^1;
- sbit LEDB=P1^0;
- bit bdata fuhao; //符号
- uc qian,bai,shi,ge; //读取温度值的千、百、十和个位(例如实际温度是123.4摄氏度,在程序里处理数据时会放大10倍,就是小数点右移一位,方便处理,就是处理的是1234)
- uc code led[] = {0x5F,0x44,0x9D,0xD5,0xC6,0xD3,0xDB,0x47,0xDF,0xD7}; //数码管对应的数字的段码
- uc code led_dian[] = {0x7f,0x64,0xbd,0xf5,0xe6,0xf3,0xfb,0x67,0xff,0xf7}; //有小数点的数字段码表
- uc m;
- uc NUM_R=0,NUM_G=0,NUM_B=0;
- uc DIS;
- ui zan=25;
- //============================================================================================
- //====================================DS18B20=================================================
- //============================================================================================
- /*****延时子程序*****/
- void Delay(int num)
- {
- while(num--) ; //num减占用系统资源,用于延时
- }
- /*****初始化DS18B20*****/
- void Init_DS18B20()
- {
- DQ = 1; //DQ复位,就是拉高电平
- Delay(8); //稍做延时
- DQ = 0; //单片机将DQ拉低
- Delay(80); //精确延时,大于480us
- DQ = 1; //拉高总线
- Delay(40); //延时
- }
- /*****读一个字节*****/
- uc ReadOneChar()
- {
- uc i=0;
- uc dat = 0; //定义变量用于循环和读取数据
- for (i=8;i>0;i--) //循环8次
- {
- DQ = 0; //拉低
- dat>>=1; //数据右移一位
- DQ = 1; //拉高
- if(DQ) //判断是否是高电平
- dat|=0x80; //是高电平的话,就让dat的最好为为1
- Delay(4); //延时
- }
- return(dat); //返回读取到的数据
- }
- /*****写一个字节*****/
- void WriteOneChar(uc dat)
- {
- uc i=0; //定义变量用于循环
- for (i=8; i>0; i--) //循环八次
- {
- DQ = 0; //低电平
- DQ = dat&0x01; //最低位是0的话,DQ就等于0;最低位是1的话,DQ就等于1
- Delay(5); //延时
- DQ = 1; //拉高
- dat>>=1; //右移一位
- }
- }
- /*****读取温度*****/
- ui ReadTemperature()
- {
- ui a=0,b=0,t=0;
- float tt=0; //定义读取温度变量
- Init_DS18B20(); //初始化18B20
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0x44); //启动温度转换
- Init_DS18B20(); //初始化18B20
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0xBE); //读取温度寄存器
- a=ReadOneChar(); //读低8位
- b=ReadOneChar(); //读高8位
- t=b; //高八位的数据提取到t
- t<<=8; //高八位数据左移八位
- t=t|a; //高位和低八位数据组成一个数据
- if(t&0xf800) //判断是否是负温度
- {
- t=~t+1; //将负温度值取反加一得到实际温度值
- fuhao=1; //符号位为负
- }
- else //如果是正温度
- fuhao=0; //符号位为正
- tt=t*0.0625; //乘以0.0625得到实际温度
- t=tt*10+0.5; //放大10倍输出并四舍五入
- return(t); //返回温度数据
- }
- /*****读取温度*****/
- void check_wendu()
- {
- ui f;
- // TR0=0;
- // zan=f;
- f=ReadTemperature(); //获取温度值并减去DS18B20的温漂误差
- // TR0=1;
- // if(abs(f-zan)>50) f=zan;
- qian=f/1000; //计算得到实际的百位数字
- bai=(f%1000)/100; //计算得到实际的十位数字
- shi=((f%1000)%100)/10; //计算得到实际的个位数字
- ge=((f%1000)%100)%10; //计算得到实际的小数位
- }
- /*****显示开机初始化等待画面*****/
- void Disp_init()
- {
- P0 = 0x7f; //显示----
- P2 = 0x7f;
- Delay(100);
- P2 = 0xdf;
- Delay(100);
- P2 = 0xf7;
- Delay(100);
- P2 = 0xfd;
- Delay(100);
- P2 = 0xff; //关闭显示
- }
- /*****显示温度子程序*****/
- void Disp_Temperature() //显示温度
- {
- if(qian==0) //千位等于0
- {
- if(fuhao==1) //是负温度
- P0=0x7f; //显示-
- else //是正温度
- P0=0xff; //不显示
- }
- else if(qian!=0) //千位不等于0
- P0 =~led[qian]; //显示千位数据
- P2 = 0xfd; //打开第一位位选
- Delay(10);
- P2 = 0xff; //关闭位选
- if((bai==0)&&(qian==0))//百位千位都是0
- P0=0xff; //不显示
- else if((bai!=0)||(qian!=0))//千位或者百位不等于0
- P0=~led[bai]; //正常显示百位数据
- P2=0xf7; //打开第二位
- Delay(10);
- P2 = 0xff; //关闭位选
- P0=~led_dian[shi]; //显示十位数据
- P2=0xdf; //打开第三位
- Delay(10);
- P2 = 0xff; //关闭位选
- P0=~led[ge]; //显示个位数据
- P2=0x7f; //打开第四位
- Delay(10);
- P2 = 0xff; //关闭位选
- }
- /*****主函数*****/
- void main()
- {
- uc z; //定义变量用于for循环
- for(z=0;z<100;z++) //循环100次读取温度并显示开机画面,防止开机显示85
- {
- Disp_init(); //开机初始化显示
- ReadTemperature();
- }
- while(1) //进入while循环
- {
- check_wendu(); //读取温度
- // Delay(20000);
- if(fuhao==0)
- {
- if((qian*100+bai*10+shi)>=0&&(qian*100+bai*10+shi)<10) {NUM_R=0; NUM_G=2; NUM_B=8;} //温度在0-10度之间,颜色:青色偏蓝,状态:寒冷
- else if((qian*100+bai*10+shi)>=10&&(qian*100+bai*10+shi)<20) {NUM_R=0; NUM_G=3; NUM_B=5;} //温度在10-20度之间,颜色:青色,状态:冷
- else if((qian*100+bai*10+shi)>=20&&(qian*100+bai*10+shi)<30) {NUM_R=0; NUM_G=5; NUM_B=0;} //温度在20-30度之间,颜色:绿色,状态:舒适
- else if((qian*100+bai*10+shi)>=30&&(qian*100+bai*10+shi)<35) {NUM_R=7; NUM_G=2; NUM_B=0;} //温度在30-35度之间,颜色:黄色,状态:热
- else if((qian*100+bai*10+shi)>=35) {NUM_R=10; NUM_G=0; NUM_B=0;} //温度在35度以上,颜色:红色,状态:炎热
- // if((qian*100+bai*10+shi)>=24&&(qian*100+bai*10+shi)<25) {NUM_R=0; NUM_G=2; NUM_B=8;} //温度在0-10度之间,颜色:青色偏蓝,状态:寒冷
- // else if((qian*100+bai*10+shi)>=25&&(qian*100+bai*10+shi)<26) {NUM_R=0; NUM_G=3; NUM_B=5;} //温度在10-20度之间,颜色:青色,状态:冷
- // else if((qian*100+bai*10+shi)>=26&&(qian*100+bai*10+shi)<27) {NUM_R=0; NUM_G=5; NUM_B=0;} //温度在20-30度之间,颜色:绿色,状态:舒适
- // else if((qian*100+bai*10+shi)>=27&&(qian*100+bai*10+shi)<28) {NUM_R=7; NUM_G=2; NUM_B=0;} //温度在30-35度之间,颜色:黄色,状态:热
- // else if((qian*100+bai*10+shi)>=28) {NUM_R=10; NUM_G=0; NUM_B=0;} //温度在35度以上,颜色:红色,状态:炎热
- // else if((qian*100+bai*10+shi)<24) {NUM_R=0;NUM_G=0;NUM_B=10;}
- }
- else //温度为负值,零下,颜色:蓝色,状态:冰冻
- {
- NUM_R=0;NUM_G=0;NUM_B=10;
- }
- for(z=0;z<10;z++) //显示10次
- {
- Disp_Temperature(); //调用显示函数
- m++;
- if(m<NUM_R) LEDR=0;
- else LEDR=1;
- if(m<NUM_G) LEDG=0;
- else LEDG=1;
- if(m<NUM_B) LEDB=0;
- else LEDB=1;
- if(m>=10) m=0;
- }
- }
- }
复制代码
|