• 方案介紹
    • 一、前言
    • 二、硬件選型
    • 三、設(shè)計思路
    • 四、項目模塊代碼
  • 附件下載
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

基于STC89C52單片機設(shè)計的防煤氣泄漏裝置

12小時前
180
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

更多詳細(xì)資料請聯(lián)系.docx

共1個文件

一、前言

煤氣泄漏是一個嚴(yán)重的安全隱患,可能導(dǎo)致火災(zāi)、爆炸以及對人體健康的威脅。為了提高家庭和工業(yè)環(huán)境中煤氣泄漏的檢測和預(yù)防能力,設(shè)計了一種基于單片機的防煤氣泄漏裝置。

單片機選擇STC89C52作為主控芯片。為了檢測煤氣泄漏,采用了MQ4傳感器,能夠快速、準(zhǔn)確地檢測煤氣濃度。通過采集MQ4傳感器的模擬信號,使用PCF8591模數(shù)轉(zhuǎn)換芯片將模擬信號轉(zhuǎn)換為數(shù)字信號。采用IIC接口的OLED顯示屏,將采集到的數(shù)據(jù)顯示出來,方便用戶獲取檢測結(jié)果。用戶可以通過兩個獨立按鍵設(shè)置煤氣泄漏的報警閾值,以適應(yīng)不同環(huán)境的需求。

當(dāng)檢測到煤氣泄漏超過設(shè)定的閾值時,裝置會觸發(fā)蜂鳴器進(jìn)行報警,并同時打開換氣扇進(jìn)行通風(fēng)換氣,以迅速排除煤氣并降低安全風(fēng)險。

這種基于單片機設(shè)計的防煤氣泄漏裝置具有以下優(yōu)點:高效可靠的煤氣泄漏檢測能力、靈活的報警閾值設(shè)置、直觀清晰的數(shù)據(jù)顯示以及及時的安全響應(yīng)措施。可以廣泛應(yīng)用于家庭、工業(yè)和商業(yè)場所,提供有效的煤氣泄漏監(jiān)測和安全保護(hù)。

二、硬件選型

在設(shè)計基于單片機的防煤氣泄漏裝置時,硬件選型是非常關(guān)鍵的。以下是詳細(xì)介紹硬件選型的相關(guān)內(nèi)容:

【1】主控芯片選擇:STC89C52 STC89C52是一款8051架構(gòu)的單片機,具有豐富的接口資源、較高的性能和穩(wěn)定可靠的工作特性,廣泛應(yīng)用于各種嵌入式系統(tǒng)中。具有8位數(shù)據(jù)總線、16位地址總線和4KB的內(nèi)部存儲器。STC89C52具備多個通用I/O口、定時器/計數(shù)器、串口等功能,非常適合本項目需求。

【2】煤氣傳感器選擇:MQ4 MQ4傳感器是一種能夠檢測多種可燃?xì)怏w,如天然氣、甲烷等的傳感器。具有高靈敏度和快速響應(yīng)的特點,能夠準(zhǔn)確地檢測煤氣泄漏情況。MQ4傳感器的輸出為模擬信號,需要通過模數(shù)轉(zhuǎn)換器將其轉(zhuǎn)換為數(shù)字信號供主控芯片處理。

【3】模數(shù)轉(zhuǎn)換器選擇:PCF8591 PCF8591是一款集成了8位模數(shù)/數(shù)模轉(zhuǎn)換和4個模擬輸入通道的模數(shù)轉(zhuǎn)換器。采用IIC總線通訊接口,能夠?qū)⒛M信號轉(zhuǎn)換為數(shù)字信號,并通過IIC協(xié)議發(fā)送給主控芯片。本項目中,PCF8591用于采集MQ4傳感器輸出的模擬信號,并將其轉(zhuǎn)換為數(shù)字信號供STC89C52處理。

【4】顯示屏選擇:0.96寸OLED顯示屏(IIC接口) 本設(shè)計采用基于IIC接口的OLED顯示屏,具有高亮度、對比度和快速響應(yīng)的特點。通過簡單的通訊方式,可以將煤氣濃度信息實時顯示在屏幕上。OLED顯示屏使用面積小、功耗低,在嵌入式系統(tǒng)中應(yīng)用廣泛。

