51单片机学习笔记:DS18B20测温程序

发布者:淡雅时光最新更新时间:2017-02-19 来源: eefocus关键字:51单片机  DS18B20  测温程序 手机看文章 扫描二维码
随时随地手机看文章

C代码  收藏代码

  1. #include "my51.h"  

  2. #include "smg.h"  

  3. #include "ds18b20.h"  

  4.   

  5. void main()           //测试 ,6位数码管显示温度值  

  6. {  

  7.     u8 i=0;  

  8.     u16 temp=0;  

  9.     while(1)  

  10.     {     

  11.         temp=ds18b20_readTemperaData();  

  12.         for(i=0;i<100;i++)  

  13.         {  

  14.             displaySMG(ds18b20_processTempData(temp));    

  15.         }             

  16.     }  

  17. }  

 

C代码  收藏代码

  1. #ifndef     _DS18B20_H     

  2. #define     _DS18B20_H  

  3. #include   "my51.h"  

  4. #include   "smg.h"  

  5.   

  6. extern u8 smgWela[7];             //数码管位选数据  

  7. sbit DQ=P2^2;                     //总线定义  

  8. bool ds18b20_init();              //初始化函数  

  9. u8*  ds18b20_processTempData(u16 temp);//将temp数据处理成数码管可显示数据  

  10. u16  ds18b20_readTemperaData();   //读温度  

  11. u8   ds18b20_readByte() ;         //读一个字节  

  12. void ds18b20_writeByte(u8 dat);   //mcu向18b20写一个字节  

  13.   

  14. #endif  

 

