背景
刚好有项目使用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);//1MhzTIM2_TimeBaseInit(TIM2_PRESCALER_16384, 2000 - 1);//976 hzTIM2_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); //清除中断标志位 }