找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5861|回复: 2
收起左侧

单片机8路ds18b20温度采集Proteus仿真+代码

[复制链接]
ID:491242 发表于 2019-3-15 10:07 | 显示全部楼层 |阅读模式
8路温度采集器
0.png

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>


  3. #define MAXNUM 8 //定义最多有8个 DS18B20

  4. sbit DQ=P2^3;    //定义DS18B20总线端

  5. sbit RS=P2^0;         //液晶端口控制线端口定义
  6. sbit RW=P2^1;         //液晶端口控制线端口定义
  7. sbit E= P2^2;         //液晶端口控制线端口定义

  8. sbit keyenter =P3^2;  //功能按键
  9. sbit keyup    =P3^3; //报警温度加键
  10. sbit keydown  =P3^4; //报警温度减键

  11. sbit led=    P1^6;          //亮灯报警
  12. sbit buzzer= P1^7;          //蜂鸣器报警控制脚



  13. unsigned char code lcd0[]={"SEARCH ROMING..."};
  14. unsigned char code lcd1[]={"SEARCH ROM OK!"};
  15. unsigned char code lcd2[]={"THE TOTAL IS:"};
  16. unsigned char code lcd3[]={"NO.[ ]:"};
  17. unsigned char code lcd4[]={'0','1','2','3','4','5','6','7','8','9','.',0xdf,0x43,' '};
  18. unsigned char code setinfo[]={"SET ALARM POINT:"};
  19. unsigned char code pointinfo[]={"ALARM:"};
  20. signed char tempalarm=0;


  21. //0xdf在1602中是“℃”符号的左上角那个圆,0X43是大写的"C" 他们一起构成了”℃“这个符号

  22. unsigned char dat[6];//用来显示温度的参数                                          
  23. unsigned char temp_l,temp_h,negetiveflag=0,temp_over,t;
  24. unsigned char num=0;
  25. unsigned int i;
  26. bit keyflag=0;
  27. idata unsigned char al[MAXNUM];
  28. idata unsigned char ID[MAXNUM][8];

  29. signed char alarm=30; //默认为30摄氏度报警

  30. /***********************液晶模块**********************************/
  31. void delaylcd(void)//延时程序
  32. {
  33.         unsigned char y;
  34.         for(y=0;y<250;y++);
  35. }

  36. void LCD_write_com(unsigned char com)//液晶写命令函数
  37. {
  38.         delaylcd();
  39.     RS=0; //RS为1 写命令
  40.     RW=0;
  41.         E=0;
  42.         E=1;
  43.     P0=com;
  44.            E=0;
  45.         delaylcd();
  46. }

  47. void LCD_write_data(unsigned char dat)//液晶写数据函数
  48. {
  49.         delaylcd();
  50.         RS=1;   //RS为1 写数据
  51.         RW=0;
  52.         E=0;
  53.         E=1;
  54.         P0=dat;
  55.         E=0;
  56.         delaylcd();
  57. }
  58. void lcdinit(void)//初始化
  59. {
  60.         LCD_write_com(0x01); //液晶清屏 
  61.         LCD_write_com(0x38); //1602”功能设置命令字“ 显示2行 每行字体用5*8 ASCII显示        8位数据接口
  62.         LCD_write_com(0x0c); //显示控制,开始显示,不显示游标,游标不闪烁       
  63.         LCD_write_com(0x06); //输入方式为增量输入,不移屏幕
  64. }

  65. /************************ds18b20模块****************************/
  66. void delay_nus(unsigned int n)//延时 程序 一次8+6(进出)=14us
  67. {
  68.         while(n--);
  69. }

  70. void reset(void)  //ds18b20初始化复位操作
  71. {
  72.          unsigned char x=0;
  73.          DQ = 1;                  //DQ复位
  74.          delay_nus(8);          //稍做延时
  75.          DQ = 0;                  //单片机将DQ拉低
  76.          delay_nus(80);         //精确延时 大于 480us
  77.          DQ = 1;                  //拉高总线
  78.          delay_nus(10);
  79.          x=DQ;                    //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
  80.          delay_nus(5);
  81. }

  82. void write_bit(unsigned char dat)        //DS18B20 写一位 操作
  83. {
  84.           DQ = 0;
  85.         _nop_();
  86.     _nop_();
  87.         DQ = dat&0x01;
  88.     delay_nus(5);
  89.         DQ = 1;
  90. }

  91. void write_byte(unsigned char dat)//写一个字节
  92. {
  93.         unsigned char i,j;
  94.         for (i=8; i>0; i--)
  95.         {
  96.                 j=dat&0x01;
  97.                   write_bit(j);
  98.                 dat>>=1;
  99.     }
  100. }

  101. unsigned char read_2bit(void)//读二位 子程序
  102. {
  103.         unsigned char i;
  104.         unsigned char dat = 0;
  105.         for (i=2;i>0;i--)
  106.         {
  107.                 DQ = 0; // 给脉冲信号
  108.                 dat<<=1;
  109.                 DQ = 1; // 给脉冲信号
  110.                 if(DQ)
  111.                 dat|=0x01;
  112.                 delay_nus(4);
  113.         }
  114.         return(dat);
  115. }

  116. unsigned char read_byte(void)//读一个字节 子程序
  117. {
  118.         unsigned char i=0;
  119.         unsigned char dat = 0;
  120.         for (i=8;i>0;i--)
  121.         {
  122.                 DQ = 0; // 给脉冲信号
  123.                 dat>>=1;
  124.                 DQ = 1; // 给脉冲信号
  125.                 if(DQ)
  126.                 dat|=0x80;
  127.                 delay_nus(4);
  128.         }
  129.         return(dat);  
  130. }



  131. void delay_nms(unsigned int n)
  132. {
  133.         unsigned int j=0;
  134.         unsigned char i=0;
  135.         for(j=0;j<n;j++)
  136.         {
  137.                 for(i=0;i<120;i++)
  138.                 {
  139.                         _nop_();
  140.                 }
  141.         }
  142. }
  143. /*******************************************************************************
  144. * 函 数 名         : read_temp
  145. * 函数功能                   : 读取某一个DS18B20的温度
  146. * 输    入         : 无
  147. * 输    出         : 无
  148. *******************************************************************************/
  149. void read_temp(unsigned char num_data)//读取温度 子程序 参数表示读第几个传感器
  150. {
  151.         unsigned char f;       
  152.         reset();                 //DS18B20复位
  153.         write_byte(0xcc);//发送跳过ROM号命令
  154.         write_byte(0x44);//发送温度转换命令
  155.         delay_nms(2000);//等待温度转换完               
  156.         reset();
  157.         write_byte(0x55);//发送匹配ROM号命令
  158.         for(f=0;f<8;f++) //一个ROM为8位
  159.         {
  160.                 write_byte(ID[num_data][f]);//发匹配ROM
  161.         }
  162.         delay_nus(100);
  163.         write_byte(0xbe);//发送读温度命令
  164.         delay_nus(100);
  165.         temp_l=read_byte();
  166.         temp_h=read_byte();
  167. }
  168. /*******************************************************************************
  169. * 函 数 名         : temp_convert
  170. * 函数功能                   : 将读取到的温度转换
  171. * 输    入         : 无
  172. * 输    出         : 无
  173. *******************************************************************************/

  174. void temp_convert(void)//温度转换
  175. {
  176.         negetiveflag=0;          //温度的符号标志位
  177.         negetiveflag=temp_h&0x80;
  178.         if(negetiveflag)   //温度为负
  179.         {
  180.                 negetiveflag=1;         //温度为负,温度标志位为1
  181.                 temp_h=~temp_h;
  182.                   if(temp_l==0)
  183.                 {
  184.                          temp_h++;  //若低8位全为0且温度为负,取补时就要向高位进1
  185.                 }
  186.                   temp_l=~temp_l+1;         //若温度为负,则求温度的绝对值(补码)
  187.         }
  188.         temp_h<<=4;
  189.         temp_l>>=4;                         //去除温度的小数部分
  190.         temp_over=temp_h|temp_l;  //留下8位的温度整数部分
  191.         tempalarm=temp_over;
  192.         if(negetiveflag==1)
  193.         {
  194.                  tempalarm=tempalarm*(-1);
  195.         }
  196. }

  197. /*******************************************************************************
  198. * 函 数 名         : search_cartoon
  199. * 函数功能                   : 搜索ROM动画的显示
  200. * 输    入         : 无
  201. * 输    出         : 无
  202. *******************************************************************************/
  203. void search_cartoon(void)//搜索ROM动画
  204. {
  205.         lcdinit();
  206.         LCD_write_com(0x80);//液晶第一行地址
  207.     for(i=0;i<16;i++)
  208.         {
  209.                 LCD_write_data(lcd0[i]); //显示"SEARCH ROMING..."字符
  210.         }
  211.         LCD_write_com(0xc0);//液晶第二行地址
  212.     for(i=0;i<16;i++)
  213.         {
  214.                 LCD_write_data(0xff);//显示类似进度条的黑点
  215.                 delay_nms(num*80);
  216.         }                 
  217. }
  218. /*******************************************************************************
  219. * 函 数 名         : display_alarm_normal
  220. * 函数功能                   : 显示报警温度
  221. * 输    入         : 无
  222. * 输    出         : 无
  223. *******************************************************************************/
  224. void display_alarm_normal(signed char alarm_data)//显示报警温度
  225. {
  226.         unsigned int data_b,data_temp,l,datx[6]={0};
  227.         data_b=alarm_data;
  228.         negetiveflag=0;                  //默认报警温度为正

  229.     LCD_write_com(0x80);
  230.         for(l=0;l<6;l++)
  231.         {
  232.                 LCD_write_data(pointinfo[l]);         //显示"ALARM:"字符
  233.         }   

  234.         if(alarm_data>=0)
  235.         {
  236.                 data_b=alarm_data/100;//显示报警温度百位
  237.         }
  238.         else
  239.         {
  240.                 negetiveflag=1;                        //报警温度为负
  241.                 alarm_data=alarm_data*(-1);//变成正温度
  242.         }

  243.         data_temp=alarm_data%100;//对100取余,也就是十位数和个位数

  244.         datx[0]=data_temp/10;//十位
  245.         datx[1]=data_temp%10;//个位
  246.         datx[2]=13;//空格符号
  247.         datx[3]=13;//空格符号
  248.         datx[4]=11;//摄氏度符号
  249.         datx[5]=12;//摄氏度符号

  250.         LCD_write_com(0x88);

  251.         if(negetiveflag==1)
  252.         {
  253.                 LCD_write_data(0x2d);//显示"-"  “负号”
  254.         }
  255.         else
  256.         {
  257.                 LCD_write_data(lcd4[data_b]);//如果大于0就显示百位数,否则百位数就显示“负号”
  258.         }

  259.         for(l=0;l<6;l++)//显示报警值和摄氏度符号
  260.         {
  261.           LCD_write_data(lcd4[datx[l]]);
  262.         }       
  263. }
  264. /*******************************************************************************
  265. * 函 数 名         : display_total
  266. * 函数功能                   : 显示报警温度
  267. * 输    入         : 无
  268. * 输    出         : 无
  269. *******************************************************************************/
  270. void display_total(void)          //显示搜索到的DS18B20传感器数目
  271. {
  272.         lcdinit();
  273.         LCD_write_com(0x80);//第一行地址
  274.     for(i=0;i<14;i++)
  275.         {
  276.                 LCD_write_data(lcd1[i]);        //显示"SEARCH ROM OK!"字符
  277.         }
  278.         LCD_write_com(0xc0);//第二行地址
  279.     for(i=0;i<13;i++)
  280.         {
  281.                 LCD_write_data(lcd2[i]);   //显示"THE TOTAL IS:"字符
  282.         }
  283.         LCD_write_data(lcd4[num]);
  284.         delay_nms(2000);
  285.         lcdinit();                                        //清屏,准备显示温度
  286.         display_alarm_normal(alarm);//显示报警温度
  287. }
  288. /*******************************************************************************
  289. * 函 数 名         : display_ds18b20
  290. * 函数功能                   : 显示编号为i的DS18B20的温度
  291. * 输    入         : 无
  292. * 输    出         : 无
  293. *******************************************************************************/
  294. void display_ds18b20(i)//显示编号为i的DS18B20的温度
  295. {
  296.         unsigned int data_b,data_temp,l;
  297.         data_b=temp_over/100;//百位
  298.         data_temp=temp_over%100;
  299.         dat[0]=data_temp/10;//十位
  300.         dat[1]=data_temp%10;//个位
  301.         dat[2]=13; //空格
  302.         dat[3]=13; //空格
  303.         dat[4]=11; //摄氏度符号
  304.         dat[5]=12; //摄氏度符号

  305.         LCD_write_com(0xc0);
  306.         for(l=0;l<7;l++)
  307.         {
  308.                 LCD_write_data(lcd3[l]); //显示"NO.[ ]:"字符
  309.         }
  310.         LCD_write_com(0xc4);
  311.         LCD_write_data(lcd4[++i]);// 依次显示"NO.[ ]:"字符串[ ]里的内容12345678
  312.         LCD_write_com(0xc8);

  313.         if(negetiveflag==1)
  314.         {
  315.                 LCD_write_data(0x2d);         //如果温度为负,显示“—"负号
  316.         }
  317.         else
  318.         {
  319.                 LCD_write_data(lcd4[data_b]);           //如果温度为正,显示温度百位
  320.         }

  321.         for(l=0;l<6;l++)
  322.                 LCD_write_data(lcd4[dat[l]]);        //显示温度的十位和个位
  323.         delay_nms(1000);
  324. }
  325. /*******************************************************************************
  326. * 函 数 名         : display_alarm
  327. * 函数功能                   : 显示 报警温度调节  的部分
  328. * 输    入         : 无
  329. * 输    出         : 无
  330. *******************************************************************************/
  331. void display_alarm(signed char alarm_data)//显示报警温度
  332. {
  333.         unsigned int data_b,data_temp,l;
  334.         data_b=alarm_data;
  335.         negetiveflag=0;
  336.         if(alarm_data>=0)         //报警温度大于0
  337.         {
  338.          data_b=alarm_data/100;//百位
  339.         }
  340.         else                                //报警温度小于0
  341.         {
  342.          negetiveflag=1;        //温度符号标志位
  343.          alarm_data=alarm_data*(-1);//变成正温度
  344.         }

  345.         data_temp=alarm_data%100;//对100取余,也就是十位数和个位数

  346.         dat[0]=data_temp/10;//十位
  347.         dat[1]=data_temp%10;//个位
  348.         dat[2]=13;//空格符号
  349.         dat[3]=11;//摄氏度符号
  350.         dat[4]=12;//摄氏度符号

  351.         if(keyflag==1)//刚刚进入设置报警温度
  352.         {
  353.             lcdinit();
  354.                 LCD_write_com(0x80);//第一行地址
  355.             for(l=0;l<16;l++)
  356.                 {
  357.                         LCD_write_data(setinfo[l]);        //显示"SET ALARM POINT:"字符
  358.                 }
  359.        
  360.                 LCD_write_com(0xc0);//第二行地址
  361.                 for(l=0;l<8;l++)
  362.                 {
  363.                         LCD_write_data(pointinfo[l]); //显示"ALARM:"字符
  364.                 }
  365.         }
  366.        

  367.         LCD_write_com(0xc7);

  368.         if(negetiveflag==1)                  //报警温度小于0
  369.         {
  370.                 LCD_write_data(0x2d);//显示"-"  “负号”
  371.         }
  372.         else                                          //报警温度大于0
  373.         {
  374.                 LCD_write_data(lcd4[data_b]);//如果大于0就显示百位数
  375.         }

  376.         for(l=0;l<5;l++)//显示报警值和摄氏度符号
  377.         {
  378.           LCD_write_data(lcd4[dat[l]]);
  379.         }       
  380. }
  381. /*******************************************************************************
  382. * 函 数 名         : display_alarm
  383. * 函数功能                   : 自动搜索ROM
  384. * 输    入         : 无
  385. * 输    出         : 无
  386. *******************************************************************************/
  387. void search_rom(void)//搜索ROM
  388. {
  389.         unsigned char k=0,l=0,chongtuwei=0,m=0,n=0;
  390.         unsigned char s=0;
  391.         unsigned char zhan[MAXNUM];
  392.         unsigned char ss[64];        //用来存放ROM,共m=8行,n=8列,一个RONM存放一行(即8位)
  393.         do
  394.         {
  395.                 reset();
  396.                 write_byte(0xf0);  //发送搜索ROM命令       
  397.                 for(m=0;m<8;m++)  //
  398.                 {
  399.                         for(n=0;n<8;n++)
  400.                         {
  401.                                 k=read_2bit();//读两位数据
  402.                                 k=k&0x03;   
  403.                                 s>>=1;
  404.                                 if(k==0x01)//01  有器件相连,在此为数据为上它们的数据为0
  405.                                 {                  
  406.                                         write_bit (0);
  407.                                     ss[(m*8+n)]=0;
  408.                                 }
  409.                                 else if(k==0x02)//01  有器件相连,在此为数据为上它们的数据为1
  410.                                 {
  411.                                         s=s|0x80;
  412.                                         write_bit (1);
  413.                                         ss[(m*8+n)]=1;
  414.                                 }
  415.                                 else if(k==0x00)//00  有器件相连,在此为数据为上它们的数据发送冲突即就有1也有0
  416.                                 {                                //如果冲突位大于栈顶写0 小于栈顶写以前数据 等于栈顶写1
  417.                                         chongtuwei=m*8+n+1;                                       
  418.                                         if(chongtuwei>zhan[l])
  419.                                         {                                               
  420.                                                 write_bit (0);
  421.                                                 ss[(m*8+n)]=0;                                                                                               
  422.                                                 zhan[++l]=chongtuwei;                                               
  423.                                         }
  424.                                         else if(chongtuwei<zhan[l])
  425.                                         {
  426.                                                 s=s|((ss[(m*8+n)]&0x01)<<7);
  427.                                                 write_bit (ss[(m*8+n)]);
  428.                                         }
  429.                                         else if(chongtuwei==zhan[l])
  430.                                         {
  431.                                                 s=s|0x80;
  432.                                                 write_bit (1);
  433.                                                 ss[(m*8+n)]=1;
  434.                                                 l=l-1;
  435.                                         }
  436.                                 }
  437.                                 else
  438.                                 {
  439.                                         goto loop;
  440.                                 }
  441.                         }
  442.                         ID[num][m]=s;               
  443.                 }
  444.                 num++;
  445.         }
  446.         while(zhan[l]!=0&&(num<MAXNUM));               
  447. loop:
  448.         search_cartoon();
  449.         display_total();

  450. }



  451. void main (void)
  452. {
  453.         unsigned char i=0,t=0;
  454.         delay_nms(50);
  455.         IT0=0;
  456.         EX0=1;
  457.         EA=1;

  458.     search_rom();//搜索ROM并且存储,把18B20的每一个ROM读取出来,方便下次调用


  459.         reset();
  460.                
  461.         while(1)
  462.         {
  463.                 if(keyflag==0)
  464.                 {
  465.                           for(i=0;i<num;i++)        //每一个 ds18b20 循环显示
  466.                           {
  467.                                         if(keyflag==1) break;
  468.                                         read_temp(i);   //读编号 i 的ds18b20 的温度
  469.                                         if(keyflag==1) break;
  470.                                         temp_convert(); //调用温度转换
  471.                                         if(keyflag==1) break;
  472.                                     if(tempalarm>alarm)//报警判断
  473.                                         {
  474.                                           for(t=0;t<3;t++)
  475.                                           {
  476.                                                    buzzer=0;//打开报警蜂鸣器
  477.                                                  led=0;   //打开报警指示灯
  478.                                                  delay_nms(100);
  479.                                                  buzzer=1;//关闭报警蜂鸣器
  480.                                                  led=1;   //关闭报警指示灯
  481.                                                  delay_nms(100);
  482.                                           }
  483.                                         }
  484.                                 display_ds18b20(i);//显示 编号 i 的温度               
  485.                       }
  486.                 }                  

  487.                 else//设置按键按下 进行按键扫描动作
  488.                 {
  489.                    display_alarm(alarm);
  490.                    keyflag=0;
  491.                    while(1)
  492.                    {
  493.                             if(keyenter==0&&keyflag==0)//进入设置以后,再按设置按键,就退出设置,重新显示每一个通道温度
  494.                                 {
  495.                                   delay_nms(200);
  496.                                   if(keyenter==0)
  497.                                   {
  498.                                         while(keyenter==0);         
  499.                                         lcdinit();
  500.                                         display_alarm_normal(alarm);//显示报警温度
  501.                                         break;//退出按键扫描
  502.                                   }
  503.                                 }
  504.                         if(keyup==0)//
  505.                                 {
  506.                                   delay_nms(200);
  507.                                   if(keyup==0&&alarm<125)
  508.                                   {
  509.                                          alarm++;//报警温度加1
  510.                                   }
  511.                                   display_alarm(alarm);
  512.                                 }
  513.                    if(keydown==0&&alarm>-55)//
  514.                                 {
  515.                                   delay_nms(200);
  516.                                   if(keydown==0)
  517.                                   {
  518.                                         alarm--;//报警温度减1
  519.                                   }
  520.                                   display_alarm(alarm);
  521.                                 }
  522.                                 delay_nms(50);
  523.                    }
  524.                    EX0=1;       
  525.                 }
  526.                              
  527.         }//while(1)结束  
  528. }

  529. void key_init0(void) interrupt 0
  530. {
  531.         if(keyenter==0)
  532.         {
  533.           delay_nms(10);
  534.           if(keyenter==0)
  535.           {
  536.                   EX0=0;
  537.                 keyflag=1;
  538.           }
  539.         }
  540.        
  541. }
复制代码

所有资料51hei提供下载:
仿真文件.zip (49.24 KB, 下载次数: 142)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:89286 发表于 2019-3-27 00:20 | 显示全部楼层
thanks for sharing
回复

使用道具 举报

ID:521711 发表于 2019-5-9 10:34 | 显示全部楼层
请问有没有联系方式,或者你加我qq943120061,想请教问题,谢谢
回复

使用道具 举报

ID:60453 发表于 2019-5-30 09:00
垃圾,骗人的,不能用

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表