C代码  收藏代码

  1. #include "ds18b20.h"  

  2.   

  3. /****************************************************************** 

  4. 当主机总线t0时刻从高拉至低电平时就产生写时间隙 

  5. 从to 时刻开始的1us之后,15us之前将所需写的位送到总线上 

  6. DSl820 在t0后的15-60us 对总线采样若低电平写入的位是0 ,若高电平写入的位是1  

  7. 连续写2 个位之间的间隙应大于1us  

  8. 写1,总时间大于60us,在t0开始延时1us就可以写1,15us之后ic来采样,采样时间最大45us 

  9. 写0,总时间是60~120us,15~60us是ic在采样,120以外就没必要了,mcu总得释放总线吧 

  10. 不管写1还是写0,大于60us的话,ic肯定已经采样完成了,那mcu就可以释放了 

  11. *******************************************************************/  

  12. void ds18b20_writeByte(u8 dat)  //mcu向ic写一个字节  

  13. {  

  14.     u8 i;  

  15.     u8 tmep=dat;  

  16.     for(i=0;i<8;i++)  

  17.     {  

  18.         DQ=0;           //产生读写时序的起始信号  

  19.         _nop_();        //要求至少1us的延时  

  20.         DQ=dat & 0x01; //对总线赋值,从最低位开始写起  

  21.         delayXus(10);//延时74us,写0在60~120us之间释放,写1的话大于60us均可释放  

  22.         DQ=1;          //释放总线,为下一次mcu送数据做准备,         

  23.         dat>>=1;     //有效数据移动到最低位,2次写数据间隙至少需1us  

  24.     }  

  25. }  

  26.   

  27. /************************************************************************** 

  28. 下降沿产生读时序 

  29. 整个读时序必须至少有60us的持续时间,相邻两个读时序必须要有至少1us的恢复时间 

  30. DS18B20在读时序产生1us后输出数据到总线上,也有可能需要2~3个微秒,但不会更多 

  31. 而要求主机释放总线和采样总线等动作要在15μs内完成,那么让mcu采样的最佳时机 

  32. 是读时序产生后的5~13us之间,在15~60us这段时间是18b20的私有时间,它会在这段 

  33. 时间内的任意时刻释放总线,是不稳定期,我们不要让mcu在这段时间里对总线操作 

  34. *******************************************************/  

  35. u8 ds18b20_readByte()    //mcu读一个字节  

  36. {  

  37.     u8 i,value=0;  

  38.     for(i=0;i<8;i++)  

  39.     {  

  40.         DQ=0;                       //起始信号  

  41.         value>>=1;                  //顺便延时3~4个机器周期  

  42.         DQ=1;                       //mcu释放总线  

  43.         _nop_();_nop_();_nop_();    //再延时3.3us   

  44.         if(DQ)            

  45.         {  

  46.             value|=0x80;//保存高电平数据,低电平的话不用保存,移位后默认是0  

  47.         }   

  48.         delayXus(8); //延时60.76us    

  49.     }  

  50.     return value;  

  51. }  

  52.   

  53. u16 ds18b20_readTemperaData()  //读取温度值  

  54. {  

  55.     u16 temp=0;  

  56.     if(ds18b20_init())  

  57.     {  

  58.         ds18b20_writeByte(0xcc);      //写指令:跳过rom检测  

  59.         ds18b20_writeByte(0x44);     //写指令:温度转换  

  60.         //delayms(750);// 转换延时需要750ms以上,我们不等它  

  61.         //首次转换未完成时,得到的初始化数据是85度,处理一下就可以了  

  62.         //温度转换电路是硬件独立的,不会阻塞初始化功能   

  63.         if(ds18b20_init())  

  64.         {  

  65.             ds18b20_writeByte(0xcc);  //写指令:跳过检测rom  

  66.             ds18b20_writeByte(0xbe);  //写指令:读取温度值  

  67.             temp=ds18b20_readByte();  //先读低8位数据  

  68.             temp|=(u16)ds18b20_readByte()<<8; //再读高8位数据,然后合并  

  69.             temp&= 0x0FFF;  //高4位数据反正没用上,我们用来存放错误码  

  70.         }  

  71.         else  

  72.         {  

  73.             led5=0;      //调试代码  

  74.             temp=0x2000; //错误码,初始化失败  

  75.         }  

  76.     }  

  77.     else  

  78.     {  

  79.         led6=0;         //调试代码  

  80.         temp=0x1000;    //错误码,初始化失败,可能器件损坏  

  81.     }  

  82.     return temp;  

  83. }  

  84.   

  85. bool ds18b20_init()   //初始化  

  86. {  

  87.     u8 checkState=0;  

  88.     DQ=1;             //总线初始状态  

  89.     _nop_();_nop_();  

  90.     DQ=0;             //mcu先将总线拉低  

  91.     delayXus(80);     //延时530us,要求480us~960us的低电平信号  

  92.                       //当ic接受到此复位信号后会回发一个存在信号  

  93.                       //mcu若要接收此存在信号则先要释放总线,让ic控制该总线  

  94.                       //当mcu释放总线后的15~60us之后,ic才向总线发一个低电平信号  

  95.                       //该信号存在时间为60~240us  

  96.     DQ=1;             //mcu释放总线  

  97.     delayXus(10);     //mcu释放15~60us以上,(8+6*10)*1.085=73us,  

  98.                       //这时DS18B20已经拉低信号,大约60~240us应答保持时间,  

  99.     checkState=DQ;    //在这段60~240us时间内,mcu采样是否有器件响应,0表示有响应  

  100.     delayXus(70);     //延时464us,加上之前的73us,共537us  

  101.                       //虽然ic在拉低电平60~240us之后,会释放总线,但整个时间至少480us  

  102.                       //故我们共用时537us,这样是为了不影响后续的操作                      

  103.     if(checkState)    //checkstate为0说明有器件响应,为1无器件响应  

  104.     {  

  105.         return FALSE;  

  106.     }  

  107.     return TRUE;      //初始化成功  

  108. }  

  109.   

  110. u8* ds18b20_processTempData(u16 temp) //返回数码管可直接显示的数据指针  

  111. {  

  112.     u8 i=0;   

  113.     if(0x0550==temp)      //如果初始化温度数据是85度的话  

  114.     {  

  115.         led7=0;           //亮灯报警,调试   

  116.         smgWela[5]=18;    //当温度是85度,第6个数码管显示负号  

  117.         return  smgWela;  //一般刚上电时能看到这个负号  

  118.     }  

  119.   

  120.     if(1==(temp&0x0800))  //检测第11位是否为1,为1是负温度  

  121.     {  

  122.         temp&=0x07ff;     //只取第0~10共11个位  

  123.         temp=(~temp+1) & 0x07ff;//将补码还原  

  124.         smgWela[0]=18;   //第一个数码管显示18号元素,即负号  

  125.     }  

  126.     else  

  127.     {  

  128.         smgWela[0]=dark;     //正温度的话这个数码管就不要显示了  

  129.     }  

  130.     temp=(u16)(temp*6.25);   //精度的1000倍,我们将小数点另外叠加显示  

  131.     if(temp>=10000)  

  132.     {  

  133.          smgWela[1]=1;       //第二个数码管显示1,是百位上,100度以上啊  

  134.     }  

  135.     else  

  136.     {  

  137.         smgWela[1]=dark;     //百位上是0的话不要显示这个0  

  138.     }  

  139.     smgWela[2]=temp%10000/1000;    //第三个数码管 十位  

  140.     smgWela[3]=temp%1000/100;      //第四个数码管 个位叠加小数点  

  141.     smgWela[4]=temp%100/10;        //第五个数码管   

  142.     smgWela[5]=temp%10;            //第六个数码管  

  143.     smgWela[6]=0xf7;               //第4个数码管叠加小数点  

  144.     return smgWela;                //返回数组  

  145. }  

 

