用ADuC7026解码遥控信号(原创)
0赞
发表于 10/20/2011 2:01:35 PM
阅读(2241)
遥控器型号:Spektrum DSx9
在每个传输周期共2个帧:Frame1和Frame2
这两个帧中包含了9个通道的序号及对应控制量。
Frame1: 00 00 + 8 byte data+ FF FF FF FF FF FF 共16 byte
Frame2: 00 00 + 10byte data+ FF FF FF FF 共16byte
传输时最小帧间隔7ms。
最大字节间隔310us,若传输时间隔大于此值则认为超时。
Frame1的起始处与Frame2的起始处时间间隔为11ms。
void IRQ_Handler() __irq //普通中断服务程序,执行周期10us
{
MyIRQstate = IRQSTA;
if((MyIRQstate & 0x10) != 0)
{
count++;
PPMCounter++;
if(SpektrumTimer) SpektrumTimer--;
if((MyIRQstate & 0x4000) != 0)
{
if((COMIID0 & 0x04) != 0)
{
c = COMRX;
Spektrum(c);
}
}
}
void Spektrum(unsigned char c)
{
static unsigned char Sync=0, FrameCnt=0, ByteHigh=0, ReSync=1, Frame2=0;
unsigned int Channel, index = 0;
int bCheckDelay;
#define MIN_FRAMEGAP 350 // 7ms 最小帧间隔
#define MAX_BYTEGAP 16 // 310us 最大字节间隔
if(ReSync == 1) //重新同步过程,首次执行是必走此处,若超时则也须重新同步
{
// 等待新的帧到来
ReSync = 0;
SpektrumTimer = MIN_FRAMEGAP; //定时变量设置为最小帧间隔
FrameCnt = 0; //统计收到的字节数而不是帧数
Sync = 0;
ByteHigh = 0; //用于存储数据高字节
}
else
{
if(!SpektrumTimer) bCheckDelay = 1; else bCheckDelay = 0; //若bCheckDelay,则表示未超时
if(Sync == 0)
{
if(bCheckDelay)
{
Sync = 1; //发现新的帧
FrameCnt++;
SpektrumTimer = MAX_BYTEGAP;//定时变量设置为最大字节时间间隔
}
else
{
Sync = 0; //若走此处则相当于什么也没做
FrameCnt = 0;
SpektrumTimer = MIN_FRAMEGAP;
ByteHigh = 0;
}
}
else if((Sync == 1) && !bCheckDelay)//已同步且在规定的超时时间内发现新的字节
{
Sync = 2;
FrameCnt++;
SpektrumTimer = MAX_BYTEGAP;
}
else if((Sync == 2) && !bCheckDelay)//又发现新字节,前两次发现的是开头 00 00 ,是不需要的数据
{
SpektrumTimer = MAX_BYTEGAP;
ByteHigh = c; //这是紧接在 00 00之后的数据,包含所需信息,称为高字节,要与下个字节组合才有意义
if(FrameCnt ==2)
{
if(ByteHigh & 0x80) //若最高位为1则此帧为Frame1,否则为Frame2;两个帧内数据不同 故需判别
Frame2 = 0;
else
Frame2 = 1;
}
Sync = 3;
FrameCnt++;
}
else if((Sync == 3) && !bCheckDelay)
{
Sync = 2;
FrameCnt++;
SpektrumTimer = MAX_BYTEGAP;
Channel = ((unsigned int)ByteHigh << 8) | c; //高低字节合成
signal = Channel & 0x7ff; //提取控制量
index = (ByteHigh >> 3) & 0x0f; //提取通道序号
if((FrameCnt < 11) && !Frame2) //对于Frame1,其有效信息占10字节,超过此范围的信息无用
{
PPM_in[index] = signal;
}
if((FrameCnt < 13) && Frame2) //Frame2的有效信息共12字节,余下丢弃
{
PPM_in[index] = signal;
}
}
else
{ //对于超时的处理
ReSync = 1;
FrameCnt = 0;
Frame2 = 0;
SpektrumTimer = MIN_FRAMEGAP;
}
if(FrameCnt >= 16) //每帧长度为16字节,超过此值则等待下一帧到来
{
FrameCnt = 0;
Frame2 = 0;
Sync = 0;
SpektrumTimer = MIN_FRAMEGAP;
}
}
}
最终9通道的控制量存储在数组PPM_in[index]中
