开始 发DS18B20复位命令
发跳过ROM命令 初始化 获取温度值 发读取温度命令 读取操作,CRC校验 与温度上下限比较 YES 报警 Y N 9字节完? Y CRC校验正?N 转换并显示 移入温度暂存器
结束
图21主程序流程图 图22读温度流程图
4.2开机数码管显示设置
/*****显示开机初始化等待画面*****/ Disp_init() {
P2 = 0xfe; //显示- P0 = 0xbf; Delay(200); P0 = 0xef; Delay(200); P0 = 0xfb; Delay(200); P0 = 0xfe; Delay(200);
P0 = 0xff; //关闭显示 }
给单片机上电后,18B20读取温度值需要一定的时间,故上数码管显示一定时间的“-”。
4.3 DS18B20采集温度程序
#define DQ P3_4 //定义DS18B20总线I/O
21
/*****延时子程序*****/
void Delay_DS18B20(int num) {
while(num--) ; }
/*****初始化DS18B20*****/ void Init_DS18B20(void) {
unsigned char x=0;
DQ = 1; //DQ复位
Delay_DS18B20(8); //稍做延时 DQ = 0; //单片机将DQ拉低
Delay_DS18B20(80); //精确延时,大于480us DQ = 1; //拉高总线 Delay_DS18B20(14);
x = DQ; //稍做延时后,如果x=0则初始化成功,x=1则初始化失败 Delay_DS18B20(20); }
/*****读一个字节*****/
unsigned char ReadOneChar(void) {
unsigned char i=0; unsigned char dat = 0; for (i=8;i>0;i--) {
DQ = 0; // 给脉冲信号 dat>>=1;
DQ = 1; // 给脉冲信号 if(DQ) dat|=0x80;
Delay_DS18B20(4); }
return(dat); }
/*****写一个字节*****/
void WriteOneChar(unsigned char dat) {
unsigned char i=0; for (i=8; i>0; i--) {
DQ = 0;
DQ = dat&0x01; Delay_DS18B20(5); DQ = 1;
22
dat>>=1; } }
/*****读取温度*****/
unsigned int ReadTemperature(void) {
unsigned char a=0; unsigned char b=0; unsigned int t=0; float tt=0; Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作 WriteOneChar(0x44); //启动温度转换 Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作 WriteOneChar(0xBE); //读取温度寄存器 a=ReadOneChar(); //读低8位 b=ReadOneChar(); //读高8位 t=b; t<<=8; t=t|a;
tt=t*0.0625;
t= tt*10+0.5; //放大10倍输出并四舍五入 return(t); }
/*****END*****/
读取18B20的程序,需要单片机发送读命令和写命令。 读出温度子程序的主要功能是读出RAM中的9字节,在读出时需进行CRC校验,校验有错时不进行温度数据的改写。其程序流程图如图18示
发DS18B20复位命令
发跳过ROM命令
发温度转换开始命令
结束
图23温度转换流程图
4.4读取温度程序
23
/*****读取温度*****/ void check_wendu(void) {
uint a,b,c;
c=ReadTemperature()-5; //获取温度值并减去DS18B20的温漂误差 a=c/100; //计算得到十位数字 b=c/10-a*10; //计算得到个位数字 m=c/10; //计算得到整数位
n=c-a*100-b*10; //计算得到小数位 if(m<0){m=0;n=0;} //设置温度显示上限
if(m>99){m=99;n=9;} //设置温度显示上限 }
读取的18B20程序需要转换出要显示的温度值。 4.5显示温度程序
/*****显示温度子程序*****/
Disp_Temperature() //显示温度 {
P2 =0x27; //显示C P0 = 0xfe; Delay(300);
P2 =LEDData[n]; //显示个位 P0 = 0xfb; Delay(300);
P2 =LEDData[m]; //显示十位 DIAN =0; //显示小数点 P0 = 0xef; Delay(300);
P2 =LEDData[m/10]; //显示百位 P0 = 0xbf; Delay(300);
P0 = 0xff; //关闭显示 }
/*****显示报警温度子程序*****/ Disp_alarm(uchar baojing) {
P2 =0x27; //显示C P0 = 0xfe; Delay(200);
P2 =LEDData[baojing]; //显示十位 P0 = 0xfb; Delay(200);
P2 =LEDData[baojing/10]; //显示百位 P0 = 0xef; Delay(200);
24
if(set_st==1)P2 =0x8c;
else if(set_st==2)P2 =0xa7; //上限H、下限L标示 P0 = 0xbf; Delay(200);
P0 = 0xff; //关闭显示 }
根据数码管和单片机管脚的连接顺序,算出P2口发送的数据为LEDData[]={0x28,0xeb,0x32,0xa2,0xe1,0xa4,0x24,0xea,0x20,0xa0};分别对应0 1 2 3 4 5 6 7 8 9.
5.调试过程
5.1数码管显示乱码
由于P2口的P2.0到P2.7并没有按照顺序和数码管的a,b,c,d,e,f,g相连,所以需要重新编码,因为用的是共阳数码管,所以数据端低电平亮,故
LEDData[]={0x28,0xeb,0x32,0xa2,0xe1,0xa4,0x24,0xea,0x20,0xa0}; 。 5.2 按键处理问题
由于按键采用的是机械按键,会发生抖动,所以程序中要加延时,去抖动。 5.3 DS18B20时序问题
DS18B20对于时序要求很严格,所以读写数据时要严格按照时序图上的时间来编写程序。
6.结论
本文详细讲述了系统设计方案,并给出了相关程序流程。本设计应用性比较强,可以应用在仓库温度、大棚温度、机房温度等的监控。另外,如果把本设计方案扩展为多点温度控制,加上上位机,则可以实现远程温度监控系统,将具有更大的应用价值。
本文的创新点在于详细设计了基于单片机AT89C51的温度监控系统,并且已经在硬件平台上成功运行.此系统可广泛用于温度在DSl8820测温范围之内的场合,有良好的应用前景。
25