51單片機課程設計:基於MQ-3的酒精濃度報警器(MQ系列通用)
本程序用於將MQ-3上讀取到的模擬信號轉換爲對應的數字信號,經51單片機處理後,在數碼管顯示,同時具有報警功能,當檢測值高於預警值,蜂鳴器報警。除了可以檢測MQ-3酒精濃度模塊的AD值,也適用於MQ系列的其他模塊,原理基本都相同,都是將讀取到的AD值轉換爲數字信號,程序修改後,如果接線方法正確,可以在吉林農業大學51開發板上完美運行,相關工程文件以及開發板對應的電路圖見最下方附件。
關於粘貼複製亂碼的問題:如果程序複製到Keil編譯器上出現註釋亂碼,可以先建一個.c文件,也就是說不在keil裏面編輯,然後用記事本打開.c文件,將源碼複製進去,再在keil中添加文件即可。
/*************************************說明*********************************** 此程序只採集模塊信號的大小 需要轉換爲對應的值 還需要轉換公式 連接方式見下方定義 關於接線 MQ7連接電源 然後AO接學校板子上A/D 模擬信號輸入端 本例程可用於MQ系列模塊,將對應的模擬信號轉換爲對應的數字信號顯示出來 (適用於吉農51開發板) 2016-12-29-----------------------SWorld ****************************************************************************/ #include <reg52.h> //頭文件 #include <intrins.h> #define uchar unsigned char //宏定義無符號字符型 #define uint unsigned int //宏定義無符號整型 #define GPIO_DIG P0//位選以及段選數據輸出端口定義 unsigned char code DIG_CODE[10]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f}; //顯示段碼 數碼管字跟 unsigned char DisplayData[8]; //用來存放要顯示的8位數的值 sbit cs=P3^5;//分別接學校單片機的ADCS ADRD ADWR sbit rd=P3^6; sbit wr=P3^7; sbit CLK=P3^3; //時鐘脈衝 sbit DUC=P2^2;// DUC段選信號 sbit WEC=P2^3;//WEC 位選信號 sbit bell=P3^4;//連接蜂鳴器 sbit setwarn=P2^7; //確定 sbit add=P2^6;//數值增加 sbit sub=P2^5;//數值減少 uint z,x,c,v,AD0809,date,ok;//定義數據類型 uint num; //默認報警值 /******************************************************************************* * 函 數 名 : Delay10ms * 函數功能 : 延時函數,延時10ms * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void Delay10ms(unsigned int c) //誤差 0us { unsigned char a, b; //--c已經在傳遞過來的時候已經賦值了,所以在for語句第一句就不用賦值了--// for (;c>0;c--) { for (b=38;b>0;b--) { for (a=130;a>0;a--); } } } unsigned char Key_Scan() { unsigned char keyValue = 0 , i; //保存鍵值 //--檢測按鍵1--// if (setwarn != 1)//檢測按鍵K1是否按下 { Delay10ms(1);//消除抖動 if (setwarn != 1)//再次檢測按鍵是否按下 { keyValue = 3; i = 0; while ((i<50) && (setwarn != 1)) //檢測按鍵是否鬆開 { Delay10ms(1); i++; } } } //--檢測按鍵1--// if (add != 1)//檢測按鍵K1是否按下 { Delay10ms(1);//消除抖動 if (add!= 1)//再次檢測按鍵是否按下 { keyValue = 1; i = 0; while ((i<50) && (add != 1)) //檢測按鍵是否鬆開 { Delay10ms(1); i++; } } } //--檢測按鍵1--// if (sub != 1)//檢測按鍵K1是否按下 { Delay10ms(1);//消除抖動 if (sub!= 1)//再次檢測按鍵是否按下 { keyValue = 2; i = 0; while ((i<50) && (sub != 1)) //檢測按鍵是否鬆開 { Delay10ms(1); i++; } } } return keyValue; //將讀取到鍵值的值返回 } /******************************************************************************* * 函 數 名 : DigDisplay * 函數功能 : 使用數碼管顯示 * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void DigDisplay() { unsigned char i; unsigned int j; for(i=0;i<8;i++) { WEC=1;DUC=0; switch(i) //位選,選擇點亮的數碼管, { case(0): GPIO_DIG=0x7F; break;//顯示第0位 case(1): GPIO_DIG=0xBF; break;//顯示第1位 case(2): GPIO_DIG=0xDF; break;//顯示第2位 case(3): GPIO_DIG=0xEF; break;//顯示第3位 case(4): GPIO_DIG=0xF7; break;//顯示第4位 case(5): GPIO_DIG=0xFB; break;//顯示第5位 case(6): GPIO_DIG=0xFD; break;//顯示第6位 case(7): GPIO_DIG=0xFE; break;//顯示第7位 } WEC=0;DUC=1; GPIO_DIG=DisplayData[i];//發送段碼 j=15; //掃描間隔時間設定 while(j--); GPIO_DIG=0x00;//消隱 } } /********************************************************************** 數碼管動態掃描 *********************************************************************/ void xianshi() //顯示函數 { if(AD0809>250) AD0809=250; date=AD0809; /****************************** data爲讀取到的AD值,通過轉換公式,可以將data轉換爲對應的酒精濃度顯示出來 需要自己查資料修改 **************************************/ if(date>num) { bell=0; } else { bell=1; } //uint z,x,c,v; z=date/1000; //求千位 x=date%1000/100; //求百位 c=date%100/10; //求十位 v=date%10; //求個位 DisplayData[6]=DIG_CODE[z]; DisplayData[5]=DIG_CODE[x]; DisplayData[4]=DIG_CODE[c]; DisplayData[3]=DIG_CODE[v]; DigDisplay(); } /************************************************************************* CLK振盪信號 **************************************************************************/ void timer0( ) interrupt 1 //定時器0工作方式1 { TH0=(65536-2)/256; //重裝計數初值 TL0=(65536-2)%256; //重裝計數初值 CLK=!CLK; //取反 } /************************************************************************* 主函數 **************************************************************************/ void main() { uint xx=0; num=100; TMOD=0X01; //定時器中斷0 bell=1; CLK=0; //脈衝信號初始值爲0 TH0=(65536-2)/256; //定時時間高八位初值 TL0=(65536-2)%256; //定時時間低八位初值 EA=1; //開CPU中斷 ET0=1; //開T/C0中斷 TR0=1; cs=0;ok=0; while(1) { if(ok==1) //無限循環 { if(xx==20) { wr=0; _nop_(); wr=1; _nop_(); _nop_(); rd=0; _nop_(); AD0809=P1; //讀取數據 rd=1; xx=0; } else { xx++; } xianshi();//數碼管顯示函數 } else//以下爲設置報警值代碼 { switch(Key_Scan()) { case 3: ok=1; break; case 1: num-=2; break; case 2: num+=2; break; } z=num/1000; //求千位 x=num%1000/100; //求百位 c=num%100/10; //求十位 v=num%10; //求個位 DisplayData[6]=DIG_CODE[z]; DisplayData[5]=DIG_CODE[x]; DisplayData[4]=DIG_CODE[c]; DisplayData[3]=DIG_CODE[v]; DigDisplay(); } } }