完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
功能介绍:
1、LED0约2秒一闪,表示程序运行中。 2、LCD和串口显示实时的温湿度,2秒一循环。上面一个temp是DS18B20,下面的是DHT11。%RH 相对湿度, CEL 摄氏度(ps:不接入DS18B20的话会循环等待) 3、按键都会翻转LED1,KEY1 开启报警模式,KEY0关闭报警模式。(按键10ms一巡检) 4、报警模式下:当温度不低于85摄氏度或者湿度不低于90%RH,蜂鸣器报警。可以通过按下KEY0关闭报警模式。(报警串口会有打印,LCD也会有提示) 接线 DS18B20 VCC -》 3.3V DQ -》 PG11 GND -》 GN DHT11 VCC -》 3.3V DATA -》 PB10 GND -》 GND 效果图 普通环境 普通版main.c 升级版 哈热气 普通版 我这哈了3下 然后持续手扇风 ok,温湿度降下来了。 升级版 搓手捂热 手有汗,湿度也上来了 最后本来应该整个打火机的,可惜没有。夹咯吱窝下(仅DHT11 旧图) 最后来个鼻息 核心代码 普通版main.c #include "led.h" #include "delay.h" #include "sys.h" #include "lcd.h" #include "usart.h" #include "bsp_dht11.h" #include "ds18b20.h" DHT11_Data_TypeDef DHT11_Data; /* DS18B20 供电电压:3 - 5.5V 接线:DQ -》 PG11 (IO口) DHT11 供电电压:3.3 - 5V 接线:DATA -》 PB10 (IO口) */ int main(void) { u8 str[100] = {0}; // DS18B20用变量 short temperature; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(115200); //串口初始化为115200 LED_Init(); //LED端口初始化 LCD_Init(); // LCD初始化 DHT11_GPIO_Config(); // 初始化DTT11的引脚 DATA -> PB10 LED0 = 0; POINT_COLOR = WHITE; BACK_COLOR = BLACK; LCD_Clear(BLACK); while(DS18B20_Init()) //DS18B20初始化 { LCD_ShowString(10,70,200,16,16,"DS18B20 Error"); delay_ms(200); LCD_Fill(10,70,239,130+16,WHITE); delay_ms(200); } LCD_ShowString(10,90,200,16,16,"Temp: . CEL"); while(1) { POINT_COLOR = WHITE; // DS18B20 temperature = DS18B20_Get_Temp(); if(temperature < 0) { LCD_ShowChar(10+40, 90, '-', 16, 0); //显示负号 temperature = -temperature; //转为正数 }else LCD_ShowChar(10+40,90,' ', 16, 0); //去掉负号 LCD_ShowNum(10+40+8, 90, temperature/10, 2, 16); //显示正数部分 LCD_ShowNum(10+40+32, 90,temperature%10, 1, 16); //显示小数部分 printf("温度为 %u.%u℃ rn",temperature/10, temperature%10); // DHT11 // 调用Read_DHT11读取温湿度,若成功则输出该信息 if( Read_DHT11(&DHT11_Data) == SUCCESS) { printf("湿度为%d.%d %RH ,温度为 %d.%d℃ rn", DHT11_Data.humi_int, DHT11_Data.humi_deci, DHT11_Data.temp_int, DHT11_Data.temp_deci); sprintf((char*)str, "HUM: %d.%d%%RH ", DHT11_Data.humi_int, DHT11_Data.humi_deci); LCD_ShowString(10,130,200,24,24, str); sprintf((char*)str, "TEMP: %d.%dCEL ", DHT11_Data.temp_int, DHT11_Data.temp_deci); LCD_ShowString(10,170,200,24,24, str); //printf("rn 湿度:%d,温度:%d rn" ,DHT11_Data.humi_int,DHT11_Data.temp_int); } else { printf("Read DHT11 ERROR!rn"); } LED0 = !LED0; // 采样周期不得低于1秒,否则会读取失败 delay_ms(1000); delay_ms(1000); } } 升级版main.c #include "led.h" #include "delay.h" #include "sys.h" #include "lcd.h" #include "usart.h" #include "bsp_dht11.h" #include "ds18b20.h" #include "key.h" #include "beep.h" DHT11_Data_TypeDef DHT11_Data; /* DS18B20 供电电压:3 - 5.5V 接线:DQ -》 PG11 (IO口) DHT11 供电电压:3.3 - 5V 接线:DATA -》 PB10 (IO口) */ int main(void) { u8 str[100] = {0}; // 蜂鸣器报警标志位 u8 flag = 0; // 报警模式 u8 mode = 0; vu8 key = 0; // 循环计数 u8 time = 0; // DS18B20用变量 short temperature; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(115200); //串口初始化为115200 LED_Init(); //LED端口初始化 LCD_Init(); // LCD初始化 KEY_Init(); // KEY初始化 BEEP_Init(); // BEEP初始化 DHT11_GPIO_Config(); // 初始化DTT11的引脚 DATA -> PB10 LED0 = 0; LED1 = 0; POINT_COLOR = WHITE; BACK_COLOR = BLACK; LCD_Clear(BLACK); while(DS18B20_Init()) //DS18B20初始化 { LCD_ShowString(10,70,200,16,16,"DS18B20 Error"); delay_ms(200); LCD_Fill(10,70,239,130+16, BLACK); delay_ms(200); } LCD_ShowString(10,90,200,16,16,"Temp: . CEL"); LCD_ShowString(10,220,220,12,12,"TOUCH KEY0 CLOSE ALARM MODE"); LCD_ShowString(10,240,220,12,12,"TOUCH KEY1 OPEN ALARM MODE"); POINT_COLOR = RED; LCD_ShowString(10,260,100,12,12,"ALARM MODE: OFF"); POINT_COLOR = WHITE; while(1) { flag = 2; POINT_COLOR = WHITE; key = KEY_Scan(0); //得到键值 if (key) { switch (key) { case WKUP_PRES: LED1 = !LED1; break; // KEY1 按下 开启报警模式 case KEY1_PRES: mode = 1; LED1 = !LED1; LCD_ShowString(80,260,100,12,12,"ON "); printf("开启报警模式rn"); break; // KEY1 按下 关闭报警模式 case KEY0_PRES: mode = 0; LED1 = !LED1; LCD_ShowString(80,260,100,12,12,"OFF "); printf("关闭报警模式rn"); break; } } // 约2秒一次 if(time % 200 == 0) { // DS18B20 temperature = DS18B20_Get_Temp(); if(temperature < 0) { LCD_ShowChar(10+40, 90, '-', 16, 0); //显示负号 temperature = -temperature; //转为正数 }else LCD_ShowChar(10+40,90,' ', 16, 0); //去掉负号 LCD_ShowNum(10+40+8, 90, temperature/10, 2, 16); //显示正数部分 LCD_ShowNum(10+40+32, 90,temperature%10, 1, 16); //显示小数部分 printf("温度为 %u.%u℃ rn",temperature/10, temperature%10); // DHT11 // 调用Read_DHT11读取温湿度,若成功则输出该信息 采样周期不得低于1秒,否则会读取失败 if( Read_DHT11(&DHT11_Data) == SUCCESS) { printf("湿度为%d.%d %RH ,温度为 %d.%d℃ rn", DHT11_Data.humi_int, DHT11_Data.humi_deci, DHT11_Data.temp_int, DHT11_Data.temp_deci); sprintf((char*)str, "HUM: %d.%d%%RH ", DHT11_Data.humi_int, DHT11_Data.humi_deci); LCD_ShowString(10,130,200,24,24, str); sprintf((char*)str, "TEMP: %d.%dCEL ", DHT11_Data.temp_int, DHT11_Data.temp_deci); LCD_ShowString(10,170,200,24,24, str); //printf("rn 湿度:%d,温度:%d rn" ,DHT11_Data.humi_int,DHT11_Data.temp_int); } else { printf("Read DHT11 ERROR!rn"); } // 判断温度是否不低于85摄氏度 if(temperature >= 850 || DHT11_Data.temp_int >= 85) { printf("温度过高!!!rn"); flag++; } else { flag--; } // 判断湿度是否高于90%RH if(DHT11_Data.humi_int >= 90) { printf("湿度过高!!!rn"); flag++; } else { flag--; } // 判断是否需要报警 if(flag >= 2 && mode == 1) { LCD_ShowString(10,200,200,16,16,"BEEP!!!(>__<)"); printf("BEEP!!!(>__<)rn"); BEEP = 1; } if(flag < 2) { LCD_ShowString(10,200,200,16,16," (- v -) "); BEEP = 0; } // 重新置零 time = 0; LED0 = !LED0; } if(mode == 0) { LCD_ShowString(10,200,200,16,16," (- v -) "); BEEP = 0; } time++; delay_ms(10); } } bsp_dht11.h #ifndef __DHT11_H #define __DHT11_H #include "stm32f10x.h" #include "delay.h" #define HIGH 1 #define LOW 0 #define DHT11_CLK RCC_APB2Periph_GPIOB #define DHT11_PIN GPIO_Pin_10 #define DHT11_PORT GPIOB //带参宏,可以像内联函数一样使用,输出高电平或低电平 #define DHT11_DATA_OUT(a) if (a) GPIO_SetBits(GPIOB,GPIO_Pin_10); else GPIO_ResetBits(GPIOB,GPIO_Pin_10) //读取引脚的电平 #define DHT11_DATA_IN() GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10) typedef struct { uint8_t humi_int; //湿度的整数部分 uint8_t humi_deci; //湿度的小数部分 uint8_t temp_int; //温度的整数部分 uint8_t temp_deci; //温度的小数部分 uint8_t check_sum; //校验和 }DHT11_Data_TypeDef; void DHT11_GPIO_Config(void); static void DHT11_Mode_IPU(void); static void DHT11_Mode_Out_PP(void); uint8_t Read_DHT11(DHT11_Data_TypeDef *DHT11_Data); static uint8_t Read_Byte(void); #endif /* __DHT11_H */ bsp_dht11.c #include "bsp_dht11.h" /* * 函数名:DHT11_GPIO_Config * 描述 :配置DHT11用到的I/O口 * 输入 :无 * 输出 :无 */ void DHT11_GPIO_Config(void) { /*定义一个GPIO_InitTypeDef类型的结构体*/ GPIO_InitTypeDef GPIO_InitStructure; /*开启DHT11_PORT的外设时钟*/ RCC_APB2PeriphClockCmd(DHT11_CLK, ENABLE); /*选择要控制的DHT11_PORT引脚*/ GPIO_InitStructure.GPIO_Pin = DHT11_PIN; /*设置引脚模式为通用推挽输出*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*设置引脚速率为50MHz */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*调用库函数,初始化DHT11_PORT*/ GPIO_Init(DHT11_PORT, &GPIO_InitStructure); /* 拉高GPIOB10 */ GPIO_SetBits(DHT11_PORT, GPIO_Pin_10); } /* * 函数名:DHT11_Mode_IPU * 描述 :使DHT11-DATA引脚变为上拉输入模式 * 输入 :无 * 输出 :无 */ static void DHT11_Mode_IPU(void) { GPIO_InitTypeDef GPIO_InitStructure; /*选择要控制的DHT11_PORT引脚*/ GPIO_InitStructure.GPIO_Pin = DHT11_PIN; /*设置引脚模式为浮空输入模式*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; /*调用库函数,初始化DHT11_PORT*/ GPIO_Init(DHT11_PORT, &GPIO_InitStructure); } /* * 函数名:DHT11_Mode_Out_PP * 描述 :使DHT11-DATA引脚变为推挽输出模式 * 输入 :无 * 输出 :无 */ static void DHT11_Mode_Out_PP(void) { GPIO_InitTypeDef GPIO_InitStructure; /*选择要控制的DHT11_PORT引脚*/ GPIO_InitStructure.GPIO_Pin = DHT11_PIN; /*设置引脚模式为通用推挽输出*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*设置引脚速率为50MHz */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*调用库函数,初始化DHT11_PORT*/ GPIO_Init(DHT11_PORT, &GPIO_InitStructure); } /* * 从DHT11读取一个字节,MSB先行 */ static uint8_t Read_Byte(void) { uint8_t i, temp=0; for(i=0;i<8;i++) { /*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/ while(DHT11_DATA_IN()==Bit_RESET); /*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”, *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 */ delay_us(40); //延时x us 这个延时需要大于数据0持续的时间即可 if(DHT11_DATA_IN()==Bit_SET)/* x us后仍为高电平表示数据“1” */ { /* 等待数据1的高电平结束 */ while(DHT11_DATA_IN()==Bit_SET); temp|=(uint8_t)(0x01<<(7-i)); //把第7-i位置1,MSB先行 } else // x us后为低电平表示数据“0” { temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行 } } return temp; } /* * 一次完整的数据传输为40bit,高位先出 * 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和 */ uint8_t Read_DHT11(DHT11_Data_TypeDef *DHT11_Data) { /*输出模式*/ DHT11_Mode_Out_PP(); /*主机拉低*/ DHT11_DATA_OUT(LOW); /*延时18ms*/ delay_ms(18); /*总线拉高 主机延时30us*/ DHT11_DATA_OUT(HIGH); delay_us(30); //延时30us /*主机设为输入 判断从机响应信号*/ DHT11_Mode_IPU(); /*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/ if(DHT11_DATA_IN() == Bit_RESET) { /*轮询直到从机发出 的80us 低电平 响应信号结束*/ while(DHT11_DATA_IN()==Bit_RESET); /*轮询直到从机发出的 80us 高电平 标置信号结束*/ while(DHT11_DATA_IN()==Bit_SET); /*开始接收数据*/ DHT11_Data->humi_int= Read_Byte(); DHT11_Data->humi_deci= Read_Byte(); DHT11_Data->temp_int= Read_Byte(); DHT11_Data->temp_deci= Read_Byte(); DHT11_Data->check_sum= Read_Byte(); /*读取结束,引脚改为输出模式*/ DHT11_Mode_Out_PP(); /*主机拉高*/ DHT11_DATA_OUT(HIGH); /*检查读取的数据是否正确*/ if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci) return SUCCESS; else return ERROR; } else { return ERROR; } } |
|
|
|
ds18b20.h
#ifndef __DS18B20_H #define __DS18B20_H #include "sys.h" // //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK战舰STM32开发板 //DS18B20驱动代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //修改日期:2012/9/12 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved // //IO方向设置 #define DS18B20_IO_IN() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;} #define DS18B20_IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;} IO操作函数 #define DS18B20_DQ_OUT PGout(11) //数据端口 PA0 #define DS18B20_DQ_IN PGin(11) //数据端口 PA0 u8 DS18B20_Init(void);//初始化DS18B20 short DS18B20_Get_Temp(void);//获取温度 void DS18B20_Start(void);//开始温度转换 void DS18B20_Write_Byte(u8 dat);//写入一个字节 u8 DS18B20_Read_Byte(void);//读出一个字节 u8 DS18B20_Read_Bit(void);//读出一个位 u8 DS18B20_Check(void);//检测是否存在DS18B20 void DS18B20_Rst(void);//复位DS18B20 #endif ds18b20.c #include "ds18b20.h" #include "delay.h" // //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK精英STM32开发板 //DS18B20驱动代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //修改日期:2012/9/12 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved // //复位DS18B20 void DS18B20_Rst(void) { DS18B20_IO_OUT(); //SET PG11 OUTPUT DS18B20_DQ_OUT=0; //拉低DQ delay_us(750); //拉低750us DS18B20_DQ_OUT=1; //DQ=1 delay_us(15); //15US } //等待DS18B20的回应 //返回1:未检测到DS18B20的存在 //返回0:存在 u8 DS18B20_Check(void) { u8 retry=0; DS18B20_IO_IN(); //SET PG11 INPUT while (DS18B20_DQ_IN&&retry<200) { retry++; delay_us(1); }; if(retry>=200)return 1; else retry=0; while (!DS18B20_DQ_IN&&retry<240) { retry++; delay_us(1); }; if(retry>=240)return 1; return 0; } //从DS18B20读取一个位 //返回值:1/0 u8 DS18B20_Read_Bit(void) { u8 data; DS18B20_IO_OUT(); //SET PG11 OUTPUT DS18B20_DQ_OUT=0; delay_us(2); DS18B20_DQ_OUT=1; DS18B20_IO_IN(); //SET PG11 INPUT delay_us(12); if(DS18B20_DQ_IN)data=1; else data=0; delay_us(50); return data; } //从DS18B20读取一个字节 //返回值:读到的数据 u8 DS18B20_Read_Byte(void) { u8 i,j,dat; dat=0; for (i=1;i<=8;i++) { j=DS18B20_Read_Bit(); dat=(j<<7)|(dat>>1); } return dat; } //写一个字节到DS18B20 //dat:要写入的字节 void DS18B20_Write_Byte(u8 dat) { u8 j; u8 testb; DS18B20_IO_OUT(); //SET PG11 OUTPUT; for (j=1;j<=8;j++) { testb=dat&0x01; dat=dat>>1; if (testb) { DS18B20_DQ_OUT=0; // Write 1 delay_us(2); DS18B20_DQ_OUT=1; delay_us(60); } else { DS18B20_DQ_OUT=0; // Write 0 delay_us(60); DS18B20_DQ_OUT=1; delay_us(2); } } } //开始温度转换 void DS18B20_Start(void) { DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xcc); // skip rom DS18B20_Write_Byte(0x44); // convert } //初始化DS18B20的IO口 DQ 同时检测DS的存在 //返回1:不存在 //返回0:存在 u8 DS18B20_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); //使能PORTG口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PORTG.11 推挽输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOG, &GPIO_InitStructure); GPIO_SetBits(GPIOG,GPIO_Pin_11); //输出1 DS18B20_Rst(); return DS18B20_Check(); } //从ds18b20得到温度值 //精度:0.1C //返回值:温度值 (-550~1250) short DS18B20_Get_Temp(void) { u8 temp; u8 TL,TH; short tem; DS18B20_Start (); // ds1820 start convert DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xcc); // skip rom DS18B20_Write_Byte(0xbe); // convert TL=DS18B20_Read_Byte(); // LSB TH=DS18B20_Read_Byte(); // MSB if(TH>7) { TH=~TH; TL=~TL; temp=0; //温度为负 }else temp=1; //温度为正 tem=TH; //获得高八位 tem<<=8; tem+=TL; //获得底八位 tem=(float)tem*0.625; //转换 if(temp)return tem; //返回温度值 else return -tem; } 参考用图 DHT11 DS18B20 |
|
|
|
只有小组成员才能发言,加入小组>>
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
382 浏览 1 评论
250 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
230 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
590 浏览 2 评论
615 浏览 2 评论
1345浏览 9评论
0浏览 3评论
27浏览 3评论
STM32CUBEMX4.22.1在main函数里面添加一行语句就死机的原因?
28浏览 3评论
31浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-4-19 09:45 , Processed in 0.555914 second(s), Total 46, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号