当前位置: 代码迷 >> 综合 >> MQ2烟雾传感器模块——stm32f103
  详细解决方案

MQ2烟雾传感器模块——stm32f103

热度:81   发布时间:2023-11-24 02:43:13.0

MQ2烟雾传感器的使用

ADC的使用

电压与浓度的转换

定时器的使用

ADC的使用

利用mq2传感器对气体进行检测,无非就是利用传感器内部的电路以及材料在不同气体环境下有着不同的电阻值,通过对电阻电压的采集来检测相应气体浓度的变化。这时我们就可以利用ADC来对外部传感器的电压值进行采集,ADC呢就是将连续变量的模拟信号转换为离散的数字信号。ADC部分大家不了解可以去详细了解一下,大佬们写的都很好。
接下来是代码部分:
首先对io口进行配置,再对ADC的模式进行配置。

void Adc_Init()//初始化函数
{
     GPIO_InitTypeDef GPIO_Initstructre;     ADC_InitTypeDef ADC_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOARCC_APB2Periph_ADC1,ENABLE)//使能时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能io口GPIO_Initstructre.GPIO_Mode=GPIO_Mode_AIN; GPIO_Initstructre.GPIO_Pin=GPIO_Pin_1;GPIO_Initstructre.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_Initstructre);GPIO_SetBits(GPIOA,GPIO_Pin_1);RCC_ADCCLKConfig(RCC_PCLK2_Div6);//保证不超过14MADC_DeInit(ADC1);//复位ADC1ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//不使能连续扫描ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;//数据右对齐ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//软件触发ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;//独立模式ADC_InitStruct.ADC_NbrOfChannel = 1;ADC_InitStruct.ADC_ScanConvMode = DISABLE;//不使用扫描模式ADC_Init(ADC1,&ADC_InitStruct);ADC_Cmd(ADC1,ENABLE);//使能指定的ADC1ADC_ResetCalibration(ADC1);//使能复位校准 while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准结束ADC_StartCalibration(ADC1);//开启AD校准while(ADC_GetCalibrationStatus(ADC1));	 //等待校准结束
}

然后是ADC电压采集的相关函数

u16 Get_Adc(u8 ch)
{
    ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5);//ADC1,通道1,配置采集周期ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件复位while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//状态发生改变return ADC_GetConversionValue(ADC1);//返回值 }

利用上一个函数的返回值进一步进行数据计算

u16 Get_Adc_Average(u8 ch,u8 times)//两个入口参数,通道,取平均值的次数
{
    u32 temp_val=0;u8 t;for(t=0;t<times;t++){
    temp_val+=Get_Adc(ch);delay_ms(5);}return temp_val/times;}

然后是对气体PPM的转换

void MQ2_cumlate(float RS)
{
    R0 = RS / pow(CAL_PPM / 613.9f, 1 / -2.074f);
}float MQ2_GetPPM(void)
{
       u16 adcx;adcx=Get_Adc_Average(ADC_Channel_1,30);//ADC1,取30次的平均值float Vrl = 3.3f * adcx / 4096.f;//3.3v的参考电压,4096份Vrl = ( (float)( (int)( (Vrl+0.005)*100 ) ) )/100;float RS = (3.3f - Vrl) / Vrl * RL;if(times<6) // 获取系统执行时间,3s前进行校准,用到了定时器{
    R0 = RS / pow(CAL_PPM / 613.9f, 1 / -2.074f);//校准R0} float ppm = 613.9f * pow(RS/R0, -2.074f);return  ppm;
}

接下来是定时器部分的代码,这一部分主要是为了上方用到的校准

void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitSture;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//定时器3,时钟TIM_TimeBaseInitSture.TIM_Period = arr;//自动装载值TIM_TimeBaseInitSture.TIM_Prescaler = psc;//预分频系数TIM_TimeBaseInitSture.TIM_CounterMode = TIM_CounterMode_Up;//向上计数TIM_TimeBaseInitSture.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitSture);//定时器3TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//定时器3,更新中断,使能NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器TIM_Cmd(TIM3,ENABLE);
}void TIM3_IRQHandler(void)//中断函数,0.5秒中断一次
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET)//判断状态{
     TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//清除中断待处理位times++;}
}

最后我们可以通过串口助手,或者显示屏幕将数据进行显示,MQ系列的传感器主要就是ADC和相应的浓度转换。

电压值转化部分参考了以下博主的代码?

https://blog.csdn.net/qq_41422043/article/details/89138213?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7

若有错误,请大家指出。???

大家加我的扣扣,是简介那个,不是ID以qq开始5……的那个喔?