找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 3811|回復(fù): 1
收起左側(cè)

單片機(jī)+溫度檢測(cè)+空氣檢測(cè)+PM2.5檢測(cè)

[復(fù)制鏈接]
ID:821815 發(fā)表于 2021-4-19 21:07 | 顯示全部樓層 |閱讀模式
基于51單片機(jī)的空氣質(zhì)量監(jiān)測(cè)系統(tǒng)
原理圖:
G@VDRW@D8~K3P23N@CW2~U0.png


程序如下:
#include <reg52.h>
#include <intrins.h>
#include <absacc.h>
#include <math.h>
#include "0832.h"

#define uchar unsigned char
#define uint unsigned int



//定義LCD1602端口
sbit E=P2^6;                //1602使能引腳
sbit RS=P2^7;                //1602數(shù)據(jù)/命令選擇引腳
sbit RW=P2^5;

sbit LED_RED=P2^2;
sbit LED_YELLOW=P2^1;
sbit LED_GREEN=P2^0;


sbit SET_KEY=P3^4;
sbit ADD_KEY=P3^5;
sbit SUB_KEY=P3^6;


sbit BUZZ=P3^7;
sbit jdq=P2^4;

                       
                       
volatile unsigned char BEEP_Cnt = 0;
                       
unsigned char PM_Waring = 50;
unsigned char Temp_Waring = 20;
unsigned char Smok_Waring = 50;


unsigned char Smok_Value = 125;

unsigned char PM_Waring;
unsigned char PM_Value;





bit FlagStartRH=0;
bit flag_BJ=0;

unsigned char a1,a2,a3;




extern volatile unsigned char KEY_Value;
#define KEY_NOP         0
#define KEY_SET                     1
#define KEY_UP                      2
#define KEY_DOWN                           3




void Delay_1ms(unsigned int n)                //@11.0592MHz
{
       
        unsigned char i, j;
        while(n--)
        {
                _nop_();
                i = 2;
                j = 199;
                do
                {
                        while (--j);
                } while (--i);
        }
}



volatile unsigned char KEY_Value = KEY_NOP;



void Key_Scan(void)        //按鍵檢測(cè)
{
       
        static volatile unsigned char Trg = 0;
        static volatile unsigned char Cnt = 0;
        unsigned char KeyRead = 0;
       
        KeyRead = ((P3>>4) & 0X07) ^ 0X07;
        Trg = KeyRead ^ (KeyRead & Cnt);
  Cnt =        KeyRead;
       
        if(Trg)
        {
                switch(Trg)
                {
                        case 0x01: KEY_Value = KEY_SET; break;
                        case 0x02: KEY_Value = KEY_UP; break;
                        case 0x04: KEY_Value = KEY_DOWN; break;
                       
                        default:   KEY_Value = KEY_NOP;break;

                       
                }
               
               
        }
       
}









unsigned char Temp_Value = 0; //溫度

/*********************************端口定義**********************************/
sbit DQ=P1^6;                                   //數(shù)據(jù)傳輸線(xiàn)接單片機(jī)的相應(yīng)的引腳




/*********************************定義全局變量******************************/
bit TemperatureLessZero;
unsigned int Temperature = 850;           //溫度值(整型變量)182表示18.2C
/****************************************************************************
函數(shù)功能:延時(shí)子程序
入口參數(shù):k
出口參數(shù):
****************************************************************************/
void DS18_delay(unsigned char useconds)                  //延遲17US.根據(jù)晶振調(diào)節(jié)
{
        unsigned char i;
        while(--useconds)
        {
                i = 3;
                while (--i);
        }
}

/***************************************************************************
函數(shù)功能:DS18B20初始化子程序
入口參數(shù):
出口參數(shù):
****************************************************************************/
unsigned char Init_DS18B20(void)
{
        unsigned char x=0;

          DQ=0;                             //發(fā)送復(fù)位脈沖
          DS18_delay(29);                         //延時(shí)(>480us)
          DQ=1;                                  //拉高數(shù)據(jù)線(xiàn)
          DS18_delay(3);                       //等待(15~60us) 等待存在脈沖
    x=DQ;  //獲得存在信號(hào)(用于判斷是否有器件)
    DS18_delay(25);  // 等待時(shí)間隙結(jié)束
    return(x);  //返回存在信號(hào),0 = 器件存在, 1 = 無(wú)器件
}

