LanQiao比赛单片机专用板——CT107D把玩笔记(二)
通过对CT107D实验板的基本原理认识,以及掌握好了LED、数码管等小部件的操作,我们就可以自信满满地学习更为复杂的外接元件了。面对板载重要器件,比如:DS18B20、DS1302、AT24C02、PCF8591等。我们要脚踏实地的逐一攻克。
首先,来看一下温度传感器——DS18B20。
上原理图:
DS18B20电路原理图.png
做为日常最常见的数字温度传感器,这无疑显得非常重要,大赛组织方对此也很重视,往届比赛试题多次涉及该传感器的相关内容。
拿过一个新器件,第一步要查看其完整的官方说明文档。看原理图已知,DS18B20有三个管脚,其中两个是电源线,只有一个数据引脚。因此它是典型的单总线传输器件。提到单总线IIC,就会涉及到单总线时序的操作,而该传感器对时序的要求非常苛刻。对,我只能用苛刻这两个字来形容,因为针对不同的硬件平台,时序操作是大不相同的,最初我在此处深陷,困惑了很长一段时间。
说明文档中,最重点是初始化、读和写的操作时序图。
先看初始化操作时序:
初始化时序图.png初始化时序,也可作复位时序。由图可见,主控器发送复位低脉冲的时间约为480微秒,主控器接收的时间大约为480微秒。编程时要注意高低电平之间的间隔延时,要严格按照时序图操作。
再来看写时序图:
写时序图.png该图明确说明了主控器在IIC总线中高低电平的间隔时间,不在具体熬述。
最后,读时序图:
读时序图.png原理如图,主控器要占用总线45微秒来采样,图片说明很详细。
分析完工作原理后,我们就可以敲代码了。
传感器驱动程序如下:
ds18b20.c
void delay(uint t)
{
uint i;
for(i = 0; i<t; i++)
{
_nop_(); //1.0us
}
}
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
delay(10);
DQ = 0;
delay(500);
DQ = 1;
delay(200);
initflag = DQ;
delay(250);
return initflag;
}
//通过单总线向器件写一个字节
void wr_ds18b20(uchar dat)
{
uchar i;
for(i = 0; i<8; i++)
{
DQ = 0;
delay(2);
DQ = dat&0x01;
delay(60);
DQ = 1;
dat >>= 1;
}
delay(5);
}
//通过单总线从器件读一个字节
uchar rd_ds18b20(void)
{
uchar i;
uchar ret;
uchar dat = '0';
for(i = 0; i<8; i++)
{
dat >>= 1;
DQ = 0;
delay(2);
DQ = 1;
ret = DQ;
delay(60);
DQ = 1;
if(ret)
dat |= 0x80;
}
return dat;
}
///温度读取及转换函数
uchar rd_temperature(void)
{
uchar low, high;
uint temp;
float temperature;
DQ = 1;
init_ds18b20();
wr_ds18b20(0xcc);//跳过读ROM
wr_ds18b20(0x44);//
delay(200);
init_ds18b20();
wr_ds18b20(0xcc);
wr_ds18b20(0xbe);//读取温度
low = rd_ds18b20(); //先读低字节
high = rd_ds18b20(); //高字节
temp = high&0x0f;
temp <<= 8;
temp |= low;
temperature=temp*0.0625; //分辨率转换
temp=temperature*10+0.5; //四舍五入,保留小数点一位
return temp;
}
驱动代码参照时序图都可以写出来,这里关键的一点是延时函数。该函数的精确度决定了整个程序的时序精确度,如果延时不准确,那整个程序是失败的,DS18B20不能正常工作。有许多同学说程序写好了,没有错误,用数码管显示温度,温度数值一直没有变过。大多是因为时序的问题。应该仔细更改延时程序,反复进行调试。