【TB作品】msp430f5529单片机,dht22,烟雾传感器

功能

//硬件:msp430f5529、dht22、LCD1602、蜂鸣器、烟雾传感器、蓝牙模块。
//功能:读取温湿度、烟雾浓度显示到屏幕;
//按键调节三个报警数值;
//温度、湿度、烟雾浓度,任意一个大于报警数值就蜂鸣器报警;
//单片机将温度、湿度、烟雾浓度,通过蓝牙模块,发送到电脑端显示。
//电脑端也可以调节三个报警数值。

引脚


//PCF8574 LCD1602----MSP430F5529
//GND----------------GND
//VCC----------------3.3v
//SDA----------------P2.4
//SCL----------------P2.5

//HC05 蓝牙----------MSP430F5529
//GND----------------GND
//VCC----------------3.3v
//RX-----------------P3.3  T
//TX-----------------P3.4  R

//PM2烟雾传感器 0~3.3v电压转为ppm单位 20~20000ppm
//DHT22--------------MSP430F5529
//GND----------------GND
//VCC----------------3.3v
//DAT----------------P2.3

//烟雾---------------MSP430F5529
//GND----------------GND
//VCC----------------3.3v
//A0-----------------P6.5

//蜂鸣器-------------MSP430F5529
//GND----------------GND
//VCC----------------3.3v
//DAT----------------P1.6

//按键----------------MSP430F5529
//KEY1----------------P1.2
//KEY2----------------P1.3
//KEY3----------------P1.4
//KEY4----------------P1.5
//GND-----------------GND

//板子自己有的按键
//KEY5----------------P1.1
//KEY6----------------P2.1

部分程序


unsigned char get_key(void) //声明一个函数,返回值类型为 unsigned char,函数名为 get_key,参数列表为空
{
    unsigned char key; //声明一个名为 key 的无符号字符变量
    if ((P1IN & BIT2) == 0) //如果 P1IN 寄存器的第二位是 0,说明按键1被按下
    {
        delay_ms(10); //延时 10 毫秒,以确保读取的值稳定
        if ((P1IN & BIT2) == 0) //再次检测按键1是否被按下
        {
            key = 1; //将 key 设置为 1,表示按下了按键1
            while ((P1IN & BIT2) == 0)
                //等待按键1松开
                ;
        }
    }
    else if ((P1IN & BIT3) == 0) //如果按键1未被按下,检测按键2是否被按下
    {
        delay_ms(10); //同样进行延时
        if ((P1IN & BIT3) == 0) //检测按键2是否被按下
        {
            key = 2; //将 key 设置为 2,表示按下了按键2
            while ((P1IN & BIT3) == 0)
                //等待按键2松开
                ;
        }
    }
    else if ((P1IN & BIT4) == 0)
    {
        delay_ms(10);
        if ((P1IN & BIT4) == 0)
        {
            key = 3;
            while ((P1IN & BIT4) == 0)
                ;
        }
    }
    else if ((P1IN & BIT5) == 0)
    {
        delay_ms(10);
        if ((P1IN & BIT5) == 0)
        {
            key = 4;
            while ((P1IN & BIT5) == 0)
                ;
        }
    }
    else if ((P1IN & BIT1) == 0)
    {
        delay_ms(10);
        if ((P1IN & BIT1) == 0)
        {
            key = 5;
            while ((P1IN & BIT1) == 0)
                ;
        }
    }
    else if ((P2IN & BIT1) == 0)
    {
        delay_ms(10);
        if ((P2IN & BIT1) == 0)
        {
            key = 6;
            while ((P2IN & BIT1) == 0)
                ;
        }
    }
    else
    {
        key = 0;
    }
    return key;
}

u8 data[5];
u16 shidu, wendu, yanwu;
u16 shidu_baojing = 900, wendu_baojing = 400, yanwu_baojing = 10000;
u8 disp[20];
u8 count = 0;
u8 timecnt = 0;
u8 keyvalue = 0;

