51單片機課程設計:基於MQ-3的酒精濃度報警器

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();
        }
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章