首页 分享 STM32项目设计:基于STM32的DHT11、MQ

STM32项目设计:基于STM32的DHT11、MQ

来源:花匠小妙招 时间:2025-01-09 23:32

一、项目功能概述

1、通过DHT11温湿度模块检测温湿度
2、通过MQ-2烟雾传感器检测烟雾
3、通过光敏电阻模块检测光照强度
4、oled液晶屏显示实时检测到的数据
5、超限蜂鸣器报警
在这里插入图片描述

源码下载地址:基于STM32的DHT11、MQ-2、光照强度检测

二、材料选择

1、主控 STM32F103C8T6
本人是自己制作的最小系统版,主要目的省钱!!!!
在这里插入图片描述
2、DHT11温湿度模块
在这里插入图片描述
3、MQ-2烟雾传感器模块
在这里插入图片描述
4、光敏电阻模块

在这里插入图片描述
5、0.96 OLED液晶屏
在这里插入图片描述
6、蜂鸣器模块
在这里插入图片描述

三、原理图设计

1、DHT11连接图
在这里插入图片描述
2、OLED液晶模块连接图
在这里插入图片描述
3、MQ-2硬件连接图
在这里插入图片描述
4、光敏电阻模块硬件连接图
在这里插入图片描述
5、蜂鸣器模块硬件连接图
在这里插入图片描述

四、成品展示

1、上电界面
由于相机刷新率比较快,拍屏幕会有闪!!!
在这里插入图片描述
2、开来台灯后,光照强度数值明显提升!!!
在这里插入图片描述
剩下的温湿度和烟雾浓度就不贴图片了,没法直观表示数据更新!!!

五、源码设计

OLED.c

