控制/MCU
这里接收机输出的是频率为50hz,周期为20ms的pwm波形,通过单片机外部中断口接收pwm信号,启用定时器/计数器对pwm高电平的持续时间进行计数。
Arduino中的pulseIn函数可以直截了当地读取pwm的值,可以参考其底层的实现方法。
文中关键部分:
微妙级,死循环读取引脚电平。因为不确定IO口接收到输入的pwm的瞬间是高电平还是低电平,所以While循环里先判断高电平,再判断低电平,再判断一次高电平,从而获得准确的占空比。
至于怎么在单片机上读取pwm呢?在网上查找一些资料后,我了解到可以通过外部中断+定时器来实现。最初我参考这个源码:
这个代码里面有一个问题就是,当单片机满足中断条件,就会不断跳到外部中断处理函数中,感觉这样太占用cpu资源,可以编写一个函数,在监听pwm值时开启外部中断,在获取到pwm值时关闭中断。具体方法如下:
STC15F104W单片机外部中断0(INT0)和外部中断1(INT1)触发有两种触发方式,上升沿或下降沿均可触发方式和仅下降沿触发方式。
TCON寄存器中的IT0/TCON.0和IT1/TCON.2决定了外部中断0和1是上升沿和下降沿均可触发还是仅下降沿触发。如果ITx = 0(x = 0,1),那么系统在INTx(x = 0,1)脚探测到上升沿或下降沿后均可产生外部中断。如果ITx = 1(x = 0,1),那么系统在INTx( x= 0,1)脚探测下降沿后才可产生外部中断。
程序中
[cpp] view plain copyIT0 = 0;
IT1 = 0;
所以上升沿或下降沿后均可产生外部中断,我设想是通过上升沿触发中断,
[cpp] view plain copyvoid pulseIn0(){
while(INT0==1);
EX0 = 1;
}
该段代码的意思是,如果接收到的pwm信号正处于高电平,先进入死循环,等pwm信号处于低电平再开启中断,那么下一个上升沿即可触发中断,触发中断后立即启用定时器0正好可以对高电平进行计数,到下一个下降沿时关闭中断。
试验效果如下:
INT1口接收到的pwm信号满足a1》1480&&a1《1520,led1熄灭。
而且用Arduino读取到的pwm值也在这个区间内,由此可见,用这种方法读取pwm的值精度是很高的,以后可以用STC15F104W单片机代替Arduino,通过pwm控制单片机的IO口。
全部0条评论
快来发表一下你的评论吧 !