背景
刚好有项目使用GDS06这款传感器,这里简单做个记录。
GDS06接口如下,这里支持串口和PWM的输出到MCU,由于项目采用STM8S003F3P6,资源极其有限。
所以硬件设计的时候,就考虑采用PWM的接口方式,这样只是消耗掉STM8S003F3P6一个管脚而已。
原理图
如下图所示CN7连接粉尘传感器,PA3对应GDS06的对应管脚PWM
PWM 输出
传感器通过 PWM 口(第 4 脚)输出 PWM 信号,该 PWM 周期为 1 秒,按低电平的宽度计算灰尘浓度值。引脚输出的脉冲宽度对应粉尘浓度的平均值。
低脉冲时间与粉尘浓度的关系:1ms = 1ug/m3
例如低电平宽度为 100 ms,则对应灰尘浓度为 100 ug/m3。 浓度输出范围为 1~999 ug/m3。 该浓度值内部进行了软件滤波处理,跳动幅度相对较小。
PWM 通信
传感器通过 PWM 口输出 PWM 信号,按低电平宽度计算灰尘浓度值。
PWM 输出周期: 1 秒
测量值输出范围: 1~999 ug/m³
低电平与测量值对应关系:测量值(ug/m³)= 低电平时间(毫秒)
软件设计
STM8S003F3P6使用PA3管脚,采用定时器2捕获模式,配置如下图所示
u16 gds06_value;
u8 gds06_Sta;
//红外遥控初始化
//设置IO以及TIM2_CH1的输入捕获
void GDS06_Init(void)
{
/* Set PA.3 TIM2_CH3 pin */
///GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_IN_PU_NO_IT);
GPIO_DeInit(GPIOA);//恢复指定端口
GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_IN_FL_NO_IT);//设置PA3为浮空输入无中断
TIM2_DeInit();
/* Time base configuration */
//TIM2_TimeBaseInit(TIM2_PRESCALER_2048, 65535);
//TIM2_TimeBaseInit(TIM2_PRESCALER_1, 999);//2Mhz
///TIM2_TimeBaseInit(TIM2_PRESCALER_1, 1999);//1Mhz
//TIM2_TimeBaseInit(TIM2_PRESCALER_16, 10000 - 1);//1Mhz
TIM2_TimeBaseInit(TIM2_PRESCALER_16384, 2000 - 1);//976 hz
TIM2_ARRPreloadConfig(ENABLE);
//TIM2_ClearFlag(TIM2_FLAG_UPDATE);//清除更新标志
TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);//允许更新/溢出中断
TIM2_Cmd(ENABLE);//开启定时器
enableInterrupts(); //开启中断
/* Prescaler configuration */
///TIM2_PrescalerConfig(TIM2_PRESCALER_2048, TIM2_PSCRELOADMODE_IMMEDIATE);
//TIM2_ICInit(TIM2_CHANNEL_3, TIM2_ICPOLARITY_RISING, TIM2_ICSELECTION_DIRECTTI, TIM2_ICPSC_DIV1, 3);
TIM2_ICInit(TIM2_CHANNEL_3, TIM2_ICPOLARITY_FALLING, TIM2_ICSELECTION_DIRECTTI, TIM2_ICPSC_DIV1, 0);
TIM2_ITConfig(TIM2_IT_CC3 , ENABLE);//中断配置与使能函数
TIM2_ClearITPendingBit(TIM2_IT_CC3);
TIM2_ClearFlag(TIM2_FLAG_CC3);
//TIM2_CCxCmd(TIM2_CHANNEL_2, ENABLE);//输入捕获/比较输出使能
}
定时器2的中断如下
主要是探测出来低电平的长度
//定时器2输入捕获中断服务程序
INTERRUPT_HANDLER(TIM2_CAP_COM_IRQHandler, 14)
{
/* In order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction.
*/
BitStatus bs;
bs = GPIO_ReadInputPin(GPIOA, GPIO_PIN_3);//读PA3的输入电平状态
//if(TIM2_GetITStatus(TIM2_IT_CC3)==SET) //处理捕获(CC1IE)中断
if(bs)//上升沿捕获
{
gds06_value = TIM2_GetCounter();//读取CCR2也可以清CC2IF捕获标志位
TIM2_OC3PolarityConfig(TIM2_OCPOLARITY_LOW); //CC1P=0 设置为上升沿捕获
//gds06_Sta |= 0X10; //标记上升沿已经被捕获
}else //下降沿捕获
{
TIM2_OC3PolarityConfig(TIM2_OCPOLARITY_HIGH); //CC1P=1 设置为下降沿捕获
TIM2_SetCounter(0x0000); //清空定时器值
}
TIM2_ClearITPendingBit(TIM2_IT_CC3); //清除中断标志位
}