#include "oled.h" #include "codetab.h" #include "main.h" #include "string.h" #include "i2c.h" #include "./usart/bsp_debug_usart.h" #include "dht11.h" #include "key.h" #include "bsp_led.h" #define IIC_SCK_0 GPIOA->BRR=0X0080 // 设置sck接口到PA7 置零 #define IIC_SCK_1 GPIOA->BSRR=0X0080 //置位 #define IIC_SDA_0 GPIOB->BRR=0X0001 // 设置SDA接口到PB0 置零 #define IIC_SDA_1 GPIOB->BSRR=0X0001 // 复位 char mStrVol[20]; char mStrCul[20]; char mStrtemp[20]; char mStrhum[20]; char mStrSpeed[20]; char mStrDirec[20]; uint16_t mVolValue; uint16_t mCulValue; extern uint8_t shidu ; extern uint8_t wendu; extern uint16_t value1; extern uint16_t value2; unsigned int GetDeltaTicks(unsigned int tickcount) {unsigned int now = GetTickCount();returnnow >= tickcount ? (now - tickcount) : (0xFFFFFFFF - tickcount + now); } void I2C_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure;__HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitStructure.Pin = GPIO_PIN_7 ; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStructure.Pull = GPIO_PULLUP;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);//SCL引脚初始化HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7 ,GPIO_PIN_SET);GPIO_InitStructure.Pin = GPIO_PIN_0 ; HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);//SDA引脚初始化HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0 ,GPIO_PIN_SET); } void delay_us(unsigned int _us_time) { unsigned char x=0; for(;_us_time>0;_us_time--) { x++;x++;x++;x++;x++;x++;x++;x++;x++;x++;x++;x++; x++;x++;x++;x++;x++;x++;x++;x++;x++;x++;x++;x++; x++;x++;x++;x++;x++;x++;x++;x++;x++;x++;x++;x++; } } void delay_ms(unsigned int _ms_time) {unsigned int i,j;for(i=0;i<_ms_time;i++){for(j=0;j<900;j++){;}} } const unsigned char OLED_init_cmd[25]= { /*0xae,0X00,0X10,0x40,0X81,0XCF,0xff,0xa1,0xa4, 0xA6,0xc8,0xa8,0x3F,0xd5,0x80,0xd3,0x00,0XDA,0X12, 0x8d,0x14,0xdb,0x40,0X20,0X02,0xd9,0xf1,0xAF*/ 0xAE,//关闭显示 0xD5,//设置时钟分频因子,震荡频率 0x80, //[3:0],分频因子;[7:4],震荡频率 0xA8,//设置驱动路数 0X3F,//默认0X3F(1/64) 0xD3,//设置显示偏移 0X00,//默认为0 0x40,//设置显示开始行 [5:0],行数. 0x8D,//电荷泵设置 0x14,//bit2,开启/关闭 0x20,//设置内存地址模式 0x02,//[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10; 0xA1,//段重定义设置,bit0:0,0->0;1,0->127; 0xC8,//设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数 0xDA,//设置COM硬件引脚配置 0x12,//[5:4]配置 0x81,//对比度设置 0xEF,//1~255;默认0X7F (亮度设置,越大越亮) 0xD9,//设置预充电周期 0xf1,//[3:0],PHASE 1;[7:4],PHASE 2; 0xDB,//设置VCOMH 电压倍率 0x30,//[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc; 0xA4,//全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏) 0xA6,//设置显示方式;bit0:1,反相显示;0,正常显示 0xAF,//开启显示 }; /***************************************** 字节数据发送函数 函数原型:void IIC_write(unsigned char date); 功能:将数据date发送出去,可以是地址,也可以是数据 ******************************************/ void IIC_write(unsigned char date) {unsigned char i, temp;temp = date;for(i=0; i<8; i++)//传送数据长度为8位{IIC_SCK_0; if ((temp&0x80)==0)//判断发送位 IIC_SDA_0; else IIC_SDA_1;temp = temp << 1;delay_us(1);IIC_SCK_1;delay_us(1);}IIC_SCK_0;delay_us(1);IIC_SDA_1;delay_us(1);IIC_SCK_1;delay_us(1);IIC_SCK_0;delay_us(1); } /************************************************************************* 功能:启动I2C总线,即发送I2C起始条件。SCL为高电平期间,SDA出现下降沿 **************************************************************************/ void IIC_start() {IIC_SDA_1;delay_us(1);IIC_SCK_1;delay_us(1); //所有操作结束释放SCLIIC_SDA_0;delay_us(3);IIC_SCK_0; IIC_write(0x78); } /************************************************************************* 功能:结束I2C总线,即发送I2C结束条件。SCL为高电平期间,SDA出现上升沿 **************************************************************************/ void IIC_stop() {IIC_SDA_0;delay_us(1);IIC_SCK_1;delay_us(3);IIC_SDA_1; } void OLED_send_cmd(unsigned char o_command) {IIC_start();IIC_write(0x00);IIC_write(o_command);IIC_stop(); } void OLED_send_data(unsigned char o_data) {IIC_start();IIC_write(0x40);IIC_write(o_data);IIC_stop(); } void Column_set(unsigned char column) {OLED_send_cmd(0x10|(column>>4)); //设置列地址高位OLED_send_cmd(0x00|(column&0x0f)); //设置列地址低位 } void Page_set(unsigned char page) {OLED_send_cmd(0xb0+page); } void OLED_clear(void) {unsigned char page,column;for(page=0;page<8;page++) //page loop { Page_set(page); Column_set(0); for(column=0;column<128;column++)//column loop{ OLED_send_data(0x00);} } } void OLED_full(void) {unsigned char page,column;for(page=0;page<8;page++) //page loop {Page_set(page);Column_set(0);for(column=0;column<128;column++)//column loop {OLED_send_data(0xff); } } } void OLED_init(void) {unsigned char i;for(i=0;i<25;i++){OLED_send_cmd(OLED_init_cmd[i]);}OLED_clear(); //OLED_Chinese16x16Str(0,0,Chinese_WEN_F16X16); //OLED_Chinese16x16Str(2,0,Chinese_DU_F16X16); //OLED_Chinese16x16Str(0,1,Chinese_SHII_F16X16); //OLED_Chinese16x16Str(2,1,Chinese_DU_F16X16); //OLED_Chinese16x16Str(0,4,Chinese_GUANG_F16X16); //OLED_Chinese16x16Str(2,4,Chinese_ZHAO_F16X16); // //OLED_Chinese16x16Str(0,6,Chinese_YAN_F16X16); //OLED_Chinese16x16Str(2,6,Chinese_WU_F16X16); //OLED_Chinese16x16Str(3,2,Chinese_YE_F16X16); //OLED_Chinese16x16Str(4,2,Chinese_SHE_F16X16); //OLED_Chinese16x16Str(5,2,Chinese_JII_F16X16); //// HAL_Delay(1000); ////OLED_clear(); // //OLED_Chinese16x16Str(1,0,Chinese_Liu_F16X16); //OLED_Chinese16x16Str(2,0,Chinese_Tang_F16X16); //OLED_Chinese16x16Str(3,0,Chinese_CHONG_F16X16); //OLED_Chinese16x16Str(4,0,Chinese_WU_F16X16); //OLED_Chinese16x16Str(5,0,Chinese_WEI_F16X16); //OLED_Chinese16x16Str(6,0,Chinese_SHI_F16X16); //OLED_Chinese16x16Str(7,0,Chinese_QI_F16X16); } void Picture_display(const unsigned char *ptr_pic) {unsigned char page,column;for(page=0;page<(64/8);page++) //page loop {Page_set(page);Column_set(0);for(column=0;column<128;column++)//column loop {OLED_send_data(*ptr_pic++); } } } void Picture_ReverseDisplay(const unsigned char *ptr_pic) { unsigned char page,column,data; for(page=0;page<(64/8);page++) //page loop { Page_set(page); Column_set(0); for(column=0;column<128;column++)//column loop { data=*ptr_pic++; data=~data; OLED_send_data(data); } } } void OLED_Set_Pos(uint8_t x, uint8_t y) {OLED_send_cmd(0xb0+y);OLED_send_cmd(((x&0xf0)>>4)|0x10);OLED_send_cmd((x&0x0f)|0x01); } void OLED_Chinese16x16Str(uint8_t x,uint8_t y,const uint8_t * ch) {uint8_t i;uint8_tj,k =0;j = x<<4;//列 0~7该字符占2*8bitsk = y<<1;//行 0~4该字符占2*8bitsOLED_Set_Pos(j,k);for(i=0;i<16;i++)OLED_send_data(*(ch+i));OLED_Set_Pos(j,k+1);for(i=16;i<32;i++)OLED_send_data(*(ch+i)); } void OLED_OneByte(uint8_t x,uint8_t y,uint8_t k) {uint8_t c=0,i=0,z =0;z = x*6;//获取起始位置c =k-32;if(z>126){z=0;y++;}OLED_Set_Pos(z,y); //设置地址/*一个ascii显示需要6个8bit数据*/for(i=0;i<6;i++)OLED_send_data(F6x8[c][i]); } void OLED_P6x8Str(uint8_t x,uint8_t y,int8_t ch[]) {uint8_t c=0,i=0,j=0,z =0;z = x*6;//while (ch[j]!=''){c =ch[j]-32;if(z>126){z=0;y++;}OLED_Set_Pos(z,y);for(i=0;i<6;i++)OLED_send_data(F6x8[c][i]);z+=6;j++;} } void OLED_P8x16Str(uint8_t x,uint8_t y,uint8_t *chr) {uint8_t j=0;uint8_t c = 0, i = 0;while (chr[j]!=''){c = chr[j] - ' ' ;OLED_Set_Pos(x,y);for(i=0;i<8;i++)OLED_send_data(F8X16[c*16+i]);OLED_Set_Pos(x,y+1);for(i=0;i<8;i++)OLED_send_data(F8X16[c*16+i+8]);x+=8;if(x>120){x=0;y+=2;}j++;} } 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376