/****************************************************************************
函數(shù)功能:向DS18B20讀一字節(jié)數(shù)據(jù)
入口參數(shù):
出口參數(shù):dat
****************************************************************************/
ReadOneChar(void)                         
{
        unsigned char i=0;                
        unsigned char dat=0;
    for (i=8;i>0;i--)                 
                {
                        DQ=1;
                           DS18_delay(1);
                    DQ=0;      
                    dat>>=1;//復(fù)合賦值運(yùn)算,等效dat=dat>>1(dat=dat右移一位后的值)
                           DQ=1;
                    if(DQ)
                           dat|=0x80;
                    DS18_delay(4);
                }
    return(dat);
}

/****************************************************************************
函數(shù)功能:向DS18B20寫(xiě)一字節(jié)數(shù)據(jù)
入口參數(shù):dat
出口參數(shù):
****************************************************************************/
void WriteOneChar(unsigned char dat)//有參函數(shù),功能是"寫(xiě)",而寫(xiě)的內(nèi)容就是括號(hào)內(nèi)的參數(shù)
{
        unsigned char i=0;                
        for(i=8;i>0;i--)         
        {
                DQ=0;           
                DQ=dat&0x01;
                DS18_delay(4);
                DQ=1;
                dat>>=1;//復(fù)合賦值運(yùn)算,等效dat=dat>>1(dat=dat右移一位后的值)
        }
//        DS18_delay(4);
}
                       
/****************************************************************************
函數(shù)功能:向DS18B20讀溫度值
入口參數(shù):
出口參數(shù):temperature
****************************************************************************/
void ReadTemperature(void)
{  
        unsigned char tempL=0;                         //臨時(shí)變量低位(無(wú)符號(hào)字符變量)
        unsigned char tempH=0;                        //臨時(shí)變量高位
        bit flag = 0;
        EA = 0;
        Init_DS18B20();                                 //初始化,調(diào)用初始化函數(shù)
        WriteOneChar(0xcc);                  //跳過(guò)讀序列號(hào)的操作,調(diào)用寫(xiě)函數(shù),寫(xiě)0xcc指令碼(跳過(guò)讀序列號(hào))
        WriteOneChar(0x44);                 //啟動(dòng)溫度轉(zhuǎn)換,調(diào)用寫(xiě)函數(shù),寫(xiě)0x44指令碼(啟動(dòng)溫度轉(zhuǎn)換)

//  Time = get_time();
//        DS18_delay(125);                           //轉(zhuǎn)換需要一點(diǎn)時(shí)間,延時(shí)
        Init_DS18B20();                         //初始化,調(diào)用初始化函數(shù)
        WriteOneChar(0xcc);                  //跳過(guò)讀序列號(hào)的操作,調(diào)用寫(xiě)函數(shù),寫(xiě)0xcc指令碼(跳過(guò)讀序列號(hào)?
        WriteOneChar(0xbe);                 //調(diào)用寫(xiě)函數(shù),寫(xiě)0xbe指令碼,讀溫度寄存器(頭兩個(gè)值分別為溫度的低位和高位)
        tempL=ReadOneChar();                 //讀出溫度的低位LSB
        tempH=ReadOneChar();                 //讀出溫度的高位MSB  
        TemperatureLessZero = (bit)(tempH&0x80);
  Temperature=((((tempH&0x7F)<<8)+tempL)*10)>>4;  //溫度轉(zhuǎn)換,把高低位做相應(yīng)的運(yùn)算轉(zhuǎn)化為實(shí)際溫度,使用DS18B20溫度傳感器手冊(cè)規(guī)定的公式,結(jié)果是十進(jìn)制數(shù)值
                                                  //這里使用*0.0625,直接增加500+字節(jié)代碼
       
        EA = 1;
        Temp_Value = Temperature/10;
       
        if(Temp_Value > 125) Temp_Value =125;
        if(TemperatureLessZero)Temp_Value = 0;

//        DS18_delay(20);
//        return(tempa);//運(yùn)算結(jié)果返回到函數(shù) :ReadTemperature()調(diào)用時(shí)需要采用i=ReadTemperature(),然后再對(duì)i(任意uchar型變量)進(jìn)行操作
}