C代码  收藏代码

  1. #ifndef _51SMG_H_  

  2. #define _51SMG_H_  

  3.   

  4. #include   

  5. #include "mytype.h"  

  6. sbit dula =P2^6;        //段选锁存器控制  控制笔段  

  7. sbit wela =P2^7;        //位选锁存器控制  控制位置  

  8.   

  9. #define dark    0x11//在段中,0x11是第17号元素,0x00是低电平,数码管不亮,即table[17]  

  10. #define dotDark 0xff//小数点全暗  

  11.   

  12. void displaySMG(u8* pWela); //数码管显示函数,参数是数组指针  

  13.   

  14. #endif  

 

C代码  收藏代码

  1. #include "smg.h"  

  2. #include "my51.h"  

  3.   

  4. static u8 code table[]= {       //0~F外加小数点和空输出的数码管编码  

  5.     0x3f , 0x06 , 0x5b , 0x4f , // 0 1 2 3  

  6.     0x66 , 0x6d , 0x7d , 0x07 , // 4 5 6 7  

  7.     0x7f , 0x6f , 0x77 , 0x7c , // 8 9 A B  

  8.     0x39 , 0x5e , 0x79 , 0x71 , // C D E F  

  9.     0x80 , 0x00 ,0x40           // . 空 负号    空为第17号元素  

  10.  };  

  11.   

  12. /*  由于此表只能一次显示一个小数点,故已注释掉,仅供查询 

  13.     例如想要第一个和第六个数码管小数点同时点亮, 

  14.     则执行 pWela->dot = 0xfe & 0xdf  即可 

  15.     u8 code dotTable[]={   //小数点位置,某一位置0时,小数点亮 

  16.     0xff ,                 //全暗 

  17.     0xfe , 0xfd , 0xfb ,   //1 2 3 

  18.     0xf7 , 0xef , 0xdf     //4 5 6                     

  19. };*/  

  20.   

  21. u8 data smgWela[7]={0,0,0,0,0,0,0}; //第一位到第六位,最后一个是小数点位置控制  

  22.   

  23. //P0口的数码管位选控制锁存器只用了低6位,我们保留高2位的数据,留作它用  

  24. void displaySMG(u8* pWela)  

  25. {  

  26.     u8 i=0;   

  27.     //控制6位数码管显示函数,不显示的位用参数dark  

  28.     u8 preState=P0|0x3f;  //保存高2位状态,其中最高位是ADC0804的片选信号  

  29.     wela=0;dula=0;_nop_();//先锁定数据,防止吴亮及位选锁存器高2位数据被改变  

  30.           

  31.     P0=0;                 //由于数码管是共阴极的,阳极送低电平,灯不亮  

  32.     dula=1;_nop_();  

  33.     dula=0;               //段选数据清空并锁定  

  34.   

  35.     P0=preState;          //共阴极数码管是阴极置高不亮,低6位置1,高2位保留     

  36.     wela=1;_nop_();       //注:wela和dula上电默认为1          

  37.     wela=0;               //位选锁定,初始保留高2位的数据,低6位置高不亮  

  38.   

  39.     for(i=0;i<6;i++)   //显示6位数码管  

  40.     {  

  41.         P0=table[pWela[i]]|(((1<

  42.         dula=1;_nop_();      //送段数据,叠加小数点的显示,0x00点亮小数点  

  43.         dula=0;  

  44.           

  45.         P0=preState&~(1<

  46.         wela=1; _nop_();     //送位选号  

  47.         wela=0;   

  48.         delayms(1);          //稍作延时,让灯管亮起来            

  49.         {  //消除叠影及误亮,阴极置1不亮,低6位置1,高2位保留并锁定  

  50.             P0=preState;  

  51.             wela=1; _nop_();              

  52.             wela=0;   

  53.         }  

  54.     }  

  55. }  

 

C代码  收藏代码

  1. #ifndef _MY51_H  

  2. #define _MY51_H  

  3. #include   

  4. //#include   

  5. #include   

  6. #include "mytype.h"  

  7.   

  8.   

  9. #define high    1   //高电平  

  10. #define low     0   //低电平  

  11.   

  12. #define led P1    //灯总线控制  

  13.   

  14. sbit led0=P1^0;     //8个led灯,阴极送低电平点亮  

  15. sbit led1=P1^1;  

  16. sbit led2=P1^2;  

  17. sbit led3=P1^3;  

  18. sbit led4=P1^4;  

  19. sbit led5=P1^5;  

  20. sbit led6=P1^6;  

  21. sbit led7=P1^7;   

  22. sbit ledLock=P2^5;  //led锁存的状态,0锁定 ,1不锁定  

  23.      

  24. sbit beep=P2^3;     //蜂鸣器  

  25.   

  26. void delayms(u16 ms);  

  27. void delayXus(u8 us); //函数执行(8+6x)个机器周期, 即t=(8+6x)*1.085  

  28. /////////////////////////////////////////////////////////////////////////////  

  29.   

  30.   

  31. #endif  

 

C代码  收藏代码

  1. #include "MY51.h"  

  2.   

  3. void delayms(u16 ms)     //毫秒级软延时函数  

  4. {     

  5.     u16 i,j;  

  6.     for(i=ms;i>0;i--)  

  7.     {  

  8.         for(j=113;j>0;j--)  

  9.         {}  

  10.     }  

  11. }  

  12.   

  13. /**************************************************************** 

  14. 若使用12分频模式的mcu,晶振频率为11059200Hz 

  15. 则每个机器周期用时12/11059200=1.085微秒 

  16. keil4编译,在默认的8级优化方式下 

  17. 参数us=0时,函数执行9个机器周期,即t=9*1.085=9.77 us 

  18. 参数us!=0时,函数执行(8+6x)个机器周期, 即t=(8+6x)*1.085 us 

  19. *****************************************************************/  

  20. void delayXus(u8 us)    //微秒级软延时函数  

  21. {  

  22.     while(us)           //这种写法有利于减小us=0时的机器周期  

  23.     {  

  24.         us--;  

  25.     }  

  26. }  

 


关键字:51单片机  DS18B20  测温程序 引用地址:51单片机学习笔记:DS18B20测温程序

上一篇:51单片机学习笔记:使用DS1302芯片制作电子钟
下一篇:51单片机学习笔记:基于状态机的按键对时程序(短按,长按,连

推荐阅读最新更新时间:2024-03-16 15:33

51单片机5110液晶显示屏实现时间温度串口发送
制作出来的实物图如下: 仿真原理图如下(proteus仿真工程文件可到本帖附件中下载) 单片机源程序如下: /** P2.7置低电平时,开机接入串口,自动进入时间设置界面 每秒钟自动检测温度一次,并在LCD上显示 每分钟自动刷新日期、时间、温度,在LCD上显示,并在串口中输出(方便电脑读取) */ #include stdio.h //#include AT89X51.H #include reg51.h #include ds1302.h #include temp.h #include nokia_5110.h //*********************************** #def
[单片机]
<font color='red'>51单片机</font>5110液晶显示屏实现时间温度串口发送
51单片机C语言教程(一) 建立第一个工程
  学习单片机实在不是件易事,一来要购买高价格的编程器,仿真器,二来要学习编程语言,还有众多种类的单片机选择真是件让人头疼的事。在众多单片机中51架构的芯片风行很久,学习资料也相对很多,是初学的较好的选择之一。51的编程语言常用的有二种,一种是汇编语言,一种是C语言。汇编语言的机器代码生成效率很高但可读性却并不强,复杂一点的程序就更是难读懂,而C语言在大多数情况下其机器代码生成效率和汇编语言相当,但可读性和可移植性却远远超过汇编语言,而且C语言还可以嵌入汇编来解决高时效性的代码编写问题。对于开发 周期 来说,中大型的软件编写用C语言的开发周期通常要小于汇编语言很多。综合以上C语言的优点,我在学习时选择了C语言。以后的教程也只是我在
[单片机]
<font color='red'>51单片机</font>C语言教程(一) 建立第一个工程
51单片机控制TC35 之发送TEXT短信——MADE BY lyq
主函数 #include reg52.h #include 1602.h #include uart.c #include tc35.c //#define RsBuf_N 50 //char RsBuf ; //定义串口接收数据缓冲区 //uchar RsPoint=0; uchar code PhoneNO = +8615900000000 ;//改了 uchar code Text = I love SDNU ; uchar code center = +8613800531500 ; void main() { TC35_init(); Uart_init(); init_1602(); Send_AT(
[单片机]
51单片机程序——数码管显示0~99
#include reg52.h #define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换 #define CtrlPort P1 //定义控制端口 unsigned char code DuanMa ={0xc0,0xf9,0xa4,0xb0, 0x99,0x92,0x82,0xf8,0x80,0x90};// 显示段码值0~9 unsigned char code WeiMa ={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//分别对应相应的数码管点亮,即位码 unsigned char TempData ; //存储显示值
[单片机]
用汇编语言实现51单片机内部RAM单元的数据传送到外部RAM
下面是实现将片内RAM30H单元开始的15B的数据传送到片外RAM3000H开始的单元中去的8051单片机汇编语言代码: STRAT:MOV R0,#30H MOV R7,#0FH MOV DPTR,#3000H LOOP: MOV A,@R0 MOVX @DPTR,A INC R0 INC DPTR DJNZ R7,LOOP RET 下面是实现将片内RAM30H单元开始的15B的数据传送到片外RAM3000H开始的单元中去的8051单片机汇编语言代码: STRAT:MOV R0,#30H MOV R7,#0FH MOV DPTR,#3000H LOOP: MOV A,@R0 MOVX @DPTR,A
[单片机]
用汇编语言实现<font color='red'>51单片机</font>内部RAM单元的数据传送到外部RAM
51单片机--LED闪烁、流水灯的简单试验
一、LED闪烁 /***************************************************************** LED闪烁的简单试验 *****************************************************************/ include reg51.h //此文件中定义了51的一些特殊功能寄存器 /*******延时函数**************************************/ // 定义一个演示函数,定时时间大概为一个ms。 void delay(unsigned int i) { unsigned
[单片机]
<font color='red'>51单片机</font>--LED闪烁、流水灯的简单试验
89C51单片机做示波器,读取波形代码
上两周主要在探索单片机实时采集AD值并用串口发送到电脑端处理。虽然原理比简单,但由于个人理论功底还有所欠缺,再加上前期目标还不清晰,所以花的时间还是有点多。 刚开始在很长一段时间内串口读不到AD采集的电压值,但在单独调试串口时却是好的。经过很长时间的测试才发现串口中断也定时中断同时打开,导致程序跑飞。后来改中断方式为查询方式,避免了这个问题。后来又遇到了串口波特率一致问题。软件问题都一一解决后,终于能读到数据。画出波形: 正弦信号:幅值2V,偏执1V 无论怎么改变采集信号的频率,发现波形还是这样。再三检查程序确认没有问题时仔细阅读AD的芯片资料后,发现手上这款PCF8591芯片内部自带了峰值保持电路,也就是正弦信号理
[单片机]
89C<font color='red'>51单片机</font>做示波器,读取波形代码
利用51单片机的电子琴设计
利用51单片机的电子琴设计 声音的频谱范围约在几十到几千赫兹,若能利用程序来控制单片机某个口线不断的输出“高”“低”电平,则在该口线上就能产生一定频率的方波,将该方波接上喇叭就能发出一定频率的声音,若再利用程序控制“高”“低”电平的持续时间,就能改变输出波形的频率,从而改变音调。         乐曲中,每一音符对应着确定的频率,表1给出C调时各音符频率。如果单片机某个口线输出“高”“低”电平的频率和某个音符的频率一样,那么将此口线接上喇叭就可以发出此音符的声音。   本系统就是根据此原理设计,对于AT89C2051单片机来说要产生一定频率的方波大致是先将某口线输出高电平然后延时一段时间再输出低电平,如此循环的
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved