51单片机解码PPM波
本帖最后由 济南电子爱好者 于 2012-7-7 21:50 编辑好久没有来论坛了,这段时间一直在学习USB方面的应用和开发。制作四轴被耽搁了下来。今天利用空余的时间看了下PMM波相关的程序,结合论坛里的程序。利用51单片机成功解码PPM波。
这是我是CY7C68013ADIY的逻辑分析仪采集的冠丽四通控的PPM波,预留两通没有使用。
先说说PPM波,从图上可以看出周期为20ms,冠丽控实际是6通控,但预留两通没有使用。通道的高电平区间为0.765~1.6ms低电平时间为0.395ms
引导波形的高电平 时间为10.165ms。
我的单片机是 11.0592MHZ 这样算的话,显示的值 应该是706到1491之间,中立位为 1100正好和理论值相符。
这里在提点单片机相关的知识,51单片机是低电平触 发中断,我这里用的是while(int0==0)来等待高电平 的到来。不知道这样做是否合理,不过实践看来还是可以的。
这里我发程序打包发上来,大家要顶啊。 好东西必须顶! 同分享一个stm32的解码程序,自己写的,但是目前还之能解一个通道,大家可以一起完善……
中断配置
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel; //设TIM2输入捕获中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //配置优先级组
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 10;
TIM配置(用的是TIM2)
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_ICInitTypeDefTIM_ICInitStruct;
TIM_TimeBaseInitStruct.TIM_Period = 0xffff; // 计数上限为最大
TIM_TimeBaseInitStruct.TIM_Prescaler = 72; // 计数器频率
TIM_TimeBaseInitStruct.TIM_ClockDivision = 0; // 不分割
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct ); // 初始化TIM2的时基单元
TIM_ITConfig(TIM2,TIM_IT_Update, DISABLE );
TIM_ClearFlag(TIM2,TIM_FLAG_Update);
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;// 选择通道1
TIM_ICInitStruct.TIM_ICPolarity= TIM_ICPolarity_Rising; // 上升沿触发(根据示波器实验观察结果调整)
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; // 每次检测到捕获输入就触发一次捕获
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; // 通道方向选择
TIM_ICInitStruct.TIM_ICFilter = 0x5;
TIM_ICInit(TIM2,&TIM_ICInitStruct );
TIM_ITConfig(TIM2, TIM_IT_CC1, DISABLE );
TIM_ClearFlag(TIM2,TIM_FLAG_CC1 );
中断函数
void TIM2_IRQHandler(void)
{
TIM_ICInitTypeDefTIM_ICInitStruct;
if(j==0)
{
j=1;
TIM2->CNT = 0x00;
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;// 选择通道4
TIM_ICInitStruct.TIM_ICPolarity= TIM_ICPolarity_Falling; // 下降沿触发(根据示波器实验观察结果调整)
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; // 每次检测到捕获输入就触发一次捕获
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; // 通道方向选择
TIM_ICInitStruct.TIM_ICFilter = 0x5;
TIM_ICInit(TIM2,&TIM_ICInitStruct );
TIM_ClearFlag(TIM2,TIM_FLAG_CC1 );
TIM_ITConfig(TIM2, TIM_IT_CC1,ENABLE);
}
else
{
j=0;
buffer = TIM2->CNT;
USART_SendData(USART1, buffer);
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;// 选择通道4
TIM_ICInitStruct.TIM_ICPolarity= TIM_ICPolarity_Rising; // 上升沿触发(根据示波器实验观察结果调整)
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; // 每次检测到捕获输入就触发一次捕获
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; // 通道方向选择
TIM_ICInitStruct.TIM_ICFilter = 0x5;
TIM_ICInit(TIM2,&TIM_ICInitStruct );
TIM_ClearFlag(TIM2,TIM_FLAG_CC1 );
TIM_ITConfig(TIM2, TIM_IT_CC1,ENABLE);
}
}
在主函数中: TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
TIM_Cmd(TIM2,ENABLE);
学习!顶………… 顶啊 都是牛人 刚开始学习这方面的东西,如获至宝啊 PPM信号从哪里引出的
00superman00 发表于 2013-2-4 20:14 static/image/common/back.gif
PPM信号从哪里引出的
PPM是直接从摇控器中引出来的 好啊 顶 顶,好东西{:tongue:}
fengyiyu1006 发表于 2012-10-16 22:54 static/image/common/back.gif
同分享一个stm32的解码程序,自己写的,但是目前还之能解一个通道,大家可以一起完善……
中断配置
额...有这么复杂么.... PPM能解出一个通道,其他通道顺理成章都可以解出来啊 wangjt1988 发表于 2013-3-17 12:20 static/image/common/back.gif
额...有这么复杂么.... PPM能解出一个通道,其他通道顺理成章都可以解出来啊 ...
这是去年写的代码,当时刚接触ppm解码,现在可以读取所有通道的了
方法还是这种,中断和定时器 wangjt1988 发表于 2013-3-17 12:20 static/image/common/back.gif
额...有这么复杂么.... PPM能解出一个通道,其他通道顺理成章都可以解出来啊 ...
void ppm_isr()
{
if (ppm_step == 0)
{
TIM1->CCER &= 0XFFFD; //change to raising
TIM1->CNT = 0;
TIM1->SR &= 0XFFFC; //clear flag
ppm_step = 1;
}
else if (ppm_step == 1)
{
TIM1->CCER |= 0X02; //change to falling
buffer = TIM1->CNT;
TIM1->SR &= 0XFFFC; //clear flag
if (buffer < 2500)
{
ppm_step = 0;
}
else
{
TIM1->CNT = 0;
ppm_step = 2;
rt_mb_send(&mb_ppm, (rt_uint32_t)&start_ppm); //发送邮箱,告诉线程已经可以开始处理了
}
}
else if (ppm_step == 2)
{
TIM1->CCER &= 0XFFFD; //change to raising
channel = TIM1->CNT;
TIM1->SR &= 0XFFFC; //clear flag
ppm_step = 3;
ppm_c++;
if(ppm_c == 6)
{
ppm_c = 0;
ppm_step = 0;
goto end;
}
}
else if (ppm_step == 3)
{
TIM1->CCER |= 0X02; //change to falling
TIM1->CNT = 0;
TIM1->SR &= 0XFFFC; //clear flag
ppm_step = 2;
}
end:__nop();
} fengyiyu1006 发表于 2013-3-17 12:49 static/image/common/back.gif
void ppm_isr()
{
if (ppm_step == 0)
额...都上系统了,厉害,不过ppm采集只用低电平到高电平的边沿就行了,不用在中断里面重新设置边沿(我的天地飞9遥控是这样,直接从模拟器口引出的ppm) 询问下那个遥控的PPM波怎么引导单片机中啊? 艾儿海绵 发表于 2013-3-18 15:43 static/image/common/back.gif
询问下那个遥控的PPM波怎么引导单片机中啊?
就是具体接单片机的哪个引脚啊? wangjt1988 发表于 2013-3-17 14:36 static/image/common/back.gif
额...都上系统了,厉害,不过ppm采集只用低电平到高电平的边沿就行了,不用在中断里面重新设置边沿(我的天地 ...
由于我没找到接收机的模拟ppm口在哪,所以用或门把所有电平加在一起了
只采集上升沿只能获取周期,怎么判断高电平时间?而且我需要先找到信号头 艾儿海绵 发表于 2013-3-18 15:52 static/image/common/back.gif
就是具体接单片机的哪个引脚啊?
你用哪个定时器哪个通道,就把信号接入哪个引脚,这个没有限制的 谢谢啦{:lol:}{:lol:}{:lol:}{:lol:}{:lol:} {:handshake:}{:handshake:}{:handshake:} 正在研究这个,顶一个 谢谢 楼主分享 顶一个,正在学习 楼主太棒了, 似乎3楼的程序不对 ,在中断服务函数 怎么能一直那么替换呢!我看别的书上写的都是定时器自动做了计时功能,你只要调用函数把那个计时器里面的数值拿出来 就可以了不用那么麻烦的! {:shocked:}此 PPM 是啥意思{:sweat:} 很有用,做迷你四轴很实用 学习了~~~{:smile:} mark。。。 我要编码,愁死。。。
页:
[1]