久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1296|回復: 2
打印 上一主題 下一主題
收起左側

51單片機寫的溫度報警器程序,下載到板子上功能是正常的,用Protues仿真不了

[復制鏈接]
跳轉到指定樓層
樓主
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define T_MAX 25 // 最大溫度限定值
  4. #define T_MIN 22 // 最小溫度限定值

  5. sbit BUZZ = P1^6;
  6. //_nop_()函數所在頭文件


  7. /*----------------音樂函數申明------------------------------*/
  8. void InitBuzz();
  9. bit isBuzz = 0; //蜂鳴器是否在響


  10. /*----------------溫度傳感器申明----------------------------*/
  11. bit Start18B20();                        //初始化DS18B20
  12. bit Get18B20Temp(int *temp);//讀取溫度
  13. bit isGetTemp = 0;                   //是否在獲取溫度


  14. /*----------------LCD1602顯示模塊申明------------------------*/
  15. void InitLcd1602();                        //LCD1602初始化函數
  16. void display();                        //顯示控制模塊

  17. /*-------------------LCD1602顯示緩存-------------------------*/
  18. //LCD1602函數調用申明
  19. void LcdShowStr(unsigned char x, unsigned char y,unsigned char *str, unsigned char len);
  20. unsigned char strbuff[4];//格式:“25°C”
  21. unsigned char code waringStrHot[] = "      Hot!      ";//報警顯示文字
  22. unsigned char code waringStrCol[] = "      Cold!     ";//報警顯示文字
  23. unsigned char code striswaring[] = "            ";//取消報警顯示文字


  24. /*----------------------其他全局變量-------------------------*/
  25. int Temp = 0;                //讀取到的當前溫度值(16bit二進制)
  26. int intT;                        //溫度值的整數和小數部分
  27. bit iswaring = 0;        //是否報警標志位


  28. void main()
  29. {
  30. //        int n = 0;
  31. //        char s[1];
  32.         bit isReay = 0;
  33.         bit sta;                                //是否成功讀取標志
  34.         unsigned int cnt = 0;        //檢測標志,主要用于控制檢測溫度的頻率
  35.         
  36.         InitBuzz();                                        //蜂鳴器初始化
  37.         Start18B20();                        //啟動DS18B20
  38.   InitLcd1602();              //初始化LCD1602液晶模塊
  39.         
  40.         while(1)
  41. {
  42.                 if(isReay == 0)
  43.                 {
  44.                         cnt++;
  45.                 }

  46.                 if((cnt>28000&&isBuzz == 0)||(cnt>14000&&isBuzz == 1))                                 //大約0.8s(仿真得到) DS18B20最多750ms轉化好
  47.                 {
  48.                         cnt = 0;
  49.                         isReay = 1;
  50.                 }
  51.                   
  52.                 if(isReay == 1 && isBuzz == 0)
  53.                 {
  54. //                        n++;
  55. //                        s[0] = n+'0';
  56. //                        LcdShowStr(0, 0,s, 1);
  57.                         isGetTemp = 1;
  58.                         sta = Get18B20Temp(&Temp);        //讀取當前溫度
  59.                         isGetTemp = 0;
  60.                         if (sta)                                        //讀取成功時,刷新當前溫度顯示
  61.                         {
  62.                                 intT = Temp >> 4;                //分離出溫度值整數部分
  63.                         }
  64.                         Start18B20();                                        //重新啟動下一次轉換
  65.         
  66.                         if(intT > T_MAX || intT < T_MIN)
  67.                         {
  68.                                 iswaring = 1;
  69.                         }else{
  70.                                 iswaring = 0;
  71.                         }

  72.                         isReay = 0;
  73.                 }

  74.                 display();//顯示
  75.         }
  76. }

  77. /*-----------------------以下是LCD1602顯示驅動------------------*/
  78. //定義LCD1602顯示相關的IO接口
  79. #define LCD1602_DB  P0
  80. sbit LCD1602_RS = P1^0;
  81. sbit LCD1602_RW = P1^1;
  82. sbit LCD1602_E  = P1^5;


  83. //顯示控制模塊
  84. void display()
  85. {
  86.         static int intTb;        //溫度值的整數部分備份
  87.         static bit isBuzzb;

  88.         if(isBuzzb != isBuzz)
  89.         {
  90.                 if(isBuzz == 0 && iswaring == 1)
  91.                 {
  92.                         if(intT > T_MAX)
  93.                         {
  94.                                 LcdShowStr(0,1,waringStrHot,16);
  95.                         }else{
  96.                                 LcdShowStr(0,1,waringStrCol,16);
  97.                         }
  98.                         
  99.                 }else{
  100.                         LcdShowStr(0,1,striswaring,11);
  101.                 }
  102.                 isBuzzb = isBuzz;
  103.         }

  104.         if(intTb != intT)//如果有變化
  105.         {
  106.                 /*備份當前值*/
  107.                 intTb = intT;
  108.                
  109.                 if((intT/10) == 0)strbuff[0] = ' ';else strbuff[0] = ((intT/10)%10)+0x30;//十位
  110.                 strbuff[1] = ((intT/1)%10)+0x30;//個位

  111.                 LcdShowStr(6,0,strbuff,4);        //顯示,初始位置隨意,只要能顯示完整就好
  112.         }
  113. }

  114. //等待液晶準備好
  115. void LcdWaitReady()
  116. {
  117.     unsigned char sta;
  118.      
  119.     LCD1602_DB = 0xFF;
  120.     LCD1602_RS = 0;
  121.     LCD1602_RW = 1;
  122.     do {
  123.         LCD1602_E = 1;      //使能LCD1602
  124.         sta = LCD1602_DB;   //讀取狀態字
  125.         LCD1602_E = 0;      //避免干擾其他器件
  126.     } while (sta & 0x80);   //第七位等于1表示液晶正忙,重復檢測直到第七位等于0為止
  127. }
  128. //向LCD1602液晶寫入一字節命令,cmd為待寫入命令值
  129. void LcdWriteCmd(unsigned char cmd)
  130. {
  131.     LcdWaitReady();
  132.     LCD1602_RS = 0;
  133.     LCD1602_RW = 0;
  134.     LCD1602_DB = cmd;
  135.     LCD1602_E  = 1;
  136.     LCD1602_E  = 0;
  137. }
  138. //向LCD1602液晶寫入一字節數據,dat為待寫入數據值
  139. void LcdWriteDat(unsigned char dat)
  140. {
  141.     LcdWaitReady();
  142.     LCD1602_RS = 1;
  143.     LCD1602_RW = 0;
  144.     LCD1602_DB = dat;
  145.     LCD1602_E  = 1;
  146.     LCD1602_E  = 0;
  147. }
  148. //設置顯示RAM起始地址,亦即光標位置,(x,y)對應屏幕上的字符的坐標
  149. void LcdSetCursor(unsigned char x, unsigned char y)
  150. {
  151.     unsigned char addr;
  152.      
  153.     if (y == 0)                          //由輸入的屏幕坐標計算顯示RAM的地址
  154.         addr = 0x00 + x;        //第一行字符地址從0x00起始
  155.     else
  156.         addr = 0x40 + x;        //第二行字符地址從0x40起始
  157.     LcdWriteCmd(addr | 0x80);        //設置RAM地址
  158. }
  159. //在液晶上顯示字符串,(x,y)-對應屏幕上的起始坐標,
  160. //str-字符串指針,len-需顯示的字符長度
  161. void LcdShowStr(unsigned char x, unsigned char y,unsigned char *str, unsigned char len)
  162. {
  163.     LcdSetCursor(x, y);   //設置起始地址
  164.     while (len--)         //連續寫入len個字符數據
  165.     {
  166.         LcdWriteDat(*str++);  //先取str指向的數據,然后str自加1
  167.     }
  168. }

  169. void InitLcd1602()//初始化1602液晶
  170. {
  171.         strbuff[2] = 0XDF;
  172.         strbuff[3] = 'C';

  173.     LcdWriteCmd(0x38);  //16*2顯示,5*7點陣,8位數據接口
  174.     LcdWriteCmd(0x0C);  //顯示器開,光標關閉
  175.     LcdWriteCmd(0x06);  //文字不動,地址自動+1
  176.     LcdWriteCmd(0x01);  //清屏
  177. }


  178. /*-----------------------以下是溫度傳感器驅動------------------*/
  179. //DS18B20通信引腳
  180. sbit IO_18B20 = P3^2;
  181. void DelayX10us(unsigned char t)
  182. {
  183.     do {
  184.         _nop_();
  185.         _nop_();
  186.         _nop_();
  187.         _nop_();
  188.         _nop_();
  189.         _nop_();
  190.         _nop_();
  191.         _nop_();
  192.     } while (--t);
  193.     /*_nop_()函數在12M晶振中延遲1us,為什么這里是8個_nop_()
  194.         因為while和--t也是需要時間的,這里不一定是準確的10us/循環
  195.         只是大致的時間*/
  196. }
  197. bit Get18B20Ack() //DS18B20存在檢測函數
  198. {
  199.         bit ack;

  200.         EA = 0;                                //關中斷
  201.         IO_18B20 = 0;                //拉低引腳
  202.         DelayX10us(50);                //延時500us(480us - 960us)
  203.         IO_18B20 = 1;                //釋放總線
  204.         DelayX10us(6);                //延時60us(15us - 60us)
  205.         ack = IO_18B20;                //讀取響應(60us - 240us)
  206.         while(!IO_18B20);        //等待DS18B20釋放總線 (60us - 240us)
  207.         EA = 1;                                //取消關中斷

  208.         return ack;                        //返回是否存在 (0:存在 1:不存在)
  209. }

  210. void  Write18B20(unsigned char dat) //寫DS18B20
  211. {
  212.         unsigned char mask;                        //臨時變量定義
  213.         EA = 0;                                                //關中斷
  214.         for(mask=0x01; mask!= 0; mask<<=1)        //循環發送單個bit位
  215.         {
  216.                 IO_18B20 = 0;                        //拉低(請求讀寫操作)
  217.                 _nop_();                                //延時(1us < time <= 15us)
  218.                 _nop_();
  219.                 if((mask&dat) == 0)                //按位讀取dat
  220.                         IO_18B20 = 0;                //本位是0,拉低
  221.                 else
  222.                         IO_18B20 = 1;                //本位是1,拉高
  223.                         //上面這個操作DS18B20讀。ㄗ钚r間 0us<time<15us,
  224.                         //典型時間 15us,最大時間45us)
  225.                 DelayX10us(6);                        //等待60us(足夠DS18B20讀取)
  226.                 IO_18B20 = 1;                        //釋放總線
  227.         }
  228.         EA = 1;                                                //取消關中斷
  229. }

  230. unsigned char Read18B20()                //讀DS18B20
  231. {
  232.         unsigned char dat;                        //數據緩存變量
  233.         unsigned char mask;                        //臨時變量

  234.         EA = 0;                                                //關中斷
  235.         for(mask=0x01; mask!=0; mask<<=1)//同上循環按位操作
  236.         {
  237.                 IO_18B20 = 0;                        //讀寫請求
  238.                 _nop_();                                //等待(1us < time < 15us)
  239.                 _nop_();
  240.                 IO_18B20 = 1;                        //初始化讀操作
  241.                 _nop_();                                //等待DS18B20輸出
  242.                 _nop_();
  243.                 if(!IO_18B20)                        //讀
  244.                         dat &= ~mask;                //“0”
  245.                 else
  246.                         dat |= mask;                //“1”
  247.                 DelayX10us(6);                        //等待DS18B20釋放總線
  248.         }
  249.         EA = 1;                                                //取消關中斷

  250.         return dat;                                        //返回數據
  251. }

  252. bit Start18B20()                //初始化DS18B20
  253. {
  254.         bit ack;                        //存在標志

  255.         ack = Get18B20Ack();//檢測存在
  256.         if(ack == 0)                //存在
  257.         {                                        //寫命令使工作
  258.                 Write18B20(0xCC);         //跳過ROM檢測
  259.                 Write18B20(0x44);        //啟動溫度轉換
  260.         }
  261.         return ~ack;                //返回是否成功(1是,0否)
  262. }

  263. bit Get18B20Temp(int *temp)        //獲取DS18B20溫度存于temp
  264. {
  265.         bit ack;                                //存在標志
  266.         unsigned char LSB, MSB;        //數據低/高位

  267.         ack = Get18B20Ack();        //檢測存在
  268.         if(ack == 0)                        //存在
  269.         {                                                //寫指令
  270.                 Write18B20(0xCC);        //跳過ROM檢測
  271.                 Write18B20(0xBE);        //讀寄存器
  272.                 LSB = Read18B20();        //讀低位
  273.                 MSB = Read18B20();        //讀高位
  274.                 *temp = ((int)MSB<<8) + LSB;        //合并
  275.         }
  276.         return ~ack;                        //返回結果(1成功,0失敗)
  277. }

  278. //下面是蜂鳴器
  279. void InterruptTimer0() interrupt 1
  280. {
  281.         static unsigned int timer;
  282.         TH0 = 0x00;
  283.         TL0 = 0x00;
  284.         timer++;
  285.         if(iswaring)
  286.         {
  287.                 if(timer>3000)
  288.                 {
  289.                         isBuzz = 1;

  290.                         if(timer%5==1)
  291.                         {
  292.                                 BUZZ = ~BUZZ;
  293.                         }

  294.                         if(timer>6000)
  295.                         {
  296.                                 timer = 0;        
  297.                         }
  298.                 }else{
  299.                         isBuzz = 0;
  300.                 }
  301.         }else{
  302.                 isBuzz = 0;
  303.         }
  304. }

  305. void InitBuzz()
  306. {
  307.         TMOD = 0x02;
  308.         TR0 = 1;
  309.         ET0 = 1;        
  310. }