void L1602_string(uchar hang,uchar lie,uchar *p);

//定時(shí)器0初始化
void Timer0_Init()
{
        //AUXR &= 0x7F;                //定時(shí)器時(shí)鐘12T模式
        TMOD &= 0xF0;                //設(shè)置定時(shí)器模式
        TMOD |= 0x01;                //設(shè)置定時(shí)器模式
        TL0 = 0xB0;                //設(shè)置定時(shí)初值
        TH0 = 0x3C;                //設(shè)置定時(shí)初值
        TF0 = 0;                //清除TF0標(biāo)志
        TR0 = 1;                //定時(shí)器0開(kāi)始計(jì)時(shí)
        ET0 = 1;
}

bit Time0_300ms_Flag = 1;


//定時(shí)器0中斷
void Timer0_ISR (void) interrupt 1 using 0
{
        static uchar RHCounter;
        static uchar Time0_300ms_Cnt;
       
        TR0 = 0;
        TL0 = 0xb0;
        TH0 = 0x3c;     //定時(shí)器賦予初值
        TR0 = 1;
       
       
        Key_Scan();
       
        if(++Time0_300ms_Cnt>= 6)
        {
                Time0_300ms_Cnt = 0;
                Time0_300ms_Flag = 1;
        }

    if(++RHCounter >= 20)
    {
                         RHCounter = 0;
                       
       FlagStartRH = 1;
                       
    }
               
        if(BEEP_Cnt)
        {
                BEEP_Cnt--;
                BUZZ = 0;
        }
        else
        {       
                BUZZ = 1;
        }
}


/********************************************************************
* 文件名  : 液晶1602顯示.c
* 描述    :  該程序?qū)崿F(xiàn)了對(duì)液晶1602的控制。
***********************************************************************/


/********************************************************************
* 名稱(chēng) : delay()
* 功能 : 延時(shí),延時(shí)時(shí)間大概為140US。
* 輸入 : 無(wú)
* 輸出 : 無(wú)
***********************************************************************/

void delay()
{
        int i,j;
        for(i=0; i<=10; i++)
        for(j=0; j<=2; j++);
}

void delay_ms(uint ms)
{
        uint i,j;
        for(i=0;i<ms;i++)
        for(j=0;j<110;j++);
}           
       
/********************************************************************
* 名稱(chēng) : enable(uchar del)
* 功能 : 1602命令函數(shù)
* 輸入 : 輸入的命令值
* 輸出 : 無(wú)
***********************************************************************/

void enable(uchar del)
{
        P0 = del;
        RS = 0;
        E = 1;
        delay();
        E = 0;
        delay();
}

/********************************************************************
* 名稱(chēng) : write(uchar del)
* 功能 : 1602寫(xiě)數(shù)據(jù)函數(shù)
* 輸入 : 需要寫(xiě)入1602的數(shù)據(jù)
* 輸出 : 無(wú)
***********************************************************************/

void write(uchar del)
{
        P0 = del;
        RS = 1;
        E = 1;
        delay();
        E = 0;
        delay();
}

/********************************************************************
* 名稱(chēng) : L1602_init()
* 功能 : 1602初始化,請(qǐng)參考1602的資料
* 輸入 : 無(wú)
* 輸出 : 無(wú)
***********************************************************************/
void L1602_init(void)
{
        RW=0;
        enable(0x38);
        enable(0x0c);
        enable(0x06);
        enable(0x01); //清屏要放在最后
        enable(0x80);
        L1602_string(1,1," PM2.5:   0ug/m3");
        enable(0xc0+0x02);
        write(0xdf);
        L1602_string(2,4,"C");
        L1602_string(2,5," Smok:");
}

