MCU裸机:一、315/433MHz/IR射频解码开发

MCU裸机:一、315/433MHz/IR射频解码开发

Frist


MCU裸机开发大多基于其寄存器和一些外设信号处理的简易逻辑

对于刚入行的我希望在博客上进行一些微处理器的开发,并将所学知识和技术以及方案进行记录总结,此篇内容将会介绍一些遥控无线模块如IR、RF433、RF315等信号基本处理。


一、315/433MHz信号数据帧解读

此例中使用WL531系列芯片作为315/433MHz的转码方案。

  1. 硬件电路如下:
    在这里插入图片描述
    在这里插入图片描述
  2. 逻辑分析仪抓取的波形如下:
    在这里插入图片描述
    抓取 初始波形,可以看见是有很多乱序的杂波。(所以需要经过一定的处理)

在这里插入图片描述提取完整两帧波形
在这里插入图片描述
放大分析得出转码波形的每一个数据bit都由一个周期的方波组成,频率为617.88Hz,定义抓取数据帧的每一个周期方波在占空比为25%(高电平时长为425us左右)时该bit=0;占空比为75%(高电平时长为1.63984ms左右)为bit=1
红外:(NEC、RC-5协议)后续更新。

二、程序解码功能实现

1.首先构造一个315/433MHz的解码结构体(方便后续的移植)

将所需要的形参及硬件接口层进行声明和定义:

#define IR_Pin RC1 //硬件接口
typedef struct IRDecode  //解码逻辑层
{
    unsigned char LeadCode1;    //引导码(用于记忆和学习部分)
    unsigned char LeadCode2;
    unsigned char LeadCode3;
    unsigned char LeadCode4;
    unsigned char IRCode1Control;  //控制码(处理后最终编码)
    unsigned char IRCode2Control;
    unsigned char IRCode3Control;
    unsigned char IRCode4Control;
    unsigned char IRCode1Data;     //传递码(源数据帧流)
    unsigned char IRCode2Data;
    unsigned char IRCode3Data;
    unsigned char IRCode4Data;
    unsigned char IRCode1;  //采集码(原始数据解码运用)
    unsigned char IRCode2;
    unsigned char IRCode3;
    unsigned char IRCode4;
    unsigned char IRWaveCount; //连续发波计时
    unsigned char IRHighLevelCount;
    unsigned char IRLowLevelCount;  
    unsigned char IRHighLevelFlag : 1;
    unsigned char IRLowLevelFlag : 1;
    unsigned char IRCodeLength  : 6;
    unsigned char IRLearnableFlag : 1;
}IRDecode;
//应用层
typedef struct IRWorkData{  //数据帧事件处理
    unsigned char IRKeyState1 :1;
    unsigned char IRKeyState2 :1;
    unsigned char IRKeyState3 :1;
    unsigned char IRKeyState4 :2;
//    unsigned char IRKey1Transfer :1;
    unsigned char IRKey2Transfer :1;
    unsigned char IRKey3Transfer :1;
    unsigned char IRKey4Transfer :1;
    unsigned char IRKey4LongPressFlag :1;
    unsigned short int IRLongKey4Count;
}IRWorkData;
IRDecode IRDriver;
IRWorkData IRKeyHandle;

2.解码逻辑函数编写

利用125us定时器对数据入口的高低电平进行计数,计算出高低电平的时间转化为bit缓存起来,后续输出完整数据帧进行下一步工作:

