一、创作思路
二维振动传感器工作原理类似于一个开关,当磁珠滚向左边时输出高电平,滚向右边时输出低电平(也可能反过来,看采集结果而定)。由于工作环境会存在一些微小振动,可能会出现高低电平的不断输出,影响采样结果,所以对采样结果做一个滤波处理。
二、代码编写
#include "user_shock.h"
#define SHOCK_SENSITIVITY 15 //150ms,输出电平的时间持续时间大于150ms,认定状态稳定。
unsigned char old_state = 0;//定义一个变量存放老的状态,用来对比。
unsigned char new_state = 0;//定义一个变量存放新采集到的状态,用来与老状态对比。
unsigned int shock_high_cnt = 0;//低电平的持续时间
unsigned int shock_low_cnt = 0;//高电平的持续时间
void shock_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_Ctrl = GPIO_Control_DIG;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;//不进行上下拉,电平取决于外部电压
GPIO_Init(GPIO_PORT12, &GPIO_InitStruct);
old_state = GPIO_ReadInputDataBit(GPIO_PORT12,GPIO_Pin_0);//读取一个状态作为老状态。
new_state = old_state;//将新老状态同步,作为一个判断标准。
}
//10ms扫描一次
//返回稳定状态
unsigned char shock_scan(void)
{
unsigned char state = 0;
if(GPIO_ReadInputDataBit(GPIO_PORT12,GPIO_Pin_0) == 0)//获取状态
{
//滤波处理
if(shock_low_cnt < SHOCK_SENSITIVITY)
{
shock_low_cnt++;
}
else
{
shock_low_cnt = 3000;//表示稳定
shock_high_cnt = 0;
}
}
else //获取状态
{
//滤波处理
if(shock_high_cnt < SHOCK_SENSITIVITY) //高电平的时间超过了预设值,认定稳定。
{
shock_high_cnt++;//高电平的时间自增
}
else
{
shock_high_cnt = 3000;//表示稳定
shock_low_cnt = 0;
}
}
//判断滤波后的状态
if(shock_high_cnt >= SHOCK_SENSITIVITY) state = 1;
if(shock_low_cnt >= SHOCK_SENSITIVITY) state = 0;
//输出结果
return state;
}
//10ms获取一次传感器状态
unsigned char shock_state(void)
{
unsigned char state = 0;
new_state = shock_scan();//获取滤波后的状态
if(new_state != old_state) state = 1;//如果状态与初状态不一样,表示设备移动。
else state = 0;//设备没动
return state;//输出判断结果。
}
三、程序说明
传感器函数初始化后,要将shock_state()函数放到10ms轮询一次的代码中,以确保稳定。shock_state()的输出结果是状态有没有进行反转。
优势:过滤掉一些短时间的振动,避免误报。