PPM协议的输出实现
关于PPM输出的具体实现我们必然先知道其原理,本人是参考站内qiyuexin大佬的PPM 信号解析这篇文章。
基本要点
1.ppm每个通道所占用的时间并不固定
2.ppm的精度主要受制于时钟精度
3.对于一个通道数据每次开头都有0.5ms的固定低电平,之后跟着0.5ms的固定的高电平,之后是0 - 1ms的数据长度。也就是说每个数据之间没有固定的时间间隔,上一个数据结束后就是下一个通道的数据。
4.ppm一般10个控制通道,每帧的长度是固定的20ms。
具体实现
通过定时器产生一个10us的中断事件,在中断内进行计数,计数到2000即20ms代表已经完成1个数据帧。
pwm_count 0 -> 2000时表示计数了一个数据帧
这里笔者犹豫了一段时间,最后决定既然每个通道都有固定的0.5ms的固定低电平,和0.5ms的固定的高电平,那就直接把他做成一个固定的片段,在输出时候先进行此片段,之后紧跟着就是数据便可。于是我们创建了一个名为mod的变量,mod = 0时执行通道开头的0.ms低和0.5ms高,mod = 1时是数据。
对于数据,因为本身就在一个循环之中,只要一直if(count <= PPM_out[1])就可以,输出完一个通道之后cnt++,下一次循环输出的就是就是PPM_out[2]的数值了。
`
if (mod == 0)//开始信号
{
if(count <= 50) //0.5m 低电平表示通道起始信号
{
PPM_out_pin_reset;
}
else if(count > 50 && count <= 100) //0.5m 高电平数据起始信号
{
PPM_out_pin_set;
}
else
{
count = 0;
mod = 1;//进入数据时间
}
}else if (mod == 1)
{
if(count <= PPM_out[cnt]) //0.5m 低电平表示通道起始信号
{
PPM_out_pin_set;//数据
}
else
{
count = 0;
mod = 0;//进入数据时间
cnt ++;
if (cnt > 9)
{
mod = 2;
}
}
}
`
之后一直循环到数据都输出完成时,mod = 2来保持之后的高电平(引导或称结束脉冲),在循环到pwm_count = 2000,一帧完成之后对所有的计数器进行清零。
`
if(pwm_count==2000)//对计数进行复位
{
pwm_count = 0;
cnt = 0;
mod = 0;
}
`
至此已经能输出正确的pwm信号了。
代码
点击查看代码
//2000 -> 20ms
//200 -> 2ms
//100 -> 1ms
//50 -> 0.5ms
//1 -> 0.01ms
u16 count=0;
u16 pwm_count=0; //总计数 周期20ms,10us进次
unsigned char mod = 0;
unsigned char cnt = 0;
void PPM_loop(void)//1us进来1次
{
pwm_count++;
count++;
if (mod == 0)//开始信号
{
if(count <= 50) //0.5m 低电平表示通道起始信号
{
PPM_out_pin_reset;
}
else if(count > 50 && count <= 100) //0.5m 高电平数据起始信号
{
PPM_out_pin_set;
}
else
{
count = 0;
mod = 1;//进入数据时间
}
}else if (mod == 1)
{
if(count <= PPM_out[cnt]) //0.5m 低电平表示通道起始信号
{
PPM_out_pin_set;//数据
}
else
{
count = 0;
mod = 0;//进入数据时间
cnt ++;
if (cnt > 9)
{
mod = 2;
}
}
}
if(pwm_count==2000)//对计数进行复位
{
pwm_count = 0;
cnt = 0;
mod = 0;
}
}