Frist
- MCU裸机:一、315/433MHz/IR射频解码开发
- MCU裸机开发大多基于其寄存器和一些外设信号处理的简易逻辑
- 一、315/433MHz信号数据帧解读
- 二、程序解码功能实现
- 1.首先构造一个315/433MHz的解码结构体(方便后续的移植)
- 2.解码逻辑函数编写
- 3.应用层书写(这一层是看应用场景需求编写)
- 总结
MCU裸机开发大多基于其寄存器和一些外设信号处理的简易逻辑
对于刚入行的我希望在博客上进行一些微处理器的开发,并将所学知识和技术以及方案进行记录总结,此篇内容将会介绍一些遥控无线模块如IR、RF433、RF315等信号基本处理。
一、315/433MHz信号数据帧解读
此例中使用WL531系列芯片作为315/433MHz的转码方案。
- 硬件电路如下:
- 逻辑分析仪抓取的波形如下:
抓取 初始波形,可以看见是有很多乱序的杂波。(所以需要经过一定的处理)
提取完整两帧波形
放大分析得出转码波形的每一个数据bit都由一个周期的方波组成,频率为617.88Hz,定义抓取数据帧的每一个周期方波在占空比为25%(高电平时长为425us左右)时该bit=0;占空比为75%(高电平时长为1.63984ms左右)为bit=1。
红外:(NEC、RC-5协议)后续更新。
将所需要的形参及硬件接口层进行声明和定义:
#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++的编程功底不行,需要多练多学。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)