蓝桥杯 模板Template Part7:DS18B20温度传感器
改编自国信长天蓝桥杯官方蓝皮书例程,按照自己的习惯进行了补充和修改 改单总线延时函数读一次温度需要对DS18B20操作两次:转换温度和读暂存器。 ●对DS18B20的每次操作包括三步○初始化ROM命令功能命令常用ROM命令:0XCC 跳过ROM常用功能命令:0X44 转换温度和0XBE 读暂存器读取温度时数码管会闪烁的原因消除85显示12位分辨率的精度为0.0625,最大转换时间为750ms。

蓝桥杯 模板Template Part7:DS18B20温度传感器
● 改编自国信长天蓝桥杯官方蓝皮书例程,按照自己的习惯进行了补充和修改
【蓝桥杯】—{模块}—{DS18B20温度传感器Part_1}
【蓝桥杯】—{模块}—{DS18B20温度传感器Part_2}
一、基本模板
1、头文件
//-------------------------------------DS18B20温度采集函数---------------------------//
sbit DQ = P1^4; //单总线接口
extern uint ui_temperature; //保存温度数据
uint rd_temperature(void); //DS18B20温度采集函数
2、改单总线延时函数
官方提供的驱动如下:
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
while(t--);
}
改为:
//单总线延时函数
void Delay_OneWire(unsigned int t)
{
t=t*12;
while(t--);
}
3、写温度采集函数rd_temperature()
//-------------------------------------DS18B20温度采集函数---------------------------//
uint rd_temperature(void)
{
uchar low=0,high=0;
uint Temp = 0 ;
init_ds18b20(); //初始化
Write_DS18B20(0XCC); //跳过ROM
Write_DS18B20(0X44); //转换温度
init_ds18b20(); //初始化
Write_DS18B20(0XCC); //跳过ROM
Write_DS18B20(0XBE); //读暂存器
low = Read_DS18B20(); //低字节
high = Read_DS18B20(); //高字节
Temp = (high<<8)+low;
return Temp;
}
Notes:
●读一次温度需要对DS18B20操作两次:转换温度和读暂存器。
●对DS18B20的每次操作包括三步:
○初始化
○ROM命令
○功能命令
●常用ROM命令:0XCC 跳过ROM
●常用功能命令:0X44 转换温度和0XBE 读暂存器
4、温度的读取与显示
在整个系统中,DS18B20一般只是一个功能部分,而且显示器件只有数码管,所以,温度在数码管上的显示一般由按键控制:按下某个按键,(进入某个状态),数码管才显示温度数值。所以温度的读取函数rd_temperature()
再按下某个按键后再进行读取。
进入某个状态放在按键控制层 按键处理函数Key_Proc()
中,温度的读取ui_temperature = rd_temperature();
放在数码管显示层 数码管处理函数SEG_Proc()
中。
//-----------------------------------------数码管处理函数---------------//
void SEG_Proc(void) //数码管处理函数
{
if(ui_SEG_flag) return; //刷新频率
ui_SEG_flag = 1;
if(uc_Key_Value == 4)
{
ui_temperature = rd_temperature(); //读取温度
sprintf(puc_SEG_Buf,"%02u %05.2f",(uint)uc_Key_Value,ui_temperature/16.0);
}
SEG_Tran(puc_SEG_Buf,puc_SEG_Code); //数码管段码转换
}
Notes:
●ui_temperature/16.0
DS18B20配置为12位分辨率,温度数据以16位符号扩展的二进制补码 形式存储在暂存器低两位的温度寄存器中。ui_temperature
默认为16位二进制数,又因为温度为正,符号位为0,所以读回来的ui_temperature
为11位二进制原码。
/为除法运算符,被除数/除数。除法运算又分为整数除法和浮点数除法。整数除法小数部分被丢弃,即截断。只要被除数和除数有一个为浮点数即为浮点数除法。
ui_temperature/16.0
等价于 ui_temperature/0.0625
等价于 ui_temperature*
2 − 4 2^{-4} 2−4。
ui_temperature
定义的为无符号整形,ui_temperature
的BIT 0 位的权重为1。对比下表可知,ui_temperature
每一个位的权重都比实际大了 2 4 2^{4} 24,所以需要ui_temperature/16.0
。
●sprinft
通过格式控制指定小数位数输出,可以实现四舍五入。
●读取温度时数码管会闪烁的原因:rd_temperature()
中的初始化,读写函数中的延时每次虽然是us级别的,但是加起来大约在5、6ms左右。
可以通过控制数码管的刷新频率,如500ms刷新一次,即500ms执行一次SEG_Proc()
,也就是500ms读取一次温度来减弱数码管的闪动。
●12位分辨率的精度为0.0625,最大转换时间为750ms。写入Write_DS18B20(0X44);
开始温度转换后,就由DS18B20的相关硬件部分去执行温度转换,转换完成后存放在暂存器的低两位字节中;若不进行初始化直接读取时序,如果DS18B20正在温度转换过程中则返回0来响应,若转换完成则返回1。主机可以对DS18B20进行其他操作,由DS18B20的其他硬件部分响应;主机若对DS18B20进行其他操作,必须由初始化开始。
在执行第二个初始化时,转换温度的命令已经写入DS18B20,虽然温度还未转换完成,但是单总线已经空闲,可以继续执行下边几乎不耗时的读暂存器命令。所以在上电之初,会出现短暂的85初始值。
5、温度传感器DS18B20上电初始值为85的消除方法
方法1:在数码管处理函数中:
if( (ui_temperature/16.0) == 85.0)
sprintf(puc_SEG_Buf," ");
else
sprintf(puc_SEG_Buf,"C %02.0f",(float)ui_temperature/16.0);
方法2:在死循环之前:
uchar puc_SEG_Code[8]= {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
void main(void)
{
Init();
Timer1Init();
UartInit();
temperature = rd_temperature()/16.0;
while(temperature == 85.0)
{
temperature = rd_temperature()/16.0;
}
//最后开中断
ET1 = 1;
EA = 1;
while(1)
{
……
……
方法3:在死循环之前直接先读取一次温度,之后直接软件延时750ms,虽然简单,却是最没有bug的方法。
ui_temperature = rd_temperature();
Delay750ms();
ui_temperature = rd_temperature();
二、备用拓展模板
1、分辨率的更改
选项 | 12位分辨率 | 11位分辨率 | 10位分辨率 | 9位分辨率 |
---|---|---|---|---|
小数部分位数 | 4位 | 3位 | 2位 | 1位 |
分辨率 | 1/16 = 0.0625 | 1/8 = 0.125 | 1/4 = 0.25 | 1/2 = 0.5 |
最大转换时间 | 750ms | 375ms | 187.5ms | 93.75ms |
配置寄存器 | 0x7f | 0x5f | 0x3f | 0x1f |
void DS18B20_Set_Reso(uchar Reso)
{
//12位分辨率 0111 1111 7f
//11位分辨率 5f
//10位分辨率 3f
//9位分辨率 1f
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0X4E); //写暂存器
Write_DS18B20(0x00); //写TH
Write_DS18B20(0x00); //写TL
Write_DS18B20(Reso); //配置寄存器
}
更多推荐
所有评论(0)