温湿度报警装置

温湿度报警装置

一、装置主要实现的功能以及操作流程

功能:使用数码管显示温湿度并实时检测环境温度

  1> 显示温度的格式 : 22.5c(目前无法显示0度以下的温度)
  2> 显示湿度的格式 : 45.6H / 45.6r

  3> 每隔5s钟刷新一次温湿度的显示(先显示5s的温度,在显示5s湿度)(逻辑的实现)

  4> KEY1按下,立即测量温度并更新显示
  5> KEY2按下,立即测量湿度并更新显示

  6> 实现温湿度阈值报警的功能,并且控制风扇调速。

  7> 用于检查错误;显示报警。

温度检测流程:温度检测–>设置阈值–>超过阈值导致led灯亮、蜂鸣器报警。

湿度检测流程:湿度检测–>设置阈值–>超过阈值导致led灯亮、开启风扇。

更新数据:

​     按下key1更新温度
​     按下key2更新湿度

二、控件介绍

    本次项目采用的是STM32单片机。使用的温湿度传感器芯片是si7006。

三、代码设计部分

  我在这里就不一一讲述了,每种单片机的引脚功能各不相同。

  我在这个项目中,将各器件进行了初始化我在这里就不一一讲述了,每种单片机的引脚功能各不相同。

  初始化了led1,led2灯作为报警指示灯。

  初始化风扇、蜂鸣器用于报警后的处理。

  初始化数字显像管作为显示温度数值的模块。

4.初始化温湿度传感器用来收集环境温度和数值。

函数流程设计思路:

主函数:

  第一步:先调用传感器采集数据,作为第一次采集的初试数据,每隔5秒,重新采集数据

  第二步:将采集来的数据显示在显像管上。

  第三步:在自动更新的过程中,设计了按键中断,按下按键可以触发中断,主动更新一次数据并继续显示数据的循环。

  第四步:设置报警阈值,当数据超过阈值时触发报警机制,激活对应设备及led灯,当数值低于阈值时,关闭对应设备,熄灭led灯。


void delay_ms(unsigned int ms);



void temp_check(unsigned short num){
    if(num>280){
        //led1高电平,蜂鸣器高电平
        hal_gpio_write(GPIOE, GPIO_PIN_10, GPIO_SET);
        hal_gpio_write(GPIOB,GPIO_PIN_6,GPIO_SET);
    }else if(num <=280){
        //led1低电平,蜂鸣器低电平
        hal_gpio_write(GPIOE, GPIO_PIN_10, GPIO_RESET);
        hal_gpio_write(GPIOB,GPIO_PIN_6,GPIO_RESET);
    }
}
void hum_check(unsigned short num){
    if(num>700){
        //led3高电平,风扇高电平
        hal_gpio_write(GPIOE, GPIO_PIN_8, GPIO_SET);
        hal_gpio_write(GPIOE, GPIO_PIN_9, GPIO_SET);
    }else if(num <=700){
        //led3低电平,风扇低电平
        hal_gpio_write(GPIOE,GPIO_PIN_8, GPIO_RESET);
        hal_gpio_write(GPIOE, GPIO_PIN_9, GPIO_RESET);

    }
}




//温度和湿度显示
void temp_show(unsigned short temp_value,unsigned char* tem){
        //显示温度
        for (j = 0 ; j < 725 ; j++)
            for (i = 0; i < 4; i++) { // 选择位
                //触发中断更新温度数据
                if(measure_again == 2){
                    hum_value = si7006_read_hum_data(SI7006_SLAVE, MEASURE_HUM_CMD);
                    hum_value = (125 * hum_value / 65536 - 6) * 10;
                    //终端显示
                    hum_check(hum_value);
                    printf("hum update!");
                    printf("hum value = %d.%d\n", hum_value / 10, hum_value % 10);
                    num(hum_value,hum);
                    measure_again=0;
                    hum_show(hum_value,hum);
                }else if(measure_again==1){
                    temp_value = si7006_read_temp_data(SI7006_SLAVE, MEASURE_TEMP_CMD);
                    temp_value = (175.72 * temp_value / 65536 - 46.85) * 10;
                    temp_check(temp_value);
                    //终端显示
                    printf("temp update!");
                    printf("temp value = %d.%d\n", temp_value / 10, temp_value % 10);
                    num(temp_value,tem);
                    measure_again=0;
                    temp_show(temp_value,tem);
                }
                SPI_write(0x80 >> i); // 依次发送数码管显示的位
                SPI_write(tem[i]); // 依次发送数码管的段,让数码管显示不同的数字
                NSS_OUTPUT_L();
                delay_ms(1);
                NSS_OUTPUT_H();
                // delay_ms(500);   // 不可以有延时
            }
}
void hum_show(unsigned short hum_value,unsigned char *hum){
    for (j = 0; j < 725; j++) {
            for (i = 0; i < 4; i++) { // 选择位
                                //触发中断更新温度数据
                if(measure_again == 2){
                    hum_value = si7006_read_hum_data(SI7006_SLAVE, MEASURE_HUM_CMD);
                    hum_value = (125 * hum_value / 65536 - 6) * 10;
                    //终端显示
                    hum_check(hum_value);
                    printf("hum update!");
                    printf("hum value = %d.%d\n", hum_value / 10, hum_value % 10);
                    num(hum_value,hum);
                    measure_again=0;
                    hum_show(hum_value,hum);
                }else if(measure_again==1){
                    temp_value = si7006_read_temp_data(SI7006_SLAVE, MEASURE_TEMP_CMD);
                    temp_value = (175.72 * temp_value / 65536 - 46.85) * 10;
                    //终端显示
                    temp_check(temp_value);
                    printf("temp update!");
                    printf("temp value = %d.%d\n", temp_value / 10, temp_value % 10);
                    num(temp_value,tem);
                    measure_again=0;
                    temp_show(temp_value,tem);
                }
                SPI_write(0x80 >> i); // 依次发送数码管显示的位
                SPI_write(hum[i]); // 依次发送数码管的段,让数码管显示不同的数字
                NSS_OUTPUT_L();
                delay_ms(1);
                NSS_OUTPUT_H();
                // delay_ms(500);   // 不可以有延时
            }
        }
}

