AVR单片机学习笔记--基于慧净HJ-2GAVR开发板第14章DS18B2014.114.114.114.1概念....这一章是关于DS18B20实时温度传感器。相信有学过c51单片机的朋友都对他不陌生吧。我恰恰也学习过,不过当初并没有掌握好。学习板搭配的DS18B20,一般上给人的感觉有点像三极管,其实DS18B20的内部结构与原理也挺猥琐的,但是我们使用也是为了实现温度传感的功能而已,基本上不会介绍过度深入。14.214.214.214.2DS18B20DS18B20DS18B20DS18B20介绍DS18B20有三只引脚,VCC,DQ,和VDD。而HJ-2G板子上,采用了外部供电的链接方式,而总线必须链接上拉电阻。这一目的告诉我们,一线总线在空置状态时,都是一直处于高电平。DS18B20的内部有64位的ROM单元,和9字节的暂存器单元。64位ROM包含了,DS18B20唯一的序列号(唯一的名字)。AVR单片机学习笔记--基于慧净HJ-2GAVR开发板以上是内部9个字节的暂存单元(包括EEPROM)。字节0~1是转换好的温度。字节2~3是用户用来设置最高报警和最低报警值。这个可以用软件来实现。字节4是用来配置转换精度,9~12位。字节5~8就不用看了。14.314.314.314.3字节0~10~10~10~1::::转换好的温度DS18B20的温度操作是使用16位,也就是说分辨率是0.0625。BIT15~BIT11是符号位,为了就是表示转换的值是正数还是负数。看看数据手册给出的例子吧。AVR单片机学习笔记--基于慧净HJ-2GAVR开发板要求出正数的十进制值,必须将读取到的LSB字节,MSB字节进行整合处理,然后乘以0.0625即可。Eg:假设从,字节0读取到0xD0赋值于Temp1,而字节1读取到0x07赋值于Temp2,然后求出十进制值。unsignedintTemp1,Temp2,Temperature;Temp1=0xD0;//低八位Temp2=0x07;//高八位Temperature=((Temp28)|Temp1)*0.0625;//又或者Temperature=(Temp1+Temp2*256)*0.0625;//Temperature=125在这里我们遇见了一个问题,就是如何求出负数的值呢?很遗憾的,单片机不像人脑那样会心算,我们必须判断BIT11~15是否是1,然后人为置一负数标志。Eg.假设从,字节0读取到0x90赋值于Temp1,而字节1读取到0xFC赋值于Temp2,然后求出该值是不是负数,和转换成十进制值。unsignedintTemp1,Temp2,Temperature;unsignedcharMinus_Flag=0;Temp1=0x90;//低八位Temp2=0xFC;//高八位//Temperature=(Temp1+Temp2*256)*0.0625;//Temperature=64656//很明显不是我们想要的答案if(Temp2&0xFC)//判断符号位是否为1{Minus_Flag=1;//负数标志置一Temperature=((Temp28)|Temp1)//高八位第八位进行整合Temperature=((~Temperature)+1);//求反,补一Temperature*=0.0625;//求出十进制}//Temperature=55;else{Minus_Flag=0;Temperature=((Temp28)|Temp1)*0.0625;}那个人为的负数标志,是真的很有用处的。这个要看你你自己的想象力了,如何去利用它。AVR单片机学习笔记--基于慧净HJ-2GAVR开发板继续继续,以上我们是求出没有小数点的正数。如果我要求出小数点的值的话,那么我应该这样做。Eg:假设从,字节0读取到0xA2赋值于Temp1,而字节1读取到0x00赋值于Temp2,然后求出十进制值,要求连同小数点也求出。unsignedintTemp1,Temp2,Temperature;Temp1=0x90;//低八位Temp2=0xFC;//高八位//实际值为10.125//Temperature=((Temp28)|Temp1)*0.0625;//10,无小数点Temperature=((Temp28)|Temp1)*(0.0625*10);//101,一位小数点//Temperature=((Temp28)|Temp1)*(0.0625*100);//1012,二位小数点如以上的例题,我们可以先将0.0625乘以10,然后再乘以整合后的Temperature变量,就可以求出后面一个小数点的值(求出更多的小数点,方法都是以此类推)。得出的结果是101,然后再利用简单的算法,求出每一位的值。unsingedcharTen,One,Dot1Ten=Temperature/100;//1One=Temperature%100/10;//0Dot1=%10;//1求出负数的思路也一样,只不过多出人为置一负数标志,求反补一的动作而已。自己发挥想象力吧。14.414.414.414.4字节2~32~32~32~3:THTHTHTH和TLTLTLTL配置TH与TL就是所谓的温度最高界限,和温度最低界限的配置。其实这些可以使用软件来试验,所以就无视了。14.514.514.514.5字节4444:配置寄存器BIT7出厂的时候就已经设置为0,用户不建议去更改。而R1与R0位组合了四个不同的转换精度,00为9位转换精度而转换时间是93.75ms,01为10位转换精度而转换时间是187.5ms,10为11位转换精度而转换时间是375ms,11为12位转换精度而转换时间是750ms(默认)。该寄存器还是留默认的好,毕竟转换精度表示了转换的质量。AVR单片机学习笔记--基于慧净HJ-2GAVR开发板14.614.614.614.6字节5~75~75~75~7,8888:保留位,CRCCRCCRCCRC无视,无视吧。14.714.714.714.7单片机访问DS18B20DS18B20DS18B20DS18B20DS18B20一般都是充当从机的角色,而单片机就是主机。单片机通过一线总线访问DS18B20的话,需要经过以下几个步骤:1.DS18B20复位。2.执行ROM指令。3.执行DS18B20功能指令(RAM指令)。补充一下。一般上我们都是使用单点,也就是说单线总线上仅有一个DS18B20存在而已。所以我们无需刻意读取ROM里边的序列号来,然后匹配那个DS18B20?而是更直接的,跳过ROM指令,然后直接执行DS18B20功能指令。DS18B20复位,在某种意义上就是一次访问DS18B20的开始,或者可说成是开始信号。ROM指令,也就是访问,搜索,匹配,DS18B20个别的64位序列号的动作。在单点情况下,可以直接跳过ROM指令。而跳过ROM指令的字节是0xCC。DS18B20功能指令有很多种,我就不一一的介绍了,数据手册里有更详细的介绍。这里仅列出比较常用的几个DS18B20功能指令。0x44:开始转换温度。转换好的温度会储存到暂存器字节0和1。0xEE:读暂存指令。读暂存指令,会从暂存器0到9,一个一个字节读取,如果要停止的话,必须写下DS18B20复位。14.814.814.814.8DS18B20DS18B20DS18B20DS18B20复位DS18B20的复位时序如下:1.单片机拉低总线480us~950us,然后释放总线(拉高电平)。2.这时DS18B20会拉低信号,大约60~240us表示应答。3.DS18B20拉低电平的60~240us之间,单片机读取总线的电平,如果是低电平,那么表示复位成功。4.DS18B20拉低电平60~240us之后,会释放总线。AVR单片机学习笔记--基于慧净HJ-2GAVR开发板C语言代码://DS1302复位函数voidDS1302_Reset(){DDRA|=BIT(DQ);//DQ为输出状态PORTA&=~BIT(DQ);//输出低电平Delay_1us(500);//延迟500微妙PORTA|=BIT(DQ);//示范总线Delay_1us(60);//延迟60微妙DDRA&=~BIT(DQ);//DQ位输出状态while(PINA&BIT(DQ));//等待从机DS18B20应答(低电平有效)while(!(PINA&BIT(DQ)));//等待从机DS18B20释放总线}14.914.914.914.9DS18B20DS18B20DS18B20DS18B20读写逻辑0000与1111DS18B20写逻辑0的步骤如下:1.单片机拉低电平大约10~15us,。2.单片机持续拉低电平大约20~45us的时间。3.释放总线DS18B20写逻辑1的步骤如下:1.单片机拉低电平大约10~15us,。2.单片机拉高电平大约20~45us的时间。3.释放总线DS18B20读逻辑0的步骤如下:1.在读取的时候单片机拉低电平大约1us2.单片机释放总线,然后读取总线电平。3.这时候DS18B20会拉低电平。4.读取电平过后,延迟大约40~45微妙DS18B20读逻辑1的步骤如下:1.在读取的时候单片机拉低电平大约1us2.单片机释放总线,然后读取总线电平。3.这时候DS18B20会拉高电平。4.读取电平过后,延迟大约40~45微妙AVR单片机学习笔记--基于慧净HJ-2GAVR开发板如果要读或者写一个字节,就要重复以上的步骤八次。如以下的C代码,使用for循环,和数据变量的左移和或运算,实现一个字节读与写。//DS18B20写字节函数voidDS1302_Write(unsignedcharData){unsignedchari;DDRA|=BIT(DQ);//DQ为输出for(i=0;i8;i++){PORTA&=~BIT(DQ);//拉低总线Delay_1us(10);//延迟10微妙(最大15微妙)if(Data&0x01)PORTA|=BIT(DQ);elsePORTA&=~BIT(DQ);Delay_1us(40);//延迟40微妙(最大45微妙)PORTA|=BIT(DQ);//释放总线Delay_1us(1);//稍微延迟Data=1;}}//DS18B20读字节函数unsignedcharDS1302_Read(){unsignedchari,Temp;for(i=0;i8;i++){Temp=1;//数据右移DDRA|=BIT(DQ);//DQ为输出状态PORTA&=~BIT(DQ);//拉低总线,启动输入PORTA|=BIT(DQ);//释放总线DDRA&=~BIT(DQ);//DQ为输入状态if(PINA&BIT(DQ))Temp|=0x80;Delay_1us(45);//延迟45微妙(最大45微妙)}returnTemp;}就是这么建档而已,不过这里有一个注意点,就是Delay_1us();函数延迟的时间,必须模拟非常准确,因为单线总线对时序的要求敏感点。AVR单片机学习笔记--基于慧净HJ-2GAVR开发板14.1014.1014.1014.10简单归纳实验开始之前,简单的归纳一些重点。单线总线高电平为闲置状态。单片机访问DS18B20必须遵守,DS18B20复位--执行ROM指令--执行DS18B20功能指令。而在单点上,可以直接跳过ROM指令。DS18B20的转换精度默认为12位,而分辨率是0.0625。DS18B20温度读取函数参考步骤:DS18B20开始转换:1.DS18B20复位。2.写入跳过ROM的字节命令,0xCC。3.写入开始转换的功能命令,0x44。4.延迟大约750~900毫秒DS18B20读暂存数据:1.DS18B20复位。2.写入跳过ROM的字节命令,0xCC。3.写入读暂存的功能命令,0xee。4.读入第0个字节LSByte,转换结果的低八位。5.读入第1个字节MSBy