【5】按鍵選擇:獨立按鍵 本設(shè)計采用兩個獨立按鍵來設(shè)置報警的閥值。一個按鍵用于遞增閥值,另一個按鍵用于遞減閥值。獨立按鍵具有簡單可靠、使用方便等特點,適合本項目需求。

【6】報警裝置選擇:蜂鳴器和換氣扇 當(dāng)檢測到煤氣泄漏超過設(shè)定的報警閥值時,蜂鳴器將發(fā)出警報,用于提醒周圍人員。同時,為了降低煤氣濃度,需要啟動換氣扇進(jìn)行通風(fēng)換氣。具體的報警和換氣扇電路可以根據(jù)實際需求設(shè)計。

三、設(shè)計思路

軟件設(shè)計思路如下:

【1】初始化:在程序開始時,進(jìn)行主控芯片STC89C52的初始化設(shè)置,包括引腳配置、定時器設(shè)置等。同時,初始化PCF8591和OLED顯示屏,確保它們可以正常工作。

【2】傳感器檢測:通過MQ4傳感器檢測煤氣是否泄漏。將MQ4傳感器與STC89C52的模擬輸入引腳連接,通過讀取該引腳的模擬電壓值,獲取煤氣濃度數(shù)據(jù)。

【3】數(shù)據(jù)采集與處理:使用PCF8591模數(shù)轉(zhuǎn)換芯片,將MQ4傳感器的模擬輸出信號轉(zhuǎn)換為數(shù)字信號,并通過STC89C52的IIC接口與PCF8591進(jìn)行通信,獲取轉(zhuǎn)換后的數(shù)字?jǐn)?shù)據(jù)。

【4】數(shù)據(jù)顯示:將采集到的煤氣濃度數(shù)據(jù)通過IIC接口的OLED顯示屏進(jìn)行顯示。使用STC89C52的IIC通信功能,將數(shù)據(jù)發(fā)送給OLED顯示屏,通過顯示屏將數(shù)據(jù)以可讀的方式展示給用戶。

【5】閾值設(shè)置:通過兩個獨立按鍵實現(xiàn)報警閾值的設(shè)置。將按鍵與STC89C52的GPIO引腳連接,通過讀取按鍵狀態(tài)來判斷用戶是否進(jìn)行閾值設(shè)置操作。當(dāng)按鍵按下時,進(jìn)入設(shè)置模式,用戶可以通過按鍵的不同組合來調(diào)整報警閾值,并將設(shè)置的值保存在相應(yīng)的變量中。

【6】報警與通風(fēng)控制:根據(jù)當(dāng)前采集到的煤氣濃度數(shù)據(jù)和用戶設(shè)置的報警閾值進(jìn)行比較。如果煤氣濃度超過設(shè)定的閾值,觸發(fā)蜂鳴器進(jìn)行報警,并控制換氣扇打開進(jìn)行通風(fēng)換氣。反之,當(dāng)煤氣濃度低于或等于設(shè)定的閾值時,停止報警并關(guān)閉換氣扇。

【7】循環(huán)監(jiān)測:使用主循環(huán)結(jié)構(gòu),不斷進(jìn)行煤氣泄漏檢測、數(shù)據(jù)采集、數(shù)據(jù)顯示和閾值比較等操作,以實現(xiàn)持續(xù)的監(jiān)測和反饋。

四、項目模塊代碼

4.1 PCF8591采集代碼

下面是使用STC89C52單片機通過PCF8591讀取MQ4傳感器的ADC數(shù)據(jù)的代碼。使用IIC總線進(jìn)行PCF8591之間的通信,使用了自定義的IIC總線函數(shù)。通過readADC()函數(shù)實現(xiàn)了讀取MQ4傳感器模擬量的ADC轉(zhuǎn)換結(jié)果。

#include <reg52.h>

#define uchar unsigned char
#define uint unsigned int

sbit SDA = P2^0;    // IIC總線數(shù)據(jù)線
sbit SCL = P2^1;    // IIC總線時鐘線