//将读取到的数据转换成显像管需要的十六进制数据
unsigned char rnum(unsigned short t)
{
    switch (t) {
    case 0:
        return 0xFC;
        break;
    case 1:
        return 0x60;
        break;
    case 2:
        return 0xDA;
        break;
    case 3:
        return 0xF2;
        break;
    case 4:
        return 0x66;
        break;
    case 5:
        return 0xB6;
        break;
    case 6:
        return 0xBE;
        break;
    case 7:
        return 0xE0;
        break;
    case 8:
        return 0xFE;
        break;
    case 9:
        return 0xF6;
        break;
    }
}
//转换数据函数
void num(unsigned short a, unsigned char* ret)
{
    short t;
    int s = a;
    t = s / 100; // 10位
    ret[0] = rnum(t);
    t = s % 10; //个位
    ret[2] = rnum(t);
    s /= 10;
    t = s % 10;
    ret[1] = rnum(t) | 0x1;
}

extern char buffer[LEN];

int main()
{
    //设置变量用于接收温度和湿度
    si7006_init();
    //驱动初始化
    hal_led_init(); //初始化指示灯
    //串口的初始化
    hal_uart4_init();
    //中断初始化
    // KEY1
    hal_gpio_IT_init(GPIOF, GPIO_PIN_9);
    hal_exti_IT_init(GPIO_PIN_9, GPIOF_EXTI, FALLING_EDGE);
    hal_gic_IT_init(99, 1);
    // KEY2
    hal_gpio_IT_init(GPIOF, GPIO_PIN_7);
    hal_exti_IT_init(GPIO_PIN_7, GPIOF_EXTI, FALLING_EDGE);
    hal_gic_IT_init(97, 1);
    //定时器初始化
    hal_tim5_IT_init();
    //数字管显示初始化
    SPI_init();
    
    while (1) {
        //显示温湿度信息
        //接收初试温湿度信息以及转化
        hum_value = si7006_read_hum_data(SI7006_SLAVE, MEASURE_HUM_CMD);
        temp_value = si7006_read_temp_data(SI7006_SLAVE, MEASURE_TEMP_CMD);
        hum_value = (125 * hum_value / 65536 - 6) * 10;
        temp_value = (175.72 * temp_value / 65536 - 46.85) * 10;
        //终端显示
        hum_check(hum_value);
        temp_check(temp_value);
        printf("hum value = %d.%d\n", hum_value / 10, hum_value % 10);
        printf("temp value = %d.%d\n", temp_value / 10, temp_value % 10);
        num(temp_value,tem);
        num(hum_value,hum);
        
        //将信息转换成字符型
        temp_show(temp_value,tem);
        //显示湿度
        hum_show(hum_value,hum);
    }
    return 0;
}

延时函数:

  延时函数的作用主要是用来作为计时程序使用。相当于c语言中的sleep函数,但是因为我所用的是裸机设备,所以需要自己设计延时程序。

  注:如果不用延时程序来实现每个五秒重新采集数据的话,则需要使用单片机的计时器功能来进行延时功能。计时器需要搭配中断处理程序来实现数据更新。

void delay_ms(unsigned int ms)
{
    int i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 1800; j++)
            ;
}

中断处理函数:

  将中断后处理方式进行标志量赋值:将对应标志位进行更改,达到一种信号传导作用。

部分代码展示:


extern int measure_again;


void do_irq(void)
{ // 1. 获取当前处理的中断的中断号  GICC_IAR[9:0]
    int irq_num;
    
    irq_num = GICC->IAR & 0x3FF;
    switch (irq_num)
    {
    case 82: // TIM5计时器
        // 2. 调用82号中断的处理函数
        printf("TIM5 1s timer interrupt ID = %d\n", irq_num);
        // 3. 清除TIM5层的中断挂起标志位
        hal_tim5_clear_IT();
        // 4. 清除GICD层的中断挂起标志位  GICD_ICPENDR3[3]
        hal_gicd_clear_IT(irq_num);
        break;
    case 97: // KEY2
        // 2. 调用97号中断的处理函数
        measure_again = 2;
        // 3. 清除EXTI层的中断挂起标志位  EXTI_FPR1[9]
        hal_exti_clear_IT(GPIO_PIN_7, FALLING_EDGE);
        // 4. 清除GICD层的中断挂起标志位  GICD_ICPENDR3[3]
        hal_gicd_clear_IT(irq_num);
        break;
    case 99: // 99 号中断处理程序  KEY1
        // 2. 调用99号中断的处理函数
        measure_again = 1;
        // 3. 清除EXTI层的中断挂起标志位  EXTI_FPR1[9]
        hal_exti_clear_IT(GPIO_PIN_9, FALLING_EDGE);
        // 4. 清除GICD层的中断挂起标志位  GICD_ICPENDR3[3]
        hal_gicd_clear_IT(irq_num);
        break;

    default:
        break;
    }
    // 5. 清除GICC层的中断号
    GICC->EOIR = irq_num;
}

你可能感兴趣的:(单片机,stm32,嵌入式硬件,物联网,arm)