void disp_line1(void) // 定义名为disp_line1的函数
{
    count = 0; // 初始化计数器
    disp[count++] = wendu % 1000 / 100 + '0'; // 将温度百位数字转换为字符存入显示缓存数组,计数器+1
    disp[count++] = wendu % 100 / 10 + '0'; // 将温度十位数字转换为字符存入显示缓存数组,计数器+1
    disp[count++] = 'C'; // 存入字符'C',表示摄氏度,计数器+1
    disp[count++] = ' '; // 存入空格字符,计数器+1
    disp[count++] = shidu % 1000 / 100 + '0'; // 将湿度百位数字转换为字符存入显示缓存数组,计数器+1
    disp[count++] = shidu % 100 / 10 + '0'; // 将湿度十位数字转换为字符存入显示缓存数组,计数器+1
    disp[count++] = '%'; // 存入字符'%',表示百分比符号,计数器+1
    disp[count++] = ' '; // 存入空格字符,计数器+1
    disp[count++] = yanwu % 100000 / 10000 + '0'; // 将烟雾万位数字转换为字符存入显示缓存数组,计数器+1
    disp[count++] = yanwu % 10000 / 1000 + '0'; // 将烟雾千位数字转换为字符存入显示缓存数组,计数器+1
    disp[count++] = yanwu % 1000 / 100 + '0'; // 将烟雾百位数字转换为字符存入显示缓存数组,计数器+1
    disp[count++] = yanwu % 100 / 10 + '0'; // 将烟雾十位数字转换为字符存入显示缓存数组,计数器+1
    disp[count++] = yanwu % 10 + '0'; // 将烟雾个位数字转换为字符存入显示缓存数组,计数器+1
    disp[count++] = 'p'; // 存入字符'p',表示“ppm”(parts per million),计数器+1
    disp[count++] = 0; // 存入字符'\0',表示字符串结束,计数器+1
    LCD_write_str(0, 0, disp); // 在LCD屏幕第0行显示disp数组中的内容
}

void send_computer(void)
{
    count = 0;
    disp[count++] = wendu % 1000 / 100 + '0';
    disp[count++] = wendu % 100 / 10 + '0';
    disp[count++] = 'C';
    disp[count++] = ' ';
    disp[count++] = shidu % 1000 / 100 + '0';
    disp[count++] = shidu % 100 / 10 + '0';
    disp[count++] = '%';
    disp[count++] = ' ';
    disp[count++] = yanwu % 100000 / 10000 + '0';
    disp[count++] = yanwu % 10000 / 1000 + '0';
    disp[count++] = yanwu % 1000 / 100 + '0';
    disp[count++] = yanwu % 100 / 10 + '0';
    disp[count++] = yanwu % 10 + '0';
    disp[count++] = 'p';
    disp[count++] = '\r';
    disp[count++] = '\n';
    disp[count++] = 0;
    Print_Str(disp);
}

void disp_line2(void)
{
    count = 0; //计数器清零
    //显示湿度报警值的百位、十位
    disp[count++] = shidu_baojing % 1000 / 100 + '0';
    disp[count++] = shidu_baojing % 100 / 10 + '0';
    disp[count++] = 'C'; //显示'C'
    disp[count++] = ' '; //显示空格
    //显示温度报警值的百位、十位
    disp[count++] = wendu_baojing % 1000 / 100 + '0';
    disp[count++] = wendu_baojing % 100 / 10 + '0';
    disp[count++] = '%'; //显示'%'
    disp[count++] = ' '; //显示空格
    //显示烟雾报警值的万位、千位、百位、十位、个位
    disp[count++] = yanwu_baojing % 100000 / 10000 + '0';
    disp[count++] = yanwu_baojing % 10000 / 1000 + '0';
    disp[count++] = yanwu_baojing % 1000 / 100 + '0';
    disp[count++] = yanwu_baojing % 100 / 10 + '0';
    disp[count++] = yanwu_baojing % 10 + '0';
    disp[count++] = 'p'; //显示'p'
    disp[count++] = 0; //末尾字符为0
    //在LCD的第1行第0列显示字符串disp
    LCD_write_str(0, 1, disp);
}

