STM32读取MQ4传感器、DHT11温湿度传感器、GP2Y1014AU0F夏普光学灰尘传感器数据

 

1.功能

STM32测量MQ4、灰尘传感器、DHT11温湿度传感器,并在TFT上显示,超过浓度阈值蜂鸣器报警。

使用普中STM32F103ZET6开发板+2.8寸触摸屏。

2.MQ4天然气传感器

MQ-4传感器简介:

MQ- 4气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2)。当传感器所处环境中存在可燃气体时,传感器的电导率随空气中可燃气体浓度的增加而增大。使用简单的电路即可将电导率的变化转换为与该气体浓度相对应的输出信号。 MQ-4气体传感器对甲烷的灵敏度高,对丙烷、丁烷也有较好的灵敏度。这种传感器可检测多种可燃性气体,特别是天然气,是一款适合多种应用的低成本传感器。

模块应用:

适用于家庭或工厂的甲烷气体,天然气等监测装置,可测试天然气、甲烷 300 to 10000ppm;

模块特色:

1、采用优质双面板设计,具有电源指示和TTL信号输出指示;

2、具有DO开关信号(TTL)输出和AO模拟信号输出;

3、TTL输出有效信号为低电平。(当输出低电平时信号灯亮,可直接接单片机或继电器模块)

4、模拟量输出的电压,浓度越高电压越高。

5、对甲烷、天然气检测有较好的灵敏度。

6、有四个螺丝孔便于定位;

7、产品外形尺寸:32(L)*20(W)*22(H)

8、具有长期的使用寿命和可靠的稳定性

9、快速的响应恢复特性

 

 

电气性能:

输入电压:DC5V 功耗(电流):150mA

DO输出:TTL数字量0和1(0.1和5V)

AO输出:0.1-0.3V(相对无污染),最高浓度电压4V左右

特别提醒:传感器通电后,需要预热20S左右,测量的数据才稳定,传感器发热属于正常现象,因为内部有电热丝,如果烫手就不正常了。

 

 

接线方式:

1、VCC:接电源正极(5V)

2、GND:接电源负极

3、DO:TTL开关信号输出

4、AO:模拟信号输出

 

 

关键代码及说明:

 

void MQ4_ADC_init()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO|RCC_APB2Periph_ADC2,ENABLE);

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//12M  最大14M 设置ADC时钟(ADCCLK)
	ADC_DeInit(ADC2);

	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;//ADC
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;	//模拟输入
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
 

	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 
	ADC_InitStructure.ADC_ScanConvMode = DISABLE; 
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; 
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 
	ADC_InitStructure.ADC_NbrOfChannel = 2; 
	ADC_Init(ADC2, &ADC_InitStructure);
	
	//设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
//	ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5);
	
	//内部温度传感器是在ADC1通道16的。
	ADC_RegularChannelConfig(ADC2,ADC_Channel_2,1,ADC_SampleTime_239Cycles5);
//	ADC_TempSensorVrefintCmd(ENABLE);//打开内部温度传感器使能
	ADC_Cmd(ADC2,ENABLE);	

	ADC_ResetCalibration(ADC2);//重置指定的ADC的校准寄存器
	while(ADC_GetResetCalibrationStatus(ADC2));//获取ADC重置校准寄存器的状态
	
	ADC_StartCalibration(ADC2);//开始指定ADC的校准状态
	while(ADC_GetCalibrationStatus(ADC2));//获取指定ADC的校准程序

	ADC_SoftwareStartConvCmd(ADC2, ENABLE);//使能或者失能指定的ADC的软件转换启动功能
}

 

u16 GetMQ4Value(void)
{
			uint16_t ADCVal;
			float Voltage;
			uint16_t ppm;
			ADC_SoftwareStartConvCmd(ADC2, ENABLE);
	    while(!ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC ));
			ADCVal = ADC_GetConversionValue(ADC2);
			Voltage = ADCVal * 3.3 / 4096;
	//无天然气的环境下,实测AOUT端的电压为0.5V,当检测到天然气时,电压每升高0.1V,实际被测气体浓度增加200ppm
			ppm = (Voltage - 0.5) / 0.1 * 200;
			return ppm;
			//return ADCVal;
}

 