//可更改或优化其中计数的阈值应用在其他协议上
//码值获取(循环调用us级)
void ScanGetIRCode(void){
    
    if(IR_Pin){
        IRDriver.IRHighLevelFlag=1;
        
        if(IRDriver.IRHighLevelCount<=250) IRDriver.IRHighLevelCount++;
        
//        //低电平时长超时滤波*16us=2ms,重新读值
//        if(IRDriver.IRHighLevelCount>=16){
//            IRDriver.IRCodeLength=0;
//        } 
          
        if(IRDriver.IRLowLevelFlag){  //上升沿
            IRDriver.IRLowLevelFlag=0;
            IRDriver.IRLowLevelCount=0;
            IRDriver.IRHighLevelCount=0;
        }
    }
    else{
        IRDriver.IRLowLevelFlag=1;
       
        if(IRDriver.IRHighLevelFlag){  //下降沿
            //高电平采样编码,下降沿处理
            if((IRDriver.IRHighLevelCount>1)&&(IRDriver.IRHighLevelCount<=11)){
                //码值1获取
                if(IRDriver.IRCodeLength<8){
                   IRDriver.IRCode1=IRDriver.IRCode1>>1;
                   if((IRDriver.IRHighLevelCount>=8)&&(IRDriver.IRHighLevelCount<=11)){
                       IRDriver.IRCode1|=0x80;
                   } 
                   else{
                       IRDriver.IRCode1&=0x7F;
                   }
                }
                //码值2获取
                else if(IRDriver.IRCodeLength<16){
                   IRDriver.IRCode2=IRDriver.IRCode2>>1;
                   if((IRDriver.IRHighLevelCount>=8)&&(IRDriver.IRHighLevelCount<=11)){
                       IRDriver.IRCode2|=0x80;
                   } 
                   else{
                       IRDriver.IRCode2&=0x7F;
                   }
                }
                //码值3获取
                else if(IRDriver.IRCodeLength<24){
                   IRDriver.IRCode3=IRDriver.IRCode3>>1;
                   if((IRDriver.IRHighLevelCount>=8)&&(IRDriver.IRHighLevelCount<=11)){
                       IRDriver.IRCode3|=0x80;
                   } 
                   else{
                       IRDriver.IRCode3&=0x7F;
                   }
                }
                //码值4获取
                else{
                   IRDriver.IRCode4=IRDriver.IRCode4>>1;
                   if((IRDriver.IRHighLevelCount>=8)&&(IRDriver.IRHighLevelCount<=11)){
                       IRDriver.IRCode4|=0x80;
                   } 
                   else{
                       IRDriver.IRCode4&=0x7F;
                   }
                }
                IRDriver.IRCodeLength++;
                //只处理32位数据
                if(IRDriver.IRCodeLength>=32){
                    IRDriver.IRCodeLength=0;
                    if((IRDriver.IRCode1==IRDriver.LeadCode1)){  //原始码
                        IRDriver.IRCode1Data=IRDriver.IRCode1;
                        IRDriver.IRCode2Data=IRDriver.IRCode2;
                        IRDriver.IRCode3Data=IRDriver.IRCode3;
                        IRDriver.IRCode4Data=IRDriver.IRCode4;
                        IRDriver.IRWaveCount=0;  //数据帧结束计时
                    }
                    //接收数据帧清零
                    IRDriver.IRCode1=0xFF;  //防止误判
                    IRDriver.IRCode2=0;
                    IRDriver.IRCode3=0;
                    IRDriver.IRCode4=0;
                }
            }
            else{
                IRDriver.IRCodeLength=0;  //高电平杂波滤除
            }
            IRDriver.IRHighLevelFlag=0;
            IRDriver.IRLowLevelCount=0;
            IRDriver.IRHighLevelCount=0;            
        }
        
        if(IRDriver.IRLowLevelCount<=250) IRDriver.IRLowLevelCount++;
         
        //低电平时长超时滤波*16us=2ms,重新读值
        if(IRDriver.IRLowLevelCount>=12){
            IRDriver.IRCodeLength=0;
        }
    }
}

3.应用层书写(这一层是看应用场景需求编写)

通过对数据帧间隔信号的获取,可以处理数据帧为波包的一种标志位跟随,即有数据帧发送到MCU时缓存可见有数据,反之缓存中的数据清零。(以追求实际操作信号的同步):

//数据帧及连续发波处理(循环调用ms级)
void IRContinnuousWave(void){
    
    if(IRDriver.IRWaveCount<=254) IRDriver.IRWaveCount++;
    if(IRDriver.IRWaveCount>=36&&IRDriver.IRCode4Data!=0){ //72ms完整数据帧间隔时间
       //原始码数据帧清零
       IRDriver.IRCode1Data=0;
       IRDriver.IRCode2Data=0;
       IRDriver.IRCode3Data=0;
       IRDriver.IRCode4Data=0;
    }
}

总结

上述内容可以拓展到一些内似协议的解码和编码上面去,但是程序暂时并未进行面向对象的封装以及队列的优化,暴露了C/C++的编程功底不行,需要多练多学。

)EV1527中断法解码 ① 设定定时器中断时间,设定为 80us,80us 进入中断进行解码。具体中断时间多少由自己 软件设定,但是中断时间不能太大。 ② 设定同步码解码范围,同步码定为 5.6ms - 16ms。进入中断判断到低电平,低电平判断 直累加 Count_Lead++,累积低电平的采集时间,判断到高电平,就判断此时 Count_Lead 的值是否在 70 跟 200之间。(备注:5.6ms/80us=70 16ms/80us=200)。 ③ 引导头通过进入数据判断,刚开始是数据高电平,累积高电平的时间 Count_Data_Hi++, 当判断到低电平时候,判断 Count_Data_Hi 是否在 80us -2.4ms 之间。这里还没进行数据 0 跟 1 的区分,先把 Count_Data_Hi 的值保存在 Hi_Cnt 里面。 (备注:80us/80us=1 2.4ms/80us=30)。 ④ 高电平判断通过,开始判断低电平,累积低电平的时间 Count_Data_lo++,当判断到高电 平时候,判断 Count_Data_Lo 是否在 80us -2.4ms 之间。这里还没进行数据 0 跟 1 的区分, 先把 Count_Data_Lo 的值保存在 Lo_Cnt 里面。 (备注:80us/80us=1 2.4ms/80us=30)。 ⑤ 对 0 跟 1 进行区分,把 24bit 数据整理成三个 byte,存在数组 RfData[0],RfData[1], RfData[2]数组里面。 ⑥ 进行相应功能码的操作。 具体解码方法参考例子程序,因为不同的震荡电阻,1527 出来的编码长度不同,例子 程序是参考 1 lck=100us 波形来做的。具体时间参数可以根据自己的 1527 发射实际长度来 编写。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值