sbit MQ4_DOUT = P3^0;   // MQ4傳感器數(shù)字輸出引腳
sbit MQ4_AIN = P3^1;    // MQ4傳感器模擬輸入引腳

sfr IAP_DATA = 0xe2;    // 定義IAP_DATA寄存器
sfr IAP_ADDRH = 0xe3;   // 定義IAP_ADDRH寄存器
sfr IAP_ADDRL = 0xe4;   // 定義IAP_ADDRL寄存器
sfr IAP_CMD = 0xe5;     // 定義IAP_CMD寄存器
sfr IAP_TRIG = 0xe6;    // 定義IAP_TRIG寄存器
sfr IAP_CONTR = 0xe7;   // 定義IAP_CONTR寄存器

// 函數(shù)聲明
void delay(uint ms);
void startIIC();
void stopIIC();
void sendByte(uchar dat);
uchar receiveByte();
void writeDAC(uchar dat);
uchar readADC();

void main() {
    uchar mq4Value;
    
    while (1) {
        mq4Value = readADC();  // 讀取ADC轉(zhuǎn)換結(jié)果
        
        // 處理mq4Value值,進(jìn)行相應(yīng)操作
        
        delay(100);  // 延時一段時間
    }
}

// 延時函數(shù)
void delay(uint ms) {
    uint i, j;
    for(i = ms; i > 0; i--) {
        for(j = 110; j > 0; j--);
    }
}

// IIC總線起始信號
void startIIC() {
    SDA = 1;
    _nop_();
    SCL = 1;
    _nop_();
    SDA = 0;
    _nop_();
    SCL = 0;
    _nop_();
}

// IIC總線停止信號
void stopIIC() {
    SDA = 0;
    _nop_();
    SCL = 1;
    _nop_();
    SDA = 1;
    _nop_();
}

// 發(fā)送一個字節(jié)的數(shù)據(jù)
void sendByte(uchar dat) {
    uchar i;
    for (i = 0; i < 8; i++) {
        SDA = dat >> 7;
        _nop_();
        SCL = 1;
        _nop_();
        SCL = 0;
        _nop_();
        dat <<= 1;
    }
    SDA = 1;
    _nop_();
    SCL = 1;
    _nop_();
    SCL = 0;
    _nop_();
}

// 接收一個字節(jié)的數(shù)據(jù)
uchar receiveByte() {
    uchar i, dat = 0;
    SDA = 1;
    for (i = 0; i < 8; i++) {
        dat <<= 1;
        SCL = 1;
        _nop_();
        dat |= SDA;
        SCL = 0;
        _nop_();
    }
    return dat;
}

// 寫入DAC數(shù)值
void writeDAC(uchar dat) {
    startIIC();
    sendByte(0x90);  // 地址和寫命令
    receiveByte();   // 接收應(yīng)答
    sendByte(0x40);  // DAC通道A,并寫入數(shù)據(jù)
    receiveByte();   // 接收應(yīng)答
    sendByte(dat);   // DAC數(shù)據(jù)
    receiveByte();   // 接收應(yīng)答
    stopIIC();
}

// 讀取ADC轉(zhuǎn)換結(jié)果
uchar readADC() {
    uchar adcValue;
    
    startIIC();
    sendByte(0x91);   // 地址和讀命令
    receiveByte();    // 接收應(yīng)答
    adcValue = receiveByte();  // 讀取ADC數(shù)據(jù)
    stopIIC();
    
    return adcValue;
}

4.2 OLED顯示屏代碼

以下是通過STC89C52控制IIC接口的OLED顯示屏顯示ADC數(shù)據(jù)實現(xiàn)代碼。

#include <reg51.h>

#define SCL P1_0   // IIC時鐘線
#define SDA P1_1   // IIC數(shù)據(jù)線

#define OLED_ADDR 0x78   // OLED顯示屏的IIC地址

// OLED顯示屏初始化函數(shù)
void OLED_Init() {
    // 初始化OLED顯示屏
    // ...

    // 發(fā)送初始化命令到OLED顯示屏
    // ...
}

// IIC總線開始信號
void IIC_Start() {
    SDA = 1;
    SCL = 1;
    SDA = 0;
    SCL = 0;
}

