使用DS18B20温度传感器采集温度,并将温度的值显示在LCD1602上,可以通过按键调整温度的阈值,当温度传感器的值在阈值之外,报警电路发出警报,在按键的时候可以将温度传感器的值数据保存在AT24C02中。可以通过串口将温度传感器的值上传到电脑的串口调试助手。
原理图如下:
单片机源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- #include"lcd1602.h"
- #include"key.h"
- #include"timer0.h"
- #include"at24c02.h"
- #include"uart.h"
- #include"nixie.h"
-
- typedef unsigned char uchar;
- typedef unsigned int uint;
-
- sbit Bus=P3^7;//数据单总线
- sbit LED=P3^6;//LED报警灯
-
- void Delay10us(void);//10us延时函数
- void Delay600us(void);//600us延时子函数
- void Delay(uint n);//LCD1602中延时子函数
- void Delay1ms(uint t);//t毫秒延时子函数
-
- void Init_Ds(void);//DS18B20初始化
- void Write_Ds(uchar com);//向DS18B20写入一字节
- uchar Read_Ds(void);//从DS18B20读出一字节
- uint Get_Tem(void);//获取温度值
-
- void Change(uint x);//把整型数值x转换为字符串
- void Write_com(uchar com);//写命令子函数
- void Write_dat(uchar dat);//写数据子函数
- void Init_1602(void);//LCD1602初始化子函数
- void Show(uchar x,uchar y,uchar *str);//LCD1602显示子函数
-
-
- uchar str[4];//储存转换值对应的字符串
- unsigned char KeyNum;
- char TLow,THigh;
- unsigned char t;
- unsigned char second=1;
- unsigned char minute;
- unsigned char hour;
- void main()
- {
- unsigned int temp;
- UART_Init(); //串口初始化
- LED=0;
- LCD_Init();
- // THigh=AT24C02_ReadByte(0); //读取温度阈值数据
- // TLow=AT24C02_ReadByte(1);
- if(THigh>125 || TLow<-55 || THigh<=TLow)
- {
- THigh=25; //如果阈值非法,则设为默认值
- TLow=20;
- }
- LCD_ShowString(2,1,"TH:");
- LCD_ShowString(2,9,"TL:");
- LCD_ShowSignedNum(2,4,THigh,3);
- LCD_ShowSignedNum(2,12,TLow,3);
- while(1)
- {
- KeyNum=Key();
- temp=Get_Tem();
- UART_SendByte(temp); //串口发送温度值
- if(temp>THigh) //越界判断
- {
- LED=1;
- }
- else if(temp<TLow)
- {
- LED=1;
- }
- else
- {
- LED=0;
- }
- Change(temp);
- LCD_ShowString(1,1,"Temperature:");
- LCD_ShowString(1,13,str);
-
- /*阈值判断及显示*/
- if(KeyNum)
- {
- if(KeyNum==1) //K1按键,THigh自增
- {
- THigh++;
- if(THigh>125){THigh=125;}
- }
- if(KeyNum==2) //K2按键,THigh自减
- {
- THigh--;
- if(THigh<=TLow){THigh++;}
- }
- if(KeyNum==3) //K3按键,TLow自增
- {
- TLow++;
- if(TLow>=THigh){TLow--;}
- }
- if(KeyNum==4) //K4按键,TLow自减
- {
- TLow--;
- if(TLow<-55){TLow=-55;}
- }
- LCD_ShowSignedNum(2,4,THigh,3); //显示阈值数据
- LCD_ShowSignedNum(2,12,TLow,3);
- AT24C02_WriteByte(0,temp); //写入到At24C02中保存
- Delay(20);
- AT24C02_WriteByte(1,THigh);
- Delay(20);
- AT24C02_WriteByte(1,TLow);
- Delay(20);
- }
-
- }
- }
-
- /***************************************延时函数体**************************/
- void Delay10us(void)//10us延时函数
- {
- unsigned char a,b;
- for(b=1;b>0;b--)
- for(a=1;a>0;a--);
- }
- void Delay600us(void)//600us延时函数
- {
- unsigned char a,b;
- for(b=119;b>0;b--)
- for(a=1;a>0;a--);
- }
- void Delay1ms(uint t)//t毫秒延时函数
- {
- unsigned char a,b;
- uint i;
- for(i=0;i<t;i++)
- for(b=199;b>0;b--)
- for(a=1;a>0;a--);
- }
-
- /********************************DS18B20初始化函数*************************/
- void Init_Ds(void)//DS18B20初始化
- {
- Bus=0;//主动拉低480-960us(此处选择600us)
- Delay600us();
- Bus=1;//释放总线,传感器15-60us后拉低总线
- while(Bus);//等待传感器拉低;
- while(!Bus);//度过传感器被拉低的时间(60-240us)后主动拉高
- Bus=1;//主动拉高
- }
- /********************************向DS18B20写入一字节***********************/
- void Write_Ds(uchar com)//从低位开始写入
- {
- uchar mask;
- for(mask=0x01;mask!=0;mask<<=1)
- {
- //该位为0,先拉低,15us后在拉高,并通过延时使整个周期为60us
- //该位为1,先拉低并在15us内(此处选择5us)拉高,并通过延时使整个周期为60us
- Bus=0;
- _nop_();_nop_();_nop_();_nop_();_nop_();//先拉低5us
- if((com&mask)==0)//该位是0
- {
- Bus=0;
- }
- else//该位是1
- {
- Bus=1;
- }
- Delay10us();Delay10us();Delay10us();Delay10us();Delay10us();;//延时60us
- _nop_();_nop_();_nop_();_nop_();_nop_();
- Bus=1;//拉高
- _nop_();_nop_();//写两个位之间至少有1us的间隔(此处选择2us)
- }
- }
- /********************************从DS18B20读出一字节***********************/
- uchar Read_Ds(void)//先读的是低位,整个读周期至少为60us,但控制器采样要在15us内完成,相邻“位”之间至少间隔1us
- {
- uchar value=0,mask;
- for(mask=0x01;mask!=0;mask<<=1)
- {
- Bus=0;//先把总线拉低超过1us(此处选择2us)后释放
- _nop_();_nop_();
- Bus=1;
- _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();//再延时6us后读总线数据
- if(Bus==0)//如果该位是0
- {
- value&=(~mask);
- }
- else
- {
- value|=mask;
- }
- Delay10us();Delay10us();Delay10us();Delay10us();Delay10us();//再延时52us,凑够至少60us的采样周期
- _nop_();_nop_();
- Bus=1;
- _nop_();_nop_();//写两个位之间至少有1us的间隔(此处选择2us)
- }
- return value;
- }
- /**********************************获取温度值函数***************************/
- uint Get_Tem(void)
- {
- uint temp=0;
- float tp;
- uchar LSB=0,MSB=0;
- Delay1ms(10);//延时10ms度过不稳定期
-
- Init_Ds();//Ds18b20初始化
- Delay1ms(1);
- Write_Ds(0xcc);//跳过ROM寻址
- Write_Ds(0x44);//启动一次温度转换
- Delay1ms(1000);//延时1s等待转化
-
- Init_Ds();//Ds18b20初始化
- Delay1ms(1);
- Write_Ds(0xcc);//跳过ROM寻址
- Write_Ds(0xbe);//发送读值命令·
- LSB=Read_Ds();
- MSB=Read_Ds();
- temp=MSB;
- temp<<=8;
- temp|=LSB;
- tp=temp*0.0625;
- temp=tp;
- if(tp-temp>=0.5)
- {
- temp+=1;
- }
- return temp;
- }
- /******************************把整型数据转换为字符串**********************/
- void Change(uint x)
- {
- str[0]=x/100+48;
- str[1]=(x/10)%10+48;
- str[2]=x%10+48;
- str[3]='\0';
- }
复制代码
仅供参考,如存在错误和不足之处,请大家回帖多多指教,切勿照搬,Keil代码下载:
代码.7z
(32.55 KB, 下载次数: 28)
|