DHT11.c

#include "dht11.h" #include "main.h" #include "oled.h" void delay_uss(unsigned int us) { uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);while(delay--){;} } void DHT11_Rst(void) {DHT11_IO_OUT();//SET OUTPUT DHT11_DQ_OUT=0;//拉低DQ HAL_Delay(25);//拉低至少18ms DHT11_DQ_OUT=1;//DQ=1delay_uss(30);//主机拉高20~40us } //等待DHT11的回应 //返回1:未检测到DHT11的存在 //返回0:存在 u8 DHT11_Check(void) {u8 retry=0;DHT11_IO_IN();//SET INPUT while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us{retry++;delay_uss(1);};if(retry>=100)return 1;else retry=0; while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us{retry++;delay_uss(1);};if(retry>=100)return 1;return 0; } //从DHT11读取一个位 //返回值:1/0 u8 DHT11_Read_Bit(void) {u8 retry=0;while(DHT11_DQ_IN&&retry<100)//等待变为低电平{retry++;delay_uss(1);}retry=0;while(!DHT11_DQ_IN&&retry<100)//等待变高电平{retry++;delay_uss(1);}delay_us(40);//等待40usif(DHT11_DQ_IN)return 1;else return 0; } //从DHT11读取一个字节 //返回值:读到的数据 u8 DHT11_Read_Byte(void) { u8 i,dat; dat=0;for (i=0;i<8;i++){dat<<=1; dat|=DHT11_Read_Bit(); } return dat; } //从DHT11读取一次数据 //temp:温度值(范围:0~50°) //humi:湿度值(范围:20%~90%) //返回值:0,正常;1,读取失败 u8 DHT11_Read_Data(u8 *temp,u8 *humi) {u8 buf[5];u8 i;DHT11_Rst();if(DHT11_Check()==0){for(i=0;i<5;i++)//读取40位数据{buf[i]=DHT11_Read_Byte();}if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){*humi=buf[0];*temp=buf[2];}}else return 1;return 0; } //初始化DHT11的IO口 DQ 同时检测DHT11的存在 //返回1:不存在 //返回0:存在 u8 DHT11_Init(void) {GPIO_InitTypeDef GPIO_InitStructure;__HAL_RCC_GPIOA_CLK_ENABLE();GPIO_InitStructure.Pin = GPIO_PIN_11; //PG11端口配置GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;//GPIO_InitStructure.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO口HAL_GPIO_WritePin(GPIOA,GPIO_PIN_11 ,GPIO_PIN_SET); //PG11 输出高DHT11_Rst(); //复位DHT11return DHT11_Check();//等待DHT11的回应 } 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122

相关知识

基于STM32设计的环境检测设备
基于STM32的智能花盆浇水系统设计
探索智能环境监测:基于STM32的温湿度与光照检测系统
基于STM32的花卉大棚环境监测系统设计
基于STM32单片机的温室环境监测系统设计.pdf
基于STM32和云平台的花卉养护系统设计(微信小程序)(209)
基于STM32单片机的环境监测系统设计与实现
基于STM32的房间湿度控制系统设计与实现(论文+源码)
基于STM32的光照检测系统设计
基于STM32的植物浇水系统开发

网址: STM32项目设计:基于STM32的DHT11、MQ https://www.huajiangbk.com/newsview1515443.html

所属分类:花卉
上一篇: 光照强度检测
下一篇: 基于单片机的光照强度控制系统设计

推荐分享