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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4658|回復: 0
收起左側

單片機室內一氧化碳報警設計源碼

[復制鏈接]
ID:295874 發表于 2018-4-27 16:44 | 顯示全部樓層 |閱讀模式
本設計程序代碼實現室內CO濃度值的在線監測,并可實現報警設定功能。可以互相學習 。,

單片機源程序如下:
  1. #include <reg52.h>                 //調用單片機頭文件
  2. #define uchar unsigned char  //無符號字符型 宏定義        變量范圍0~255
  3. #define uint  unsigned int         //無符號整型 宏定義        變量范圍0~65535

  4. #include <intrins.h>
  5. //#include "lcd1602.h"

  6. sbit CS=P1^3;                //CS定義為P2口的第4位腳,連接ADC0832CS腳
  7. sbit SCL=P1^0;                //SCL定義為P2口的第3位腳,連接ADC0832SCL腳
  8. sbit DO=P1^1;                //DO定義為P2口的第4位腳,連接ADC0832DO腳

  9. sbit beep = P2^0;   //蜂鳴器IO口定義
  10. long dengji,s_dengji = 50;     //濃度等級


  11. bit flag_300ms ;
  12. uchar key_can;                 //按鍵值的變量
  13. uchar menu_1;        //菜單設計的變量
  14. uchar flag_clock;

  15. //這三個引腳參考資料
  16. sbit rs=P1^2;         //1602數據/命令選擇引腳 H:數據              L:命令
  17. //sbit rw=P2^6;         //1602讀寫引腳                 H:數據寄存器          L:指令寄存器
  18. sbit e =P1^4;         //1602使能引腳          下降沿觸發
  19. uchar code table_num[]="0123456789abcdefg";

  20. /********************************************************************
  21. * 名稱 : delay_uint()
  22. * 功能 : 小延時。
  23. * 輸入 : 無
  24. * 輸出 : 無
  25. ***********************************************************************/
  26. void delay_uint(uint q)
  27. {
  28.         while(q--);
  29. }

  30. /********************************************************************
  31. * 名稱 : write_com(uchar com)
  32. * 功能 : 1602命令函數
  33. * 輸入 : 輸入的命令值
  34. * 輸出 : 無
  35. ***********************************************************************/
  36. void write_com(uchar com)
  37. {
  38.         e=0;
  39.         rs=0;
  40. //        rw=0;
  41.         P0=com;
  42.         delay_uint(3);
  43.         e=1;
  44.         delay_uint(25);
  45.         e=0;
  46. }

  47. /********************************************************************
  48. * 名稱 : write_data(uchar dat)
  49. * 功能 : 1602寫數據函數
  50. * 輸入 : 需要寫入1602的數據
  51. * 輸出 : 無
  52. ***********************************************************************/
  53. void write_data(uchar dat)
  54. {
  55.         e=0;
  56.         rs=1;
  57. //        rw=0;
  58.         P0=dat;
  59.         delay_uint(3);
  60.         e=1;
  61.         delay_uint(25);
  62.         e=0;       
  63. }

  64. /********************************************************************
  65. * 名稱 : write_sfm2(uchar hang,uchar add,uchar date)
  66. * 功能 : 顯示2位十進制數,如果要讓第一行,第五個字符開始顯示"23" ,調用該函數如下
  67.                   write_sfm1(1,5,23)
  68. * 輸入 : 行,列,需要輸入1602的數據
  69. * 輸出 : 無
  70. ***********************************************************************/
  71. void write_sfm2(uchar hang,uchar add,uint date)
  72. {
  73.         if(hang==1)   
  74.                 write_com(0x80+add);
  75.         else
  76.                 write_com(0x80+0x40+add);
  77.         if(date >= 100)
  78.         {
  79.                 write_data(0x30+date/100%10);
  80.                 write_data(0x30+date/10%10);
  81.         }
  82.         else
  83.         {
  84.                 write_data(' ');
  85.                 write_data(0x30+date/10%10);
  86.         }
  87.         write_data(0x30+date%10);       
  88. }

  89. /********************************************************************
  90. * 名稱 : write_string(uchar hang,uchar add,uchar *p)
  91. * 功能 : 改變液晶中某位的值,如果要讓第一行,第五個字符開始顯示"ab cd ef" ,調用該函數如下
  92.                   write_string(1,5,"ab cd ef;")
  93. * 輸入 : 行,列,需要輸入1602的數據
  94. * 輸出 : 無
  95. ***********************************************************************/
  96. void write_string(uchar hang,uchar add,uchar *p)
  97. {
  98.         if(hang==1)   
  99.                 write_com(0x80+add);
  100.         else
  101.                 write_com(0x80+0x40+add);
  102.                 while(1)
  103.                 {
  104.                         if(*p == '\0')  break;
  105.                         write_data(*p);
  106.                         p++;
  107.                 }       
  108. }

  109. /********************************************************************
  110. * 名稱 : clear_1602()
  111. * 功能 : 清除1602顯示
  112. * 輸入 : 無
  113. * 輸出 : 無
  114. ***********************************************************************/
  115. void clear_1602()
  116. {
  117.         write_string(1,0,"                ");
  118.         write_string(2,0,"                ");
  119. }

  120. /***********************lcd1602上顯示特定的字符************************/
  121. void write_zifu(uchar hang,uchar add,uchar date)
  122. {
  123.         if(hang==1)   
  124.                 write_com(0x80+add);
  125.         else
  126.                 write_com(0x80+0x40+add);
  127.         write_data(date);       
  128. }


  129. /********************************************************************
  130. * 名稱 : init_1602()
  131. * 功能 : 初始化1602液晶
  132. * 輸入 : 無
  133. * 輸出 : 無
  134. ***********************************************************************/
  135. void init_1602()
  136. {
  137.         write_com(0x38);
  138.         write_com(0x0c);
  139.         write_com(0x06);
  140.         write_string(1,0," thickne: 00    ");
  141.         write_string(2,0," Thresho: 80    ");
  142.         write_sfm2(2,9,s_dengji);                   //顯示濃度等級
  143. }

  144. uchar a_a;

  145. /********STC89C51扇區分布*******
  146. 第一扇區:1000H--11FF
  147. 第二扇區:1200H--13FF
  148. 第三扇區:1400H--15FF
  149. 第四扇區:1600H--17FF
  150. 第五扇區:1800H--19FF
  151. 第六扇區:1A00H--1BFF
  152. 第七扇區:1C00H--1DFF
  153. 第八扇區:1E00H--1FFF
  154. *****************/

  155. /********STC89C52扇區分布*******
  156. 第一扇區:2000H--21FF
  157. 第二扇區:2200H--23FF
  158. 第三扇區:2400H--25FF
  159. 第四扇區:2600H--27FF
  160. 第五扇區:2800H--29FF
  161. 第六扇區:2A00H--2BFF
  162. 第七扇區:2C00H--2DFF
  163. 第八扇區:2E00H--2FFF
  164. *****************/


  165. #define RdCommand 0x01 //定義ISP的操作命令
  166. #define PrgCommand 0x02
  167. #define EraseCommand 0x03
  168. #define Error 1
  169. #define Ok 0
  170. #define WaitTime 0x01 //定義CPU的等待時間
  171. sfr ISP_DATA=0xe2;  //寄存器申明
  172. sfr ISP_ADDRH=0xe3;
  173. sfr ISP_ADDRL=0xe4;
  174. sfr ISP_CMD=0xe5;
  175. sfr ISP_TRIG=0xe6;
  176. sfr ISP_CONTR=0xe7;

  177. /* ================ 打開 ISP,IAP 功能 ================= */
  178. void ISP_IAP_enable(void)
  179. {
  180.          EA = 0;       /* 關中斷   */
  181.          ISP_CONTR = ISP_CONTR & 0x18;       /* 0001,1000 */
  182.          ISP_CONTR = ISP_CONTR | WaitTime; /* 寫入硬件延時 */
  183.          ISP_CONTR = ISP_CONTR | 0x80;       /* ISPEN=1  */
  184. }
  185. /* =============== 關閉 ISP,IAP 功能 ================== */
  186. void ISP_IAP_disable(void)
  187. {
  188.          ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
  189.          ISP_TRIG = 0x00;
  190.          EA   =   1;   /* 開中斷 */
  191. }
  192. /* ================ 公用的觸發代碼 ==================== */
  193. void ISPgoon(void)
  194. {
  195.          ISP_IAP_enable();   /* 打開 ISP,IAP 功能 */
  196.          ISP_TRIG = 0x46;  /* 觸發ISP_IAP命令字節1 */
  197.          ISP_TRIG = 0xb9;  /* 觸發ISP_IAP命令字節2 */
  198.          _nop_();
  199. }
  200. /* ==================== 字節讀 ======================== */
  201. unsigned char byte_read(unsigned int byte_addr)
  202. {
  203.         EA = 0;
  204.          ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址賦值 */
  205.          ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  206.          ISP_CMD   = ISP_CMD & 0xf8;   /* 清除低3位  */
  207.          ISP_CMD   = ISP_CMD | RdCommand; /* 寫入讀命令 */
  208.          ISPgoon();       /* 觸發執行  */
  209.          ISP_IAP_disable();    /* 關閉ISP,IAP功能 */
  210.          EA  = 1;
  211.          return (ISP_DATA);    /* 返回讀到的數據 */
  212. }
  213. /* ================== 扇區擦除 ======================== */
  214. void SectorErase(unsigned int sector_addr)
  215. {
  216.          unsigned int iSectorAddr;
  217.          iSectorAddr = (sector_addr & 0xfe00); /* 取扇區地址 */
  218.          ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
  219.          ISP_ADDRL = 0x00;
  220.          ISP_CMD = ISP_CMD & 0xf8;   /* 清空低3位  */
  221.          ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3  */
  222.          ISPgoon();       /* 觸發執行  */
  223.          ISP_IAP_disable();    /* 關閉ISP,IAP功能 */
  224. }
  225. /* ==================== 字節寫 ======================== */
  226. void byte_write(unsigned int byte_addr, unsigned char original_data)
  227. {
  228.          EA  = 0;
  229. //         SectorErase(byte_addr);
  230.          ISP_ADDRH = (unsigned char)(byte_addr >> 8);  /* 取地址  */
  231.          ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  232.          ISP_CMD  = ISP_CMD & 0xf8;    /* 清低3位 */
  233.          ISP_CMD  = ISP_CMD | PrgCommand;  /* 寫命令2 */
  234.          ISP_DATA = original_data;   /* 寫入數據準備 */
  235.          ISPgoon();       /* 觸發執行  */
  236.          ISP_IAP_disable();     /* 關閉IAP功能 */
  237.          EA =1;
  238. }


  239. /***********************1ms延時函數*****************************/
  240. void delay_1ms(uint q)
  241. {
  242.         uint i,j;
  243.         for(i=0;i<q;i++)
  244.                 for(j=0;j<120;j++);
  245. }


  246. /******************把數據保存到單片機內部eeprom中******************/
  247. void write_eeprom()
  248. {
  249.         SectorErase(0x2000);
  250. //        byte_write(0x2000, s_dengji);
  251.         byte_write(0x2001, s_dengji);
  252.         byte_write(0x2060, a_a);       
  253. }

  254. /******************把數據從單片機內部eeprom中讀出來*****************/
  255. void read_eeprom()
  256. {
  257. //        s_dengji   = byte_read(0x2000);
  258.         s_dengji = byte_read(0x2001);
  259.         a_a      = byte_read(0x2060);
  260. }

  261. /**************開機自檢eeprom初始化*****************/
  262. void init_eeprom()
  263. {
  264.         read_eeprom();                //先讀
  265.         if(a_a != 2)                //新的單片機初始單片機內問eeprom
  266.         {
  267.                 s_dengji = 80;
  268.                 a_a = 2;
  269.                 write_eeprom();
  270.         }       
  271. }

  272. /***********讀數模轉換數據********************************************************/       
  273. //請先了解ADC0832模數轉換的串行協議,再來讀本函數,主要是對應時序圖來理解,本函數是模擬0832的串行協議進行的
  274.                                                 //  1  0  0 通道
  275.                                                 //  1  1  1 通道
  276. unsigned char ad0832read(bit SGL,bit ODD)
  277. {
  278.         unsigned char i=0,value=0,value1=0;               
  279.                 SCL=0;
  280.                 DO=1;
  281.                 CS=0;                //開始
  282.                 SCL=1;                //第一個上升沿       
  283.                 SCL=0;
  284.                 DO=SGL;
  285.                 SCL=1;          //第二個上升沿
  286.                 SCL=0;
  287.                 DO=ODD;
  288.                 SCL=1;            //第三個上升沿
  289.                 SCL=0;            //第三個下降沿
  290.                 DO=1;
  291.                 for(i=0;i<8;i++)
  292.                 {
  293.                         SCL=1;
  294.                         SCL=0; //開始從第四個下降沿接收數據
  295.                         value<<=1;
  296.                         if(DO)
  297.                                 value++;                                               
  298.                 }
  299.                 for(i=0;i<8;i++)
  300.                 {                        //接收校驗數據
  301.                         value1>>=1;
  302.                         if(DO)
  303.                                 value1+=0x80;
  304.                         SCL=1;
  305.                         SCL=0;
  306.                 }
  307.                 CS=1;
  308.                 SCL=1;       
  309.                 if(value==value1)                                //與校驗數據比較,正確就返回數據,否則返回0       
  310.                         return value;
  311.         return 0;
  312. }


  313. /*************定時器0初始化程序***************/
  314. void time_init()          
  315. {
  316.         EA   = 1;                   //開總中斷
  317.         TMOD = 0X01;          //定時器0、定時器1工作方式1
  318.         ET0  = 1;                  //開定時器0中斷
  319.         TR0  = 1;                  //允許定時器0定時
  320. }

  321. /****************按鍵處理顯示函數***************/
  322. void key_with()
  323. {
  324.         if(key_can == 1)
  325.         {
  326.                 s_dengji ++ ;                    //濃度設置數加1
  327.                 if(s_dengji > 999)
  328.                         s_dengji = 999;
  329.         }
  330.         if(key_can == 2)
  331.         {
  332.                         s_dengji -= 1;        //濃度設置數減1
  333.                 if(s_dengji <= 1)
  334.                         s_dengji = 1 ;
  335.         }
  336.         write_sfm2(2,9,s_dengji);                   //顯示濃度等級
  337.         write_eeprom();       //保存數據                                       
  338.                        
  339. }  

  340. /********************獨立按鍵程序*****************/
  341. uchar key_can;         //按鍵值
  342. sbit key1=P1^5;
  343. sbit key2=P3^3;
  344. void key()         //獨立按鍵程序
  345. {
  346.         static uchar key_new;
  347.         key_can = 20;                   //按鍵值還原
  348.         key1 = 1;
  349.         key2 = 1;
  350.         if((key1==0)||(key2==0))                //按鍵按下
  351.         {
  352.                 delay_1ms(1);                     //按鍵消抖動
  353.                 if(((key1==0)||(key2==0)) && (key_new == 1))
  354.                 {                                                //確認是按鍵按下
  355.                         key_new = 0;
  356.                         if(key1==0) key_can = 1;
  357.                         if(key2==0) key_can = 2;
  358.                 }                       
  359.         }
  360.         else
  361.                 key_new = 1;       
  362. }

  363. /****************報警函數***************/
  364. void clock_h_l()
  365. {
  366.         static uchar value;
  367.         if(dengji >= s_dengji )                //報警
  368.         {
  369.                 value ++;
  370.                 if(value >= 2)
  371.                 {
  372.                         value = 10;
  373.                         beep = ~beep;          //蜂鳴器報警
  374.                 }
  375.         }else
  376.         {
  377.                 if(dengji < s_dengji)          //取消報警
  378.                 {
  379.                         value = 0;
  380.                         beep = 1;
  381.                 }       
  382.         }
  383. }

  384. /***************主函數*****************/
  385. void main()
  386. {
  387.         beep = 0;                                //開機叫一聲   
  388.         delay_1ms(150);
  389.         P0 = P1 = P2 = P3 = 0xff;                //單片機IO口初始化為1       
  390.         init_eeprom();                              //讀eeprom數據
  391.         time_init();                                //初始化定時器
  392.         init_1602();
  393.         while(1)
  394.         {
  395.                 key();                                        //獨立按鍵程序
  396.                 if(key_can < 10)
  397.                 {
  398.                         key_with();                        //按鍵按下要執行的程序
  399.                 }
  400.                 if(flag_300ms == 1)
  401.                 {               
  402.                         flag_300ms = 0;
  403.                         clock_h_l();           //報警函數
  404.                         dengji = ad0832read(1,0);       
  405.                         dengji = dengji * 450 / 255.0;
  406.                     dengji = dengji - 100;              //首先減去零點漂移,一般是1V
  407.                         if(dengji < 0)
  408.                                 dengji = 0;       
  409.                         dengji = dengji * 2;             //將mV轉變成mg/L,系數需要校準   
  410.                                                                   //電壓每升高0.1V,實際被測氣體的濃度增加20ppm
  411.                                                                   //1ppm=1mg/kg=1mg/L=1×10-6 常用來表示氣體濃度,或者溶液濃度。      

  412.                         write_sfm2(1,9,dengji);                  //顯示濃度
  413.                 }
  414.         }
  415. }

  416. /*************定時器0中斷服務程序***************/
  417. void time0_int() interrupt 1
  418. {       
  419.         static uchar value;
  420.         TH0 = 0x3c;
  421.         TL0 = 0xb0;     // 50ms
  422.         value ++;         
  423.         if(value % 6 == 0)
  424.         {
  425.                 flag_300ms = 1;           //300ms
  426.                 value = 0;
  427.         }
  428. }
