温湿度报警装置

温湿度报警装置

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

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

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

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
代码:#include //用AT89C51时就用这个头文件 //#include //用华邦W78E58B时必须用这个头文件 #include #include #include #include #include #include #include "LCD1602.h" ////液晶显示头文件 //sbit DQ = P3^4; //定义DQ引脚为P3.4 sbit mode=P1^3; sbit add=P1^4; sbit sub=P1^5; sbit power=P1^7; unsigned char TH=50,TL=20; unsigned char t[2],*pt; //用来存放温度值,测温程序就是通过这个数组与主函数通信的 unsigned char TempBuffer1[9]={0x2b,0x31,0x32,0x32,0x2e,0x30,0x30,0x43,'\0'}; //显示实时温度,上电时显示+125.00C unsigned char TempBuffer0[17]={0x54,0x48,0x3a,0x2b,0x31,0x32,0x35,0x20, 0x54,0x4c,0x3a,0x2b,0x31,0x32,0x34,0x43,'\0'}; //显示温度上下限,上电时显示TH:+125 TL:+124C unsigned char code dotcode[4]={0,25,50,75}; /***因显示分辨率为0.25,但小数运算比较麻烦,故采用查表的方法******* 再将表值分离出十位和个位后送到十分位和百分位********************/ void covert0( unsigned char TH, unsigned char TL) //将温度上下限转换为LCD显示的数据 { if(TH>0x7F) //判断正负,如果为负温,将其转化为其绝对值 { TempBuffer0[3]=0x2d; //0x2d为"-"的ASCII码 TH=~TH; TH++; } else TempBuffer0[3]=0x2b; //0x2B为"+"的ASCII码 if(TL>0x7f) { TempBuffer0[11]=0x2d; //0x2d为"-"的ASCII码 TL=~TL+1; } else TempBuffer0[11]=0x2b; //0x2B为"+"的ASCII码 TempBuffer0[4]=TH/100+0x30; //分离出TH的百十个位 if( TempBuffer0[4]==0x30) TempBuffer0[4]=0xfe; //百位数消隐 TempBuffer0[5]=(TH0)/10+0x30; //分离出十位 TempBuffer0[6]=(TH0)+0x30; //分离出个位 TempBuffer0[12]=TL/100+0x30; //分离出TL的百十个位 if( TempBuffer0[12]==0x30) TempBuffer0[12]=0xfe; //百位数消隐 TempBuffer0[13]=(TL0)/10+0x30; //分离出十位 TempBuffer0[14]=(TL0)+0x30; //分离出个位 } void covert1(void) //将温度转换为LCD显示的数据 { unsigned char x=0x00,y=0x00; t[0]=*pt; pt++; t[1]=*pt; if(t[1]>0x07) //判断正负温度 { TempBuffer1[0]=0x2d; //0x2d为"-"的ASCII码 t[1]=~t[1]; /*下面几句把负数的补码*/ t[0]=~t[0]; /* 换算成绝对值*********/ x=t[0]+1; /***********************/ t[0]=x; /***********************/ if(x>255) /**********************/ t[1]++; /*********************/ } else TempBuffer1[0]=0x2b; //0xfe为变"+"的ASCII码 t[1]<>=4; //右移4位 x=x&0x0f; //和前面两句就是取出t[0]的高四位 t[1]=t[1]|x; //将高低字节的有效值的整数部分拼成一个字节 if(t[1]>TH) { power=0; } if(t[1]>=2; //左移两位,以便查表 x=t[0]; y=dotcode[x]; //查表换算成实际的小数 TempBuffer1[5]=y/10+0x30; //分离出十分位 TempBuffer1[6]=y+0x30; //分离出百分位 } void delay(unsigned char i) { while(i--); } main() { bit flag1=0; bit flag2=0; //下一步扩展时可能通过这两个变量,调节上下限 power=0; //测温函数返回这个数组的头地址 while(1) { if(mode==0) { if(add==1) { flag1=0; } if(add==0&&flag1==0) { TL++; flag1=1; } if(sub==1) { flag2=0; } if(sub==0&&flag2==0&&TL>20) { TL--; flag2=1; } } if(mode==1) { if(add==1) { flag1=0; } if(add==0&&flag1==0&&TH<50) { TH++; flag1=1; } if(sub==1) { flag2=0; } if(sub==0&&flag2==0) { TH--; flag2=1; } } pt=ReadTemperature(TH,TL,0x3f); //上限温度-22,下限-24,分辨率10位,也就是0.25C //读取温度,温度值存放在一个两个字节的数组中, delay(100); covert1(); covert0(TH,TL); LCD_Initial(); //第一个参数列号,第二个为行号,为0表示第一行 //为1表示第二行,第三个参数为显示数据的首地址 LCD_Print(0,0,TempBuffer0); LCD_Print(0,1,"Cur_Temp:"); LCD_Print(10,1,TempBuffer1); } }
DHT11是一种常用的数字式温湿度传感器,适用于测量环境中的温度和湿度。它具有低成本、简单易用的特点,适用于各种基于单片机温湿度监测应用。 DHT11传感器通过一个单一的数据引脚与微控制器或其他主控设备进行通信。它使用数字信号传输温湿度数据,没有内置的ADC(模数转换器)或I2C等接口,因此只需要一个数字输入引脚即可。 以下是一个使用DHT11传感器和Arduino开发板读取温湿度数据的简单示例: #include <DHT.h> #define DHTPIN 2 // 定义DHT11连接到Arduino的引脚(此处为引脚2) #define DHTTYPE DHT11 // 指定传感器类型为DHT11 DHT dht(DHTPIN, DHTTYPE); void setup() { Serial.begin(9600); dht.begin(); } void loop() { delay(2000); // 延迟2秒 // 读取温湿度数据 float temperature = dht.readTemperature(); float humidity = dht.readHumidity(); // 检查是否成功读取到数据 if (isnan(temperature) || isnan(humidity)) { Serial.println("读取数据失败"); return; } // 打印温湿度数据 Serial.print("温度:"); Serial.print(temperature); Serial.print(" °C"); Serial.print(" 湿度:"); Serial.print(humidity); Serial.println(" %"); } 在上述示例中,我们使用DHT库来与DHT11传感器进行通信,并读取温度和湿度数据。在setup()函数中,我们初始化串口通信和DHT传感器。在loop()函数中,我们通过dht.readTemperature()和dht.readHumidity()函数分别读取温度和湿度数据。然后,我们使用串口输出将温湿度数据打印出来。 请注意,在使用DHT11传感器之前,您需要安装并导入DHT库,可以通过Arduino IDE的库管理器来进行安装。 希望以上示例对您有帮助,可以让您开始使用DHT11传感器读取温湿度数据。如有进一步问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值