/********************************************************************
* 名稱(chēng) : L1602_char(uchar hang,uchar lie,char sign)
* 功能 : 改變液晶中某位的值,如果要讓第一行,第五個(gè)字符顯示"b" ,調(diào)用該函數(shù)如下
                 L1602_char(1,5,'b')
* 輸入 : 行,列,需要輸入1602的數(shù)據(jù)
* 輸出 : 無(wú)
***********************************************************************/
void L1602_char(uchar hang,uchar lie,char sign)
{
        uchar a;
        if(hang == 1) a = 0x80;
        if(hang == 2) a = 0xc0;
        a = a + lie - 1;
        enable(a);
        write(sign);
}

/********************************************************************
* 名稱(chēng) : L1602_string(uchar hang,uchar lie,uchar *p)
* 功能 : 改變液晶中某位的值,如果要讓第一行,第五個(gè)字符開(kāi)始顯示"ab cd ef" ,調(diào)用該函數(shù)如下
                  L1602_string(1,5,"ab cd ef;")
* 輸入 : 行,列,需要輸入1602的數(shù)據(jù)
* 輸出 : 無(wú)
***********************************************************************/
void L1602_string(uchar hang,uchar lie,uchar *p)
{
        uchar a;
        if(hang == 1) a = 0x80;
        if(hang == 2) a = 0xc0;
        a = a + lie - 1;
        enable(a);
        while(1)
        {
                if(*p == '\0') break;
                write(*p);
                p++;
        }
}






void LCD1602_Write_String(bit x,unsigned char y,unsigned char *P)
{
       
        if(x)
        {
                enable(0x80 + 0x40 + y);
        }
        else
        {
                enable(0x80 + y);
        }
       
        while(*P)
        {
                write(*P++);
        }
       
}




void LCD1602_Write_8bit(unsigned int x,unsigned char SIZE)
{
        switch(SIZE)
        {
               
                case 3:
               
                                        write(0x30 + ((x/100)%10));
                                        write(0x30 + ((x/10)%10));
                                        write(0x30 + ((x)%10));
               
                                        break;
                case 4:
                       
                        break;
               
               
                default:  break;
               
        }
}



void display()
{

        if(PM_Value%10000/1000!=0)
        L1602_char(1,8,PM_Value%10000/1000+0x30);
        else
        L1602_char(1,8,' ');
        if(PM_Value%10000/100!=0)
        L1602_char(1,9,PM_Value%1000/100+0x30);
        else
        L1602_char(1,9,' ');
        if(PM_Value%10000/10!=0)
        L1602_char(1,10,PM_Value%100/10+0x30);
        else
        L1602_char(1,10,' ');
        L1602_char(1,11,PM_Value%10+0x30);
       

        a1=(Temp_Value/10)%10;
        a3=Temp_Value%10;

        L1602_char(2,1,a1+0x30);
        L1602_char(2,2,a3+0x30);
       
       
        L1602_string(2,5," Smok:");
       
        LCD1602_Write_8bit(Smok_Value,3);
       
        BUZZ=1;         //蜂鳴器關(guān)
}



void ALARM()
{
       
        if((PM_Value >= PM_Waring)||(Smok_Value >= Smok_Waring)||(Temp_Value >= Temp_Waring))
        {
                BEEP_Cnt = 20;
               
                LED_RED=0;
                LED_YELLOW=1;
                LED_GREEN=1;
                jdq=0;
        }
        else
        {
                if((PM_Value < PM_Waring)  &&  (PM_Value >= PM_Waring/2) && (Smok_Value < Smok_Waring)&& (Temp_Value < Temp_Waring))
                {
                        LED_RED=1;
                        LED_YELLOW=0;
                        LED_GREEN=1;
                        jdq=1;
                }
                else
                {
                        LED_RED=1;
                        LED_YELLOW=1;
                        LED_GREEN=0;
                        jdq=1;
                }

        }
}





bit LCD1602_Enable = 1;

volatile unsigned char Menu_States = 0;