int Read_MQ4_DOUT_Data()
{
	int status;
	status = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3);
	return status;
}

 

3.DHT11温湿度传感器

 

//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在    	 
u8 DHT11_Init(void)
{	 
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);	 //使能PG端口时钟
	
 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;				 //PG11端口配置
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOG, &GPIO_InitStructure);				 //初始化IO口
 	GPIO_SetBits(GPIOG,GPIO_Pin_11);						 //PG11 输出高
			    
	DHT11_Rst();  //复位DHT11
	return DHT11_Check();//等待DHT11的回应
} 

 

//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
u8 DHT11_Read_Data(u16 *temp,u16 *humi)    
{        
 	float 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;	    
}

 

4.GP2Y1014AU0F夏普光学灰尘传感器

参考链接:https://detail.tmall.com/item.htm?spm=a230r.1.14.4.1a81Dr&id=544189174002&cm_id=140105335569ed55e27b&abbucket=9

 

http://blog.sina.com.cn/s/blog_72359bde010191m0.html

 

添加一个150ohm的电阻和一个220uF的电容,接线如下图:

 

 

void GP2Y_ADC_init()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF|RCC_APB2Periph_AFIO|RCC_APB2Periph_ADC3,ENABLE);

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//12M  最大14M 设置ADC时钟(ADCCLK)
	ADC_DeInit(ADC3);

	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;//ADC
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;	//模拟输入
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOF,&GPIO_InitStructure);
 

	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 
	ADC_InitStructure.ADC_ScanConvMode = DISABLE; 
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; 
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 
	ADC_InitStructure.ADC_NbrOfChannel = 4; 
	ADC_Init(ADC3, &ADC_InitStructure);
	
	//设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
//	ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5);
	
	//内部温度传感器是在ADC1通道16的。
	ADC_RegularChannelConfig(ADC3,ADC_Channel_4,1,ADC_SampleTime_239Cycles5);
//	ADC_TempSensorVrefintCmd(ENABLE);//打开内部温度传感器使能
	ADC_Cmd(ADC3,ENABLE);	

	ADC_ResetCalibration(ADC3);//重置指定的ADC的校准寄存器
	while(ADC_GetResetCalibrationStatus(ADC3));//获取ADC重置校准寄存器的状态
	
	ADC_StartCalibration(ADC3);//开始指定ADC的校准状态
	while(ADC_GetCalibrationStatus(ADC3));//获取指定ADC的校准程序

	ADC_SoftwareStartConvCmd(ADC3, ENABLE);//使能或者失能指定的ADC的软件转换启动功能
	GPIO_SetBits(GPIOC, GPIO_Pin_2);//置1

 

u16 GetGP2YAverageValue(u8 times)
{
    u32 temp_val=0;
    u8 t;
    for(t=0;t<times;t++)
    {
        temp_val+=GetGP2YSingleValue();
    }
    return temp_val/times;
}

u16 GetGP2YSingleValue(void)
{
		int samplingTime = 280;//等待LED开启的时间是280μs
		int deltaTime = 40;//整个脉冲持续时间为320μs。因此,我们还需再等待40μs
	
		uint16_t ADCVal;
		float dustVal = 0;
		float Voltage;
	
		GPIO_ResetBits(GPIOC, GPIO_Pin_2);//置1  开启内部LED  ????????
		delay_us(samplingTime); 					// 开启LED后的280us的等待时间
		
		ADC_SoftwareStartConvCmd(ADC3, ENABLE);
    while(!ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC));
		ADCVal = ADC_GetConversionValue(ADC3);
	
		delay_us(40);
		GPIO_SetBits(GPIOC, GPIO_Pin_2);//置0
		delay_us(9680);//需要脉宽比0.32ms/10ms的PWM信号驱动传感器中的LED
		Voltage = ADCVal * 3.3 / 4096;
		dustVal = (Voltage + 1) * 1000 / 10;//*1000作用是将单位转换为ug/m3