// IIC總線停止信號
void IIC_Stop() {
    SDA = 0;
    SCL = 1;
    SDA = 1;
}

// IIC總線發(fā)送一個字節(jié)的數(shù)據(jù)
void IIC_WriteByte(unsigned char dat) {
    unsigned char i;
    for (i = 0; i < 8; i++) {
        SCL = 0;
        if (dat & 0x80)
            SDA = 1;
        else
            SDA = 0;
        SCL = 1;
        dat <<= 1;
    }
    SCL = 0;
    SDA = 1;
    SCL = 1;
}

// 設(shè)置OLED顯示屏光標(biāo)位置
void OLED_SetPos(unsigned char x, unsigned char y) {
    IIC_Start();
    IIC_WriteByte(OLED_ADDR);
    IIC_WriteByte(0xb0 + y);
    IIC_WriteByte(((x & 0xf0) >> 4) | 0x10);
    IIC_WriteByte((x & 0x0f) | 0x01);
    IIC_Stop();
}

// 在OLED顯示屏上顯示一個字符
void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch) {
    unsigned char c = 0, i = 0;
    c = ch - ' ';   // 獲取字符在字庫中的偏移量
    if (x > 128 - 8 || y > 64 - 16)
        return;   // 超出屏幕范圍,退出函數(shù)
    OLED_SetPos(x, y);
    for (i = 0; i < 8; i++) {
        IIC_Start();
        IIC_WriteByte(OLED_ADDR);
        IIC_WriteByte(0x40);
        IIC_WriteByte(*(OLED_CharSet + c * 16 + i));
        IIC_Stop();
        x++;
    }
}

// 在OLED顯示屏上顯示字符串
void OLED_ShowString(unsigned char x, unsigned char y, unsigned char *str) {
    while (*str) {
        OLED_ShowChar(x, y, *str);
        x += 8;
        str++;
    }
}

// ADC模擬數(shù)值轉(zhuǎn)換為字符串
void ADC_ToString(unsigned int adcValue, unsigned char *str) {
    unsigned char i, j;
    unsigned int temp;

    temp = adcValue;
    for (i = 0; i < 4; i++) {
        str[i] = temp % 10 + '0';
        temp /= 10;
    }

    // 反轉(zhuǎn)字符串
    i = 0;
    j = 3;
    while (i < j) {
        temp = str[i];
        str[i] = str[j];
        str[j] = temp;
        i++;
        j--;
    }
    str[4] = '?';   // 字符串結(jié)束符
}

// 主函數(shù)
void main() {
    unsigned int adcValue = 0;
    unsigned char str[5];

    // 初始化OLED顯示屏
    OLED_Init();

    while (1) {
        // 讀取ADC數(shù)據(jù)
        adcValue = ADC_Read();   // 假設(shè)使用的函數(shù)為ADC_Read(),用于讀取ADC數(shù)據(jù)

        // 將ADC數(shù)據(jù)轉(zhuǎn)換為字符串
        ADC_ToString(adcValue, str);

        // 在OLED顯示屏上顯示ADC數(shù)據(jù)
        OLED_ShowString(0, 0, "ADC Value:");
        OLED_ShowString(0, 2, str);
    }
}

4.3 主代碼邏輯

#include <reg51.h>

#define SCL P1_0    // IIC時鐘線
#define SDA P1_1    // IIC數(shù)據(jù)線

#define OLED_ADDR 0x78    // OLED顯示屏的IIC地址
#define MQ4_PIN P2      // MQ4傳感器連接的引腳

sbit Buzzer = P3^0;    // 蜂鳴器控制引腳
sbit VentilationFan = P3^1;    // 換氣扇控制引腳

// 全局變量
unsigned int alarmThreshold = 100;    // 報警閾值,默認(rèn)為100
unsigned int adcValue = 0;    // 保存ADC采集到的數(shù)值

// IIC總線開始信號
void IIC_Start() {
    SDA = 1;
    SCL = 1;
    SDA = 0;
    SCL = 0;
}

// IIC總線停止信號
void IIC_Stop() {
    SDA = 0;
    SCL = 1;
    SDA = 1;
}

// IIC總線發(fā)送一個字節(jié)的數(shù)據(jù)
void IIC_WriteByte(unsigned char dat) {
    unsigned char i;
    for (i = 0; i < 8; i++) {
        SCL = 0;
        if (dat & 0x80)
            SDA = 1;
        else
            SDA = 0;
        SCL = 1;
        dat <<= 1;
    }
    SCL = 0;
    SDA = 1;
    SCL = 1;
}

// 設(shè)置OLED顯示屏光標(biāo)位置
void OLED_SetPos(unsigned char x, unsigned char y) {
    IIC_Start();
    IIC_WriteByte(OLED_ADDR);
    IIC_WriteByte(0xb0 + y);
    IIC_WriteByte(((x & 0xf0) >> 4) | 0x10);
    IIC_WriteByte((x & 0x0f) | 0x01);
    IIC_Stop();
}

// 在OLED顯示屏上顯示一個字符
void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch) {
    unsigned char c = 0, i = 0;
    c = ch - ' ';    // 獲取字符在字庫中的偏移量
    if (x > 128 - 8 || y > 64 - 16)
        return;    // 超出屏幕范圍,退出函數(shù)
    OLED_SetPos(x, y);
    for (i = 0; i < 8; i++) {
        IIC_Start();
        IIC_WriteByte(OLED_ADDR);
        IIC_WriteByte(0x40);
        IIC_WriteByte(*(OLED_CharSet + c * 16 + i));
        IIC_Stop();
        x++;
    }
}

// 在OLED顯示屏上顯示字符串
void OLED_ShowString(unsigned char x, unsigned char y, unsigned char *str) {
    while (*str) {
        OLED_ShowChar(x, y, *str);
        x += 8;
        str++;
    }
}

// ADC轉(zhuǎn)換函數(shù)
unsigned int ADC_Convert(unsigned char channel) {
    ADC_CONTR = ADC_POWER | ADC_START | channel | ADC_SPEED;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    while (!(ADC_CONTR & ADC_FLAG))
        ;
    ADC_CONTR &= ~ADC_FLAG;
    return (ADC_RES * 256 + ADC_RESL);
}

// ADC模擬數(shù)值轉(zhuǎn)換為字符串
void ADC_ToString(unsigned int adcValue, unsigned char *str) {
    unsigned char i, j;
    unsigned int temp;

    temp = adcValue;
    for (i = 0; i < 4; i++) {
        str[i] = temp % 10 + '0';
        temp /= 10;
    }

    // 反轉(zhuǎn)字符串
    i = 0;
    j = 3;
    while (i < j) {
        temp = str[i];
        str[i] = str[j];
        str[j] = temp;
        i++;
        j--;
    }
    str[4] = '?';    // 字符串結(jié)束符
}

 主函數(shù)
void main() {
    unsigned char str[5];

    // 初始化OLED顯示屏
    OLED_Init();

    // 設(shè)置初始報警閾值
    SetAlarmThreshold();

    while (1) {
        // 讀取MQ4傳感器的ADC數(shù)值
        adcValue = ADC_Convert(0);    // 假設(shè)MQ4傳感器連接到ADC的通道0

        // 將ADC數(shù)值轉(zhuǎn)換為字符串
        ADC_ToString(adcValue, str);

        // 在OLED顯示屏上顯示ADC數(shù)值
        OLED_ShowString(0, 0, "Gas Level:");
        OLED_ShowString(0, 2, str);

        // 判斷是否觸發(fā)報警
        if (adcValue > alarmThreshold) {
            // 觸發(fā)報警
            ActivateAlarm();
        } else {
            // 取消報警
            DeactivateAlarm();
        }

        // 檢測是否按下設(shè)置閾值的按鍵
        if (IsThresholdButtonPressed()) {
            // 設(shè)置報警閾值
            SetAlarmThreshold();
        }

        // 檢測是否按下通風(fēng)換氣的按鍵
        if (IsVentilationButtonPressed()) {
            // 控制通風(fēng)換氣
            ControlVentilation();
        }
    }
}
  • 更多詳細(xì)資料請聯(lián)系.docx
    下載

相關(guān)推薦