void KEY_Processing(void)
{
       
        if(KEY_SET == KEY_Value)       
        {
                KEY_Value = KEY_NOP;

                Menu_States = ++Menu_States % 4;
               
                enable(0x01);
                if(Menu_States == 0)
                {
                        L1602_init();
                }       
               
                LCD1602_Enable = 1;
        }
       
       
        if(KEY_UP==KEY_Value)        //下限加
        {
                KEY_Value = KEY_NOP;
                LCD1602_Enable = 1;
                switch(Menu_States)
                {
                        case 1:if(PM_Waring   < 255)PM_Waring++;   enable(0x01);  break;
                        case 2:if(Temp_Waring < 125)Temp_Waring++; enable(0x01); break;
                        case 3:if(Smok_Waring < 100)Smok_Waring++; enable(0x01); break;
                }
        }
       
       
        if(KEY_DOWN ==KEY_Value)        //上限減
        {
                KEY_Value = KEY_NOP;
                LCD1602_Enable = 1;
                switch(Menu_States)
                {
                        case 1:if(PM_Waring   > 0)PM_Waring--;   enable(0x01); break;
                        case 2:if(Temp_Waring > 0)Temp_Waring--; enable(0x01); break;
                        case 3:if(Smok_Waring > 0)Smok_Waring--; enable(0x01); break;
                       
                }
        }

       
       
       
}





void LCD1602_Processing(void)
{
       
        if(Time0_300ms_Flag || LCD1602_Enable)
        {
                Time0_300ms_Flag = 0;
                LCD1602_Enable = 0;
                switch(Menu_States)
                {
                        case 0:
                                                        display();
                                                        break;
                       
                        case 1:
                                                        enable(0x0c);  //不顯示光標(biāo)
                                                        LCD1602_Write_String(0,0,"PM_Waring:");
                       
                                                        enable(0xC0+4);
                                                        LCD1602_Write_8bit(PM_Waring,3);
                               
                                                        enable(0xC0+6);
                                                        enable(0x0F);  //顯示光標(biāo)
                       
                                                break;
                       
                        case 2:
                                                        enable(0x0c);  //不顯示光標(biāo)
                                                        LCD1602_Write_String(0,0,"Temp_Waring:");
                                                        enable(0xC0+4);
                                                        LCD1602_Write_8bit(Temp_Waring,3);
                               
                                                        enable(0xC0+6);
                                                        enable(0x0F);  //顯示光標(biāo)
                       
                                                break;
                       
                        case 3:
                                                        enable(0x0c);  //不顯示光標(biāo)
                                                        LCD1602_Write_String(0,0,"Smok_Waring:");
                       
                                                        enable(0xC0+4);
                                                        LCD1602_Write_8bit(Smok_Waring,3);
                                                        enable(0xC0+6);
                                                        enable(0x0F);  //顯示光標(biāo)
                                                break;
                       
                       
                        default:  break;
                       
                }                       
        }
}



/********************************************************************
* 名稱(chēng) : Main()
* 功能 : 主函數(shù)
***********************************************************************/
void main()
{
        static bit CH;
        Timer0_Init();  //定時(shí)器0初始化
       

        L1602_init();
       
        ReadTemperature();
        ReadTemperature();
        Delay_1ms(1000);
        ReadTemperature();
        Delay_1ms(1000);
  ReadTemperature();
        Delay_1ms(1000);
        ReadTemperature();
        Delay_1ms(1000);
        ReadTemperature();
       
        PM_Value = ADC0832_Read(0);
       
        Smok_Value = ADC0832_Read(1)/2.56;
       
        EA = 1;
        while(1)
        {
                if(FlagStartRH )         //溫濕度轉(zhuǎn)換標(biāo)志檢查
                {
                        FlagStartRH = 0;
                                 
                        CH = ~CH;
                       
                        if(CH)
                        {
                                PM_Value = ADC0832_Read(0);
                        }
                        else
                        {
                                Smok_Value = ADC0832_Read(1)/2.56;
                        }
               
                        ReadTemperature();

                }
               
                LCD1602_Processing();
               
                KEY_Processing();
               
                ALARM();
        }
}


回復(fù)

使用道具 舉報(bào)

ID:910466 發(fā)表于 2021-4-25 20:06 | 顯示全部樓層
#include "0832.h"
這個(gè)文件是什么?
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表