復制代碼

所有資料51hei提供下載:
keil4版.rar (50.05 KB, 下載次數: 71)


回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美成人免费在线 | 91久久精品国产91久久 | 男女视频在线观看免费 | 久草.com| 羞羞网站在线观看 | 午夜精品福利视频 | 99热热99| 国产在线资源 | 日本精品久久 | 国产精品中文字幕在线 | 日本精品在线播放 | 欧美精品久久久 | 91精品国产综合久久久动漫日韩 | 九九福利 | 青青草网 | 黄视频国产 | 国产精品性做久久久久久 | 亚洲国产成人精品女人久久久 | 国产精品免费在线 | 国产无人区一区二区三区 | 日韩精品一区二区三区中文在线 | 欧美日韩国产不卡 | 日韩中文在线视频 | 欧美一区二区久久 | 天堂综合 | 欧洲一区二区视频 | 激情91| 日韩欧美一区二区三区免费观看 | 九九九久久国产免费 | 一区二区在线视频 | 美女张开腿露出尿口 | 九九99久久 | 亚洲小视频在线播放 | 日本精品在线一区 | 成人在线影视 | 欧美精品在线免费 | 99久久婷婷国产综合精品首页 | 9久久婷婷国产综合精品性色 | 欧美成人在线免费 | 成人免费大片黄在线播放 | 亚洲高清一区二区三区 |