DS18B20温度传感器
demo.c
/***************************************************************************** * 步骤: * 01、分文件把不同功能模块分开 * 02、定义管脚 * 03、定义temp.h文件,把一些全局参数和函数抽象出来,相当于接口 * 04、DS18B20初始化 * 05、DS18B20写数据 * 06、DS18B20读数据 * 07、DS18B20发送转换温度命令 * 08、DS18B20发送读取温度命令 * 09、DS18B20开始读取温度 * 10、处理温度数据(把温度数据包括负号拆分成数组用多个数码管显示) * 11、动态数码管显示温度 ******************************************************************************/ #include <reg52.h> #include "temp.h" // 138译码器管脚(动态数码管位选:即显示哪一个数码管) sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; // 动态数码管段选(即数码管显示什么数字) uchar code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; /***************************************************************************** * 用来保存温度数据,把温度 temp 拆分成数组:第0位是符号位(可正可负) * 第1/2/3位是整数位(0-125℃),第4/5位是小数位 ******************************************************************************/ uchar DisplayData[8]; /******************************************************************************* * 函 数 名 : Delay * 函数功能 : 延时函数,i=1时,大约延时10us *******************************************************************************/ void Delay(uint i) { while(i--); } /******************************************************************************* * 函 数 名 : DataPros * 函数功能 : 数据处理函数,把温度 temp 拆分成数组 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void DataPros(int temp) { float tp; // 温度 if(temp<0) // 如果温度为零下温度 { DisplayData[0]=0x40; // 负号- // 因为读取的温度是实际温度的补码,所以减1,再取反求出原码 temp-=1; temp=~temp; tp=temp; } else { DisplayData[0]=0x00; // 如果温度为正数,则去掉负号(即不显示) tp=temp; } /* 留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点 后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就 算加上0.5,还是在小数点后面 */ temp=tp*0.0625*100+0.5; DisplayData[1]=smgduan[temp/10000]; DisplayData[2]=smgduan[temp%10000/1000]; DisplayData[3]=smgduan[temp%1000/100]|0x80; // 0x80是小数点,对应七段码的dp管脚 DisplayData[4]=smgduan[temp%100/10]; DisplayData[5]=smgduan[temp%10]; } /******************************************************************************* * 函 数 名 : DigDisplay * 函数功能 : 在动态数码管上显示温度 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void DigDisplay() { uchar i; for(i=0; i<6; i++) { switch(i) { case(0): LSA=0; LSB=0; LSC=0; break; // 显示第0位 case(1): LSA=1; LSB=0; LSC=0; break; // 显示第1位 case(2): LSA=0; LSB=1; LSC=0; break; // 显示第2位 case(3): LSA=1; LSB=1; LSC=0; break; // 显示第3位 case(4): LSA=0; LSB=0; LSC=1; break; // 显示第4位 case(5): LSA=1; LSB=0; LSC=1; break; // 显示第5位 } P0=DisplayData[5-i]; // 单个数码管的数据 Delay(100); // 间隔一段时间扫描 P0=0x00; // 数码管消影 } } /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main() { while(1) { DataPros(Ds18b20ReadTemp()); // 读取温度,数据处理 DigDisplay(); // 显示温度 } }
temp.c
#include "temp.h" /******************************************************************************* * 函 数 名 : Delay1ms * 函数功能 : 延时函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Delay1ms(uint y) { uint x; for(; y>0; y--) { for(x=110; x>0; x--); } } /******************************************************************************* * 函 数 名 : Ds18b20Init * 函数功能 : 初始化 * 输 入 : 无 * 输 出 : 初始化成功返回1,失败返回0 *******************************************************************************/ uchar Ds18b20Init() { uchar i; DSPORT=0; // 拉低总线 // 延时642us,480us-960us范围都行 i=70; while(i--); DSPORT=1; // 拉高总线 i=0; // 复位i while(DSPORT) // 如果初始化成功,则Ds18b20会在15到60us之间返回0,失败则返回1 { Delay1ms(1); i++; if(i>5) // 如果初始化失败,开始计数,5ms后自动返回0 { return 0; // 初始化失败 } } return 1; // 初始化成功 } /******************************************************************************* * 函 数 名 : Ds18b20ReadByte * 函数功能 : 读取一个字节 * 输 入 : 无 * 输 出 : uchar *******************************************************************************/ uchar Ds18b20ReadByte() { uchar tmp, dat; uint i, j; for(i=0; i<8; i++) { DSPORT=0; // 将数据线拉低“0” j++; // 延迟1us DSPORT=1; // 将数据线拉高“1”,释放总线准备读数据 // 延时6us等待数据稳定 j++; j++; tmp=DSPORT; // 读数据线的状态得到1个状态位,并进行数据处理 // 先把dat右移1位,腾出最高位,再把tmp左移7位,留下最后一位x,相或后,x就变成了dat的最高位 dat=(dat>>1)|(tmp<<7); // 读取完之后等待48us再接着读取下一个数 j=4; while(j--); } return dat; // 返回读取的字节数据 } /******************************************************************************* * 函 数 名 : Ds18b20WriteByte * 函数功能 : 向18B20写入一个字节 * 输 入 : dat * 输 出 : 无 *******************************************************************************/ void Ds18b20WriteByte(uchar dat) { uint i, j; for(i=0; i<8; i++) { DSPORT=0; // 数据线先置低电平“0” j++; DSPORT=dat&0x01; // 和0x01相与,最后一位由dat的最后一位来决定,0就是0,1就是1,其他位均为0 // 延时68us,持续时间最少60us j=6; while(j--); DSPORT=1; // 将数据线拉到高电平 dat>>=1; // 最后一位已经写入,移出去,为下一次写入做准备 } } /******************************************************************************* * 函 数 名 : Ds18b20ChangTemp * 函数功能 : 让18b20发出转换温度的命令 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds18b20ChangTemp() { Ds18b20Init(); // 初始化 Delay1ms(1); // 延迟1ms Ds18b20WriteByte(0xcc); // 跳过ROM操作命令 Ds18b20WriteByte(0x44); // 温度转换命令 //Delay1ms(100); // 等待转换成功,而如果你是一直刷着的话,就不用这个延时了 } /******************************************************************************* * 函 数 名 : Ds18b20ReadTempCom * 函数功能 : 发送读取温度命令 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds18b20ReadTempCom() { Ds18b20Init(); // 初始化 Delay1ms(1); // 延迟1ms Ds18b20WriteByte(0xcc); // 跳过ROM操作命令 Ds18b20WriteByte(0xbe); // 发送读取温度命令 } /******************************************************************************* * 函 数 名 : Ds18b20ReadTemp * 函数功能 : 读取温度 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ int Ds18b20ReadTemp() { int temp=0; // 温度临时变量 uchar tml, tmh; // tml,tmh分别是温度数据的低8位和高8位,温度数据由两个字节构成,共16位 Ds18b20ChangTemp(); // Ds18b20发出温度转换命令 Ds18b20ReadTempCom(); // 发送读取温度命令 tml=Ds18b20ReadByte(); // Ds18b20中低8位在前,高8位在后,所以先读低8位 tmh=Ds18b20ReadByte(); // 再读高8位 temp=tmh; // 因为高8位的前5位是符号位(+/-),所以先处理高8位 temp<<=8; // 先把temp的16位中的前8位移出(因为初始化时高8位均为0,变成:tmh00000000) temp|=tml; // 再和低8位相或,变成:tmhtml return temp; // 返回完整的温度 }
temp.h
/***************************************************************************** * 这里定义和 DS18B20 温度传感器相关的参数, * 这个 .h 文件只定义标准参数,全局参数,相当于 Java 中的接口 ******************************************************************************/ #ifndef _TEMP_H_ #define _TEMP_H_ #include <reg52.h> #ifndef uint #define uint unsigned int #endif #ifndef uchar #define uchar unsigned char #endif // DS18B20 温度传感器管脚 sbit DSPORT=P3^7; // 定义函数 uchar Ds18b20Init(); // Ds18b20 初始化 uchar Ds18b20ReadByte(); // Ds18b20 读数据 void Ds18b20WriteByte(uchar dat); // Ds18b20 写数据 void Ds18b20ChangTemp(); // Ds18b20 发送转换温度命令 void Ds18b20ReadTempCom(); // Ds18b20 发送读取温度命令 int Ds18b20ReadTemp(); // Ds18b20 开始读取温度 void Delay1ms(uint i); // 延迟1ms #endif
实验结果: