本帖最后由 会笑的星星 于 2019-12-30 13:20 编辑
从本质上来说,单片机的主要任务有两个,一个是识别输入,二个就是根据输入产生输出。对于信号输入而言,方波信号的检测无疑是经常会遇到的。这是因为其生成简单,容易检测,所以得到比较广泛的应用。一些通信协议比如曼彻斯特、1527编码等等就是方波信号。因此,对于方波信号的检测就显得比较重要。而方波信号的检测方法也有多种,这一篇**我就介绍其中的一种,我称之为计数法的方法。这种方法比较简单,但也能满足一些应用。
我以安防行业中用到的一种被称为安定宝协议为例。这个协议规定,在单片机发送信息到中心机时,中心机接收到信息后需要向单片机端发送一个1400HZ,持续时间750ms-1000ms的应答信号,而单片机端需要检测到持续时间至少400ms以上且为1400HZ信号才能视为中心机过来的有效应答。现在我们的问题就是如何检测这个持续时间至少400ms的1400HZ的方波信号(需要硬件电路把应答信号转换为方波信号),如下图所示。
这里,我介绍一种我称之为计数法的方法来解决这个问题。使用这种方法需要一个外部中断以及一个10ms的软件定时器。
外部中断采用上升沿或者下降沿中断都可以,用来对方波周期的计数。由于应答信号的周期是0.714ms(1400HZ),在10ms内能检测到的方波周期数量为10/0.714=14个,在400ms内能接收到的方波周期数量为400/0.714 = 560个,考虑10ms的误差,将400ms内接收到的方波周期数量要求降低到560-14 = 546,这意味着只要方波周期数量达到546个以上,就认为是有效应答音。基于上述分析,我们就可以实现代码了。 unsigned int sq_wave_count = 0, sq_wave_count_save = 0;
unsigned int sq_wave_count_timeout = 0;
//硬件GPIO中断
void gpio_interrupt( )
{
sq_wave_count++; //方波的计数
}
//10ms软件定时器
void app_clk_10ms()
{
if(sq_wave_count_timeout)
{
sq_wave_count_timeout --;
if(sq_wave_count_timeout == 0)
{
sq_wave_count = sq_wave_count_save = 0;
}
}
if(sq_wave_count != sq_wave_count_save)
{
sq_wave_count_timeout = 3;
if(sq_wave_count >= 546)
{
//接收到握手音,可以做后续任务
sq_wave_count = 0;
//30ms后,如果波形计数变量依然没有更新,则清除波形计数变量
sq_wave_count_timeout = 0;
}
sq_wave_count_save = sq_wave_count;
}
}
上述就是所谓的用计数法检测方波信号。这种方法只需要占用一个硬件资源外加一个公共的软件定时器就能完成检测任务,这在一些对准确度要求不高的场合下使用该方法还是不错的选择。对于信号检测准确度要求较高的情况下,可能还是需要使用其他方法,比如硬件定时器+外部中断,这个我后续会讲到。
|