void deal_key(void)
{
    // 定义一个函数deal_key,没有返回值,没有参数
    if (keyvalue == 1)
    {
        // 如果keyvalue的值为1
        shidu_baojing += 10;
        // 湿度报警值加10
        if (shidu_baojing > 900)
        {
            // 如果湿度报警值大于900
            shidu_baojing = 900;
            // 把湿度报警值设为900
        }
    }
    else if (keyvalue == 2)
    {
        // 否则,如果keyvalue的值为2
        shidu_baojing -= 10;
        // 湿度报警值减10
        if (shidu_baojing < 100)
        {
            // 如果湿度报警值小于100
            shidu_baojing = 100;
            // 把湿度报警值设为100
        }
    }
    else if (keyvalue == 3)
    {
        // 否则,如果keyvalue的值为3
        wendu_baojing += 10;
        // 温度报警值加10
        if (wendu_baojing > 900)
        {
            // 如果温度报警值大于900
            wendu_baojing = 900;
            // 把温度报警值设为900
        }
    }
    else if (keyvalue == 4)
    {
        // 否则,如果keyvalue的值为4
        wendu_baojing -= 10;
        // 温度报警值减10
        if (wendu_baojing < 100)
        {
            // 如果温度报警值小于100
            wendu_baojing = 100;
            // 把温度报警值设为100
        }
    }
    else if (keyvalue == 5)
    {
        // 否则,如果keyvalue的值为5
        yanwu_baojing += 100;
        // 烟雾报警值加100
        if (yanwu_baojing > 20000)
        {
            // 如果烟雾报警值大于20000
            yanwu_baojing = 20000;
            // 把烟雾报警值设为20000
        }
    }
    else if (keyvalue == 6)
    {
        // 否则,如果keyvalue的值为6
        yanwu_baojing -= 100;
        // 烟雾报警值减100
        if (yanwu_baojing < 200)
        {
            // 如果烟雾报警值大于200
            yanwu_baojing = 200;
            // 把烟雾报警值设为200
        }
    }
}

void contorl_beep(void) // 定义一个名为 contorl_beep 的函数
{
    if ((shidu > shidu_baojing) || (wendu > wendu_baojing) // 如果湿度、温度或烟雾任意一个超过了警戒值
            || (yanwu > yanwu_baojing))
    {
        P1OUT &= ~BIT6; // 将 P1OUT 寄存器的第 6 位设置为 0,表示开启蜂鸣器
    }
    else // 如果湿度、温度和烟雾都没有超过警戒值
    {
        P1OUT |= BIT6; // 将 P1OUT 寄存器的第 6 位设置为 1,表示关闭开启蜂鸣器
    }
}

/* 烟雾浓度换算 */
static unsigned int  yw_ppm_count(unsigned int x1)
{
    float a =0 ,b = 0,c = 0,d = 0;
    float ax =0 ,bx = 0,cx = 0,dx = 0;
    float y;
    float x;
    x=x1*3.3/4096;
    a = x * x * x * x * x;
    b = x * x * x * x;
    c = x * x * x;
    d = x * x ;
    ax = 0.0001923 * a;
    bx = 0.006017 * b;
    cx = 0.07267 * c;
    dx = 0.425 * d;
    y = ax - bx + cx - dx + (1.267 * x) + 1.209;
    y = y * 1000;

    return (unsigned int)y;
}


void main(void)
{
    WDTCTL = WDTPW + WDTHOLD;                 // 停止看门狗定时器



    init_clock();                             // 初始化时钟
    init_uart();                              // 初始化UART串口
    init_adc();                               // 初始化ADC模块
    init_key();                               // 初始化按键
    init_beep();                              // 初始化蜂鸣器
    while (DHT22_Init() == 1)                 // 初始化DHT22温湿度传感器
    {
        delay_ms(100);                        // 延时100毫秒
    }
    delay_ms(1000);
    LCD_Init();                               // 初始化液晶屏
    disp_line2();                             // 在液晶屏上显示第二行
    _EINT();                                  // 开启总中断


    while (1)                                 // 无限循环
    {
        delay_ms(10);                         // 延时10毫秒
        timecnt++;                            // 时间计数器加1
        if (timecnt > 200)                    // 如果时间计数器超过200
        {
            timecnt = 0;                      // 重置时间计数器
            DHT22_Read_Data(data);            // 读取DHT22传感器数据
            shidu = data[0];                  // 湿度数据
            shidu = (shidu << 8) + data[1];   // 拼接数据
            wendu = data[2];                  // 温度数据
            wendu = (wendu << 8) + data[3];   // 拼接数据
            yanwu = get_adc();                // 获取烟雾浓度值
            //0到4096转为0到20000ppm
            yanwu = yw_ppm_count(yanwu);             // 将ADC值转换为烟雾浓度值
            contorl_beep();                    // 控制蜂鸣器
            disp_line1();                      // 在液晶屏上显示第一行
            disp_line2();                      // 在液晶屏上显示第二行
            send_computer();
        }
        keyvalue = get_key();                 // 获取按键值
        if (keyvalue)                         // 如果有按键按下
        {
            deal_key();                       // 处理按键
            disp_line2();                     // 在液晶屏上显示第二行
        }
    }
}