//		if(ADCVal > 36.455)
//			dustVal = ((float)(ADCVal / 1024.0) - 0.0356) * 120000 * 0.035;
//		dustVal = 0.17 * ADCVal - 0.1;
//		dustVal = ADCVal;
//		return dustVal; //		mg/m3
		return dustVal;
}
 

 

放大后:

 

 

5.蜂鸣器报警模块

使用无源蜂鸣器模块

 

 

关键代码如下,其中有驱动蜂鸣器发出救护车或者电动车报警的声音:

 

#include "beep.h"
#include "lcd_driver.h"
#include "systick.h"
#include "public.h"
#include "gui.h"
#define TEMPALARMVALUEDOWN 		18//温度报警上下限
#define TEMPALARMVALUEUP		 	30

#define HUMIALARMVALUEDOWN 		10//湿度报警上下限
#define HUMIALARMVALUEUP		 	60

#define MQ4ALARMVALUEUP		 	1000//天然气浓度报警上限

#define DUSTALARMVALUEUP		 	400//粉尘浓度报警上限

#define   BEEPALARM 	GPIO_SetBits(GPIOB, GPIO_Pin_5)//置1
#define 	BEEPNOALARM GPIO_ResetBits(GPIOB, GPIO_Pin_5)//置0
int AlarmFlag[4] = {0, 0, 0, 0};
void Beep_GPIO_Init()//PB5
{
		GPIO_InitTypeDef GPIO_InitStructure;
	/****************************LED*******************************/
	/* GPIOC Periph clock enable */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	/* Configure PC2 and PC3 in output pushpull mode */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;	//PB5
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void Temp_Humi_Alarm(u8 temp, u8 humi)//当温度不在18-28度时,蜂鸣器报警;当湿度不在30%-60%时,蜂鸣器报警
 {
		if((temp < TEMPALARMVALUEDOWN) || (temp > TEMPALARMVALUEUP)){
				AlarmFlag[0] = 1;
				GUI_Show12ASCII(10,280,"temperature alarm!",YELLOW,BLACK);
				sound1();
//				BEEPALARM;
		}
		else{
				AlarmFlag[0] = 0;
				GUI_Show12ASCII(10,280,"               ",YELLOW,BLACK);
				BEEPNOALARM;
		}
		if((humi < HUMIALARMVALUEDOWN) || (humi > HUMIALARMVALUEUP)){
				AlarmFlag[1] = 1;
				GUI_Show12ASCII(10,300,"humidity alarm!",YELLOW,BLACK);
				sound2();
//				BEEPALARM;
		}
		else{
				AlarmFlag[1] = 0;
				GUI_Show12ASCII(10,300,"               ",YELLOW,BLACK);
				BEEPNOALARM;
		}
 }
 
  void MQ4_Alarm(u16 MQ4Value)
 {
		if(MQ4Value > MQ4ALARMVALUEUP){
			AlarmFlag[2] = 1;
			GUI_Show12ASCII(10,320,"MQ4 gas alarm!",YELLOW,BLACK);
			sound3();
		}
		else{
			AlarmFlag[2] = 0;
			GUI_Show12ASCII(10,320,"              ",YELLOW,BLACK);
//			TFT_ClearOneLine(260, BLACK);
			BEEPNOALARM;
		}
 }
 
void Dust_Alarm(u16 dustValue)//当浓度不在0-400内时,蜂鸣器报警
 {
		if(dustValue > DUSTALARMVALUEUP){
			AlarmFlag[3] = 1;
			GUI_Show12ASCII(10,340,"dust alarm!",YELLOW,BLACK);
			sound4();
		}
		else{
			AlarmFlag[3] = 0;
			GUI_Show12ASCII(10,340,"              ",YELLOW,BLACK);
			BEEPNOALARM;
		}
 }
 
/*******************************************************************************
* 函 数 名         : sound1
* 函数功能		   : 蜂鸣器报警函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void sound1()  //救护车报警
{
	u32 i=1000;
	while(i--)			   //产生一段时间的PWM波,使蜂鸣器发声
	{
		GPIO_SetBits(GPIOB,GPIO_Pin_5);		 //IO口输出高电平
		delay(i);
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);	  //IO口输出低电平
		delay(i--);
	}	
}

/*******************************************************************************
* 函 数 名         : sound2
* 函数功能		   : 蜂鸣器报警函数	  通过改变频率控制声音变化
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void sound2()  //电动车报警
{
	u32 i=2000;
	while(i--)					//产生一段时间的PWM波,使蜂鸣器发声
	{
		GPIO_SetBits(GPIOB,GPIO_Pin_5);	   //IO口输出高电平
		delay(i);
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);	//IO口输出低电平
		delay(i--);
	}	
}



/*******************************************************************************
* 函 数 名         : sound2
* 函数功能		   : 蜂鸣器报警函数	  通过改变频率控制声音变化
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void sound3()  //电动车报警
{
	u32 i=3000;
	while(i--)					//产生一段时间的PWM波,使蜂鸣器发声
	{
		GPIO_SetBits(GPIOB,GPIO_Pin_5);	   //IO口输出高电平
		delay(i);
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);	//IO口输出低电平
		delay(i--);
	}	
}


/*******************************************************************************
* 函 数 名         : sound2
* 函数功能		   : 蜂鸣器报警函数	  通过改变频率控制声音变化
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void sound4()  
{
	u32 i=4000;
	while(i--)					//产生一段时间的PWM波,使蜂鸣器发声
	{
		GPIO_SetBits(GPIOB,GPIO_Pin_5);	   //IO口输出高电平
		delay(i);
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);	//IO口输出低电平
		delay(i--);
	}	
}


 

6.系统图

 

 

代码

 

  • 54
    点赞
  • 424
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 44
    评论
好的,我会尽力回答你的问题。首先,你需要连接STM32F407芯片和DHT11传感器。在连接之前,请确保你已经在STM32CubeMX中配置了正确的引脚和时钟设置。接下来,你可以按照以下步骤来读取DHT11传感器数据: 1. 在FreeRTOS中创建一个任务来读取DHT11传感器数据。 2. 在任务中初始化GPIO引脚并将其设置为输出。 3. 然后,向DHT11传感器发送一个启动信号。 4. 等待20毫秒,然后将GPIO引脚设置为输入。 5. 接下来,读取传感器发送的40位数据,将其存储到一个变量中。 6. 最后,将读取数据进行解码,获取度和湿度值。 以下是一个简单的示例代码,可以帮助你开始: ```c void DHT11_Task(void *pvParameters) { uint8_t data[5]; // 存储读取数据 GPIO_InitTypeDef GPIO_InitStruct; // 初始化GPIO引脚 GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 向传感器发送启动信号 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); vTaskDelay(pdMS_TO_TICKS(20)); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); // 等待传感器响应 GPIO_InitStruct.Mode = GPIO_MODE_INPUT; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); vTaskDelay(pdMS_TO_TICKS(40)); // 读取传感器发送的数据 if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) { vTaskDelay(pdMS_TO_TICKS(80)); for (uint8_t i = 0; i < 5; i++) { uint8_t byte = 0; for (uint8_t j = 0; j < 8; j++) { while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET); vTaskDelay(pdMS_TO_TICKS(30)); if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) { byte |= (1 << (7 - j)); } while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET); } data[i] = byte; } // 解码并输出度和湿度值 uint8_t checksum = data[0] + data[1] + data[2] + data[3]; if (checksum == data[4]) { float temp = (float)data[2] + ((float)data[3] / 10.0f); float humi = (float)data[0] + ((float)data[1] / 10.0f); printf("Temperature: %.1f C, Humidity: %.1f%%\n", temp, humi); } } vTaskDelete(NULL); } ``` 请注意,以上代码仅供参考,并且可能需要进行一些调整才能适应你的特定应用程序。在将其用于生产环境之前,请务必进行测试和验证。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大师兄电子工作室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值