再谈DS18B20驱动程序--工作电压为3.3V
之前讨论过DS18B20的驱动,都是工作在5V电压下的,经过改良过的程序,直接移过来就可以用,不需要再调时序。由于项目需要,这次用的DS18B20的工作电压是3.3V,程序移过去之后运行,取得的温度值一直都是16,改变外界环境时,这个值也不会变,这肯定是不正常的。
网上也有人遇到类似的情况,解决办法无非就是换上拉电阻值,或是直接把工作电压改成5V,然后数据口直接与单片机相连。我测试的情况是,换上拉电阻没有任何作用,改电压的有点反应,就是器件时不时会取85这个值,也就是说取到值在85或16跳动,更多时候取出来的值是16。
想到低电压的抗干扰能力弱一些,时序上做些调整应该会好一点。于是把电路改回3.3V,然后对初始化及数据读写部分中用到_nop_()函数的部分进行统一修改,用固定的延时函数(5us)来取代,测试结果完成正确。以下为修改过的代码(主要修改部分就是DQ从高变低期间的延时):
/**************复位***********************/ unsigned char DS1B20Init(void) { unsigned char i; DQ=1; Delay5us_xn(1); DQ=0; Delay5us_xn(96); //延时480us DQ=1; Delay5us_xn(12); //延时60us i=0; while(DQ) //在480us内检测DQ是否变为低,如果为低则复位成功,否则复位不成功 { Delay5us(); i++; if(i>96) { i=255; break; } } if(i==255) return 0; //初始化失败 while(!DQ); //等待DS18B20释放总线 return 1; //初始化成功 } /**********写一个字节数据到DS18B20***********/ void WriteDat(unsigned char dat) { unsigned char i; for (i=8; i>0; i--) // { DQ=1; Delay5us_xn(1); DQ=0; Delay5us(); DQ=dat&0x01; //最低位移出 Delay5us_xn(13); dat=dat>>1; //右移一位 } DQ=1; Delay5us_xn(2); } /**********读一个字节数据从DS18B20***********/ unsigned char ReadDat(void) { unsigned char dat,i; for (i=8;i>0;i--) { DQ=1; Delay5us_xn(1); dat>>=1; DQ=0; // Delay5us_xn(1); DQ=1; Delay5us_xn(1); if(DQ) dat|=0x80; Delay5us_xn(13); } DQ=1; return(dat); }
至此,问题完美解决。再次提醒我们,涉及到时序操作的器件驱动,为了保证良好的可移植性,务必选用固定的延时函数来完成时序控制。以下为改良后的DS18B20的完整驱动程序。
http://pan.baidu.com/s/1mhN2DMK
凯特网版权声明:以上内容允许转载,但请注明出处,谢谢!