unsigned char revchar = 0;                      // 定义一个无符号字符变量,初始值为0,用于保存接收到的字符
unsigned char revchar_openflag = 0;       // 定义一个无符号字符变量,初始值为0,用于标志接收到的字符是否为有效数据
unsigned char revchar_cnt = 0;               // 定义一个无符号字符变量,初始值为0,用于计数接收到的有效数据个数
unsigned char revchar_buffer[20];              // 定义一个无符号字符数组,长度为20,用于存储接收到的有效数据

#pragma vector=USCI_A0_VECTOR                   // 定义中断函数,当 USCI_A0_VECTOR 中断发生时,执行以下函数
__interrupt void USCI_A0_ISR(void)
{
    switch (__even_in_range(UCA0IV, 4))
    // 获取 USCI_A0_VECTOR 中断的状态
    {
    case 0:                                     // Vector 0 - no interrupt,无中断状态
        break;
    case 2:                                     // Vector 2 - RXIFG,接收到数据的中断状态
        revchar = UCA0RXBUF;            // 读取 USCI_A0_VECTOR 的接收缓冲区数据到变量 revchar
        if (revchar_openflag)                   // 如果接收到的字符是有效数据
        {
            //S889912345                        // 检查接收到的数据是否符合特定的格式,如S889912345
            if ((revchar >= '0') && (revchar <= '9'))  // 如果接收到的数据是数字字符
            {
                revchar_buffer[revchar_cnt] = revchar - '0'; // 把接收到的数字字符转化为对应的数字存入 revchar_buffer 数组中
                revchar_cnt++;                              // 计数器加1
                if (revchar_cnt >= 9)                     // 如果接收到的数字字符数量达到特定的数量
                {
                    shidu_baojing = revchar_buffer[0] * 100
                            + revchar_buffer[1] * 10;  // 计算湿度报警值
                    wendu_baojing = revchar_buffer[2] * 100
                            + revchar_buffer[3] * 10;  // 计算温度报警值
                    yanwu_baojing = revchar_buffer[4] * 10000
                            + revchar_buffer[5] * 1000 + revchar_buffer[6] * 100
                            + revchar_buffer[7] * 10 + revchar_buffer[8]; // 计算烟雾报警值

                    revchar_openflag = 0;               // 清除接收标志
                    revchar_cnt = 0;                    // 清除计数器
                }

            }
            else                                    // 如果接收到的字符不是数字字符
            {
                revchar_openflag = 0;               // 清除接收标志
                revchar_cnt = 0;                    // 清除计数器
            }
        }
        if (revchar == 'S')
        {
            revchar_openflag = 1;
            revchar_cnt = 0;
        }

        break;
    case 4:
        break;                             // Vector 4 - TXIFG
    default:
        break;
    }
}

全部程序

https://docs.qq.com/sheet/DUEdqZ2lmbmR6UVdU?tab=BB08J2

最近更新

  1. TCP协议是安全的吗?

    2024-06-06 13:50:11       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-06 13:50:11       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-06 13:50:11       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-06 13:50:11       20 阅读

热门阅读

  1. Selenium自动化测试入门:设置等待时间

    2024-06-06 13:50:11       8 阅读
  2. 【车载开发系列】自动驾驶技术--HUD技术

    2024-06-06 13:50:11       9 阅读
  3. idea2024年最新激活码,即拿即用

    2024-06-06 13:50:11       12 阅读
  4. SQL入门详细教程

    2024-06-06 13:50:11       8 阅读
  5. 学习VUE3——组件(一)

    2024-06-06 13:50:11       8 阅读
  6. 【数据库系统概论】事务

    2024-06-06 13:50:11       10 阅读
  7. 小程序怎样进行本地存储的读、写、删、清?

    2024-06-06 13:50:11       9 阅读
  8. 【Python】常见的生成随机数的方法

    2024-06-06 13:50:11       11 阅读