基本知识
DS13B20是用于OneWire协议进行通信的,在比赛中提供了OneWire和DS13B20的底层代码,我们只需根据数据手册的时序图写一个读取温度的函数。
DS13B20概述:
工作电压:3.0V~5.5V。
测量范围:-55摄氏度~+125摄氏度。
通信方式:单总线,数据线接上拉电阻,使总线空闲时处于高电平。
转换精度:9~12位分辨率可调,默认为12位,即分辨率是0.0625。
转换时间:典型值200ms
编程思路
步骤:
- DS13B20复位:通过提供的驱动程序中的init_ds18b20对DS13B20进行初始化。
- 写入字节0XCC:这是跳过ROM指令操作,由于蓝桥杯开发板上只有一个DS18B20,无需匹配ID,所以跳过此过程,直接进行温度转换。
- 写入字节0x44:开始温度转换指令。
- 再次复位D13B20.
- 跳过ROM指令。
- 写入0XBE,读取高速暂存器:温度转换完之后,数据存放在高度暂存器的第1和第0字节,存储区一共有九个字节。
- 读取暂存器中的第0 字节(LSB)和第1字节(MSB):存放在暂存器中的数据有16位,Low与High分别存放高八位以及低八位。
- DS13B20复位,告诉DS18B20数据读取结束。
最后将Low,High转换为16进制,再转化为浮点数据。
//需要自己完成读取DS18B20温度的程序
float fRead_Temperature(void)
{
float temp_return;
u8 low,high;
init_ds18b20();
Write_DS18B20(0xcc); //跳过读取ROM
Write_DS18B20(0x44); //启动温度转换
//不加上Delay延时,等待温度转换完成,直接去读取暂存器
init_ds18b20();
Write_DS18B20(0xcc); //跳过读取ROM
Write_DS18B20(0xbe); //获取暂存器数据
low = Read_DS18B20(); //温度低8位数据
high = Read_DS18B20(); //温度高8位数据
temp_return = (high<<8|low)*0.0625; //将高八位左移或上低八位转换位十六位数据,再除16.0,
//十六进制转换浮点数要除16.0
return temp_return;
}
void Delay750ms() //@12.000MHz //在系统运行前将ds18b20_Read()读取一次再延
{ //时750ms,就不会读取为上一次温度
unsigned char i, j, k;
_nop_();
_nop_();
i = 35;
j = 51;
k = 182;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
注意:原来,蓝桥杯是使用STC89C52进行比赛的,所以单总线延时也是基于STC89C52实现的,但是现在使用IAP15系列芯片比赛的,IAP15的运行速度比STC89C51快12倍,所以相应的单总线延时函数需要修改,也就是t乘以12。现在第十五届提供的驱动已经将延时函数修改完善好,不需要乘12。
在mian中调用函数
DS13B20在定时器中每100ms刷新读取一次温度
读取函数可以用浮点数(易接收,但是在数码管中显示要进行类型转换)
用unsigned char 类型(接收时要转换,较麻烦,但是在数码管中方便显示)
temp_float =(u32) (fRead_Temperature()*10000);(将数据扩大10000显示四位小数,将数据扩大100显示俩位小数,以此类推),在数码管显示时数据高二位要加上小数点。
//读取温度函数
u8 temperature;
u32 temp_float;
u8 cnt_temp;
void vDS18B20_Read()
{
if(cnt_temp>=100)
{
cnt_temp=0;
//temperature =(u8)fRead_Temperature();
temp_float =(u32) (fRead_Temperature()*10000);
}
}
//数码管操作函数
void vSMG_Process()
{
smg_buf[0]=smg_code[temperature/10];
smg_buf[1]=smg_code[temperature%10];
smg_buf[2]=smg_code[temp_float/100000];
smg_buf[3]=smg_code[temp_float/10000%10]|0x80;
smg_buf[4]=smg_code[temp_float/1000%10];
smg_buf[5]=smg_code[temp_float/100%10];
smg_buf[6]=smg_code[temp_float/10%10];
smg_buf[7]=smg_code[temp_float%10];
}
void main(void)
{
vSystem_Init();
vTimer2_Init();
while(1)
{
vSMG_Process();
vDS18B20_Read ();
}
}
//中断服务程序
void vTimer2_ISR() interrupt 12 //中断入口
{
cnt_temp++;
vSMG_Display();
}