第八课 温度检测DS18B20
实验准备:
DS18B20
LCD1602
课程内容:
一、 模块分析:
仅一条总线,既用于传命令,又用于传数据。
单总线的所有处理均从初始化开始。
1) 初始化
t0时刻总线拉高,然后即把总线(P37)电平拉低(给0),延时480—960微秒然后把总线拉高(给1),延时480微秒
(在这480微秒时间内DS18B20会响应,单模块可以忽略,多模块才需要判断)
如果要判断DS18B20是否存在,可以先延时100微秒,判断总线电平是否为0然后再继续延时380微秒
3)写入 基本数据 0 与 1 的判断
写0时序:
t0总线先拉高再拉低,延时>60微秒,
然后总线拉高,延时>1微秒
写1时序:
t0总线先拉高再拉低,延时4微秒,
然后总线拉高,延时>60微秒
4)读数据
t0时刻总线拉高,再拉低,延时4微秒,再拉高,延时10秒,准备收数据。
然后,接收总线数据(即判断 总线 是 0 或 1,这是由DS18B20送出的)。
延时50微秒,总线拉高。
5)传数据,字节传送时,先传送低位
一、 分功能块编代码,可放入 中
sbit D18B20=P3^7; //ds18b20 端口
//TempDelay(80); //530uS
//TempDelay(14); //100uS
//_nop_(); ) 1us(12M)
//可用 KEIL调试模式检测
void TempDelay (uchar us) //延时处理
{
while(us--);
}
void Init18b20 (void) //18B20初始化
{
D18B20=1;
D18B20=0;
TempDelay(80); //delay 530 uS//80
D18B20=1;
TempDelay(34); //delay 480 uS//70
D18B20 = 1;
}
void write_byte (uchar dat) //18B20写入一个字节
{
uchar i;
for (i=0;i<8;i++)
{
D18B20 = 0;
_nop_(); //用空指令延时
D18B20=dat&0x01; //取出最低位放入总线
TempDelay(5); //delay 45 uS //5
D18B20=1;
dat>>= 1; //准备下一位数据
}
}
//说明 一次1bit的读取最少需要60us 两次读取之间需要至少1us的恢复时间
// 单次读取1bit 总线拉低不能超过15us 然后马上拉高
uchar read_byte (void) //读18B20的一个字节
{
uchar i,u=0;
for(i=0;i<8;i++)
{
D18B20 = 0;
u >>= 1; //右移,腾出左边的一位存数,同时有延时效果
D18B20 = 1;
if(D18B20==1) u |= 0x80; //存入 数据
TempDelay (4);
}
return(u);
}
//读出温度函数
//返回为温度值 温度值为short变量 有正负
short read_temp() //short可以表示-32768~+32767
{
uchar TL,TH;
uchar temp;
short t;
Init18b20 (); //总线复位
write_byte(0xcc); //发命令
write_byte(0x44); //发转换命令
Init18b20(); //复位
write_byte(0xcc); //发命令
write_byte(0xbe); //发送读温度命令
TL=read_byte(); //读温度值的低字节
TH=read_byte(); //读温度值的高字节
t=TH;
if(TH>7)
{
TH=~TH;
TL=~TL;
temp=0;//温度为负
}else temp=1;
t<<=8;
t+=TL; // 两字节合成一个整型变量。
t=(float)t*0.0625; 为12位温度采集的分辨率 t为采集的数值 这里扩大10倍提取小数点后一位
if(temp)return t;
else return -t;
}
LCD1602 显示温度时,要先判断正负,负的要显示 – 号,实现以上代码段后,主程序就简单了,当然,简单的背后还有前几节课的支撑。
void main()
{
short temp;
lcd_init(); // 1602初始化
lcd_ wcmd (0x80); //设置显示位置为第一行的第1个字符
while(1)
{
lcd_ wcmd (0x80);
temp =read_temp();
lcd_wdat(temp %10000/1000+0x30);
lcd_wdat(temp %1000/100+0x30);
lcd_wdat(temp %100/10+0x30);
lcd_wdat(temp %10+0x30);
}
}
后记:
自这课之后,基本可以使用不同的器件玩下开发了,例如加液晶屏,时钟控制等.
各种器件,一般都附带有厂家的例程或者能从网上找到例程.只要仔细分析时序图,把例程中代码"搬运"一下到自己的代码中,略加修改,即可用,不需要重复花时间去开发对应驱动,这就是平常所讲的不要重复造"轮子".
编程思想,并不是把所有代码放一堆在一个文件中,而是把想实现的功能细分为简单的功能模块(用各个 .h头文件 #include作关联调用),然后专心设计每一个简单模块,这是C语言开发软件常用的一种模式.
另外.并不是跟着教程学会了基本的编程与几个器件的使用,就表示会了单片机开发了,只有当自己能够独立完成一个完整的系统,例如 洞洞板+液晶+时钟+蜂鸣器+本课的温度器件,动手焊接线路,构造一个完整的代码结构和模块化编程,实现整点报时及报室温,再想牛点的话,排上几个LED点阵,模拟指针时钟特效,等等.当一个完整的系统是自己一点一点建成后,可以向人展示成品时,也就入门了.
再之后,可以玩点步进电机,超声波,红外,数模转换,无线传送,3寸或5寸屏液晶汉字显示,控制家电,控制PC,... ...