復制代碼


51hei圖片20221122091640.png (352.25 KB, 下載次數: 77)

51hei圖片20221122091640.png

51hei圖片20221122091449.png (45.99 KB, 下載次數: 76)

51hei圖片20221122091449.png
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:161164 發表于 2022-11-22 14:14 | 只看該作者
部份版本的Protues LCD1602仿真不支援查忙 于是你的程序在while (sta & 0x80);中死循環了

回復

使用道具 舉報

板凳
ID:77589 發表于 2022-11-23 15:05 | 只看該作者
Protues仿真對程序要求更嚴謹,也就是說在實物上通過的代碼,在Protues上仿真不一定能過;在Protues上仿真能過,電路一樣的情況下,在實物板上基本都能過。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久久大陆 | 91精品国产综合久久精品 | 天天射网站 | 亚洲高清网 | 国产三级一区二区 | 91在线精品秘密一区二区 | 超碰国产在线 | 精品国产黄a∨片高清在线 成人区精品一区二区婷婷 日本一区二区视频 | 国产婷婷精品av在线 | 欧美精品网站 | 在线观看国产 | 女人天堂av | 日韩不卡一区二区 | 99视频在线 | 日本欧美在线视频 | 色婷婷久久综合 | 欧美一区二区三区四区视频 | 欧美区在线 | 美女天天干天天操 | 精品国产一区二区国模嫣然 | 91精品久久久久久久久 | 精品成人免费一区二区在线播放 | 亚洲一区二区三区免费在线观看 | 国产成人精品一区二区三区在线 | 日韩在线免费视频 | 欧美日本亚洲 | www.亚洲免费 | 免费黄色在线观看 | 一级欧美视频 | 亚洲欧美第一视频 | 国产精品久久免费观看 | 精品一区二区三区不卡 | 国产精品亚洲一区二区三区在线 | 亚洲精品亚洲人成人网 | 毛片高清 | 天天躁日日躁性色aⅴ电影 免费在线观看成年人视频 国产欧美精品 | 午夜在线精品偷拍 | 欧美在线小视频 | 日韩精品在线观看免费 | 视频一区二区在线观看 | 欧美日韩国产传媒 |