本帖最后由 119163wzj 于 2020-8-5 16:28 编辑
315/433无线模块解码
上图是接收模块接收到的发送模块按键一次发来的信息波形,可以分为5个阶段来分析,分别是:1、开始无接收信号,输出的是杂波;2、引导码;3、键码;4、相同连续的引导码和键码,如果长按发送会一直输出这样的波形;5、松开发送键,接收输出一个比较明显的结束码; 接收模块在无信号状态下接收引脚是不断输出杂波,在接到信号时,才会输出信息码,所以写程序的难点在解码。 网上找不到比较好的方案,这里是有类似的讨论:http://www.amobbs.com/thread-959411-1-1.html 像在程序中延时解码的方式,如果其他程序需要快速的循环执行的话,会有影响,再有就是移植性不高。 我们可以设定一个较快的定时中断(下面设定24us),然后在中调用接收解码函数,每次中断只判断相应的标志,不会造成中断执行时间过长的问题。 比如其中一对收发模块,同步码为10ms低电平,之后是25位数据,只取24位3个字节,"1"是1.1ms高+0.2ms低, "0"是0.45高+0.9低,所以可以只通过高电平判断,下面是具体的程序,需要注意的是各回调函数中不能执行太久,最好是设置标志就好了: /******************H头文件*********************************/ #ifndef RF433MDecode_H_ #define RF433MDecode_H_ /***************************************************/ //Define I/O Register #define PORT_RF_REC pa #define P_RF_REC pa.7 #define PC_RF_REC pac.7 #define PPH_RF_REC paph.7 //**************************************************// //Define Constant //在24us定时中断中调用433M接收解码函数 //同步码,10ms低电平 #define C_RF_START_L_MAX 500 //12MS //10MS--10000/24=416 #define C_RF_START_L_MIN 250 //6MS //之后是25位数据,只取24位3个字节 #define C_RF_REC_BIT_LEN 24 //"1"是1.1ms高+0.2ms低,"0"是0.45高+0.9低 //所以可以只通过高电平判断 #define C_RF_DATA1_MAX 54 //1.3ms #define C_RF_DATA1_MIN 37 //0.9ms #define C_RF_DATA0_MAX 25 //0.6ms #define C_RF_DATA0_MIN 13 //0.3ms //结束码,短按:130ms低电平,长按:500ms,这里取大于70ms //#define C_RF_END_L_MAX 500 //140MS #define C_RF_END_L_MIN 2916 //70MS #define C_RF_DATA_CLENT_1 0xAD //客户码1 #define C_RF_DATA_CLENT_2 0x2F //客户码2 #define C_RF_DATA_1_KEY 0x01 //A键值 #define C_RF_DATA_2_KEY 0x02 //B键值 #define C_RF_DATA_3_KEY 0x04 //C键值 #define C_RF_DATA_4_KEY 0x08 //D键值 #define C_DELAY_KEY_PRESS_SHORT 500 //1000*1MS #define C_DELAY_KEY_PRESS_LONG 2000 //3000*1MS /****************************************************/ // Define General Register //************************************************** //Define FUNCTION void RF433M_Init(void); void RF433M_RecevieDecode(void); #endif /******************C文件*********************************/ //*************************************************** //CUSTOMER: //OBJECT:433M解码程序 //AUTHOR:TJY //DESCRIPTION: // 在24us定时中断中调用433M接收解码函数 /************************************************************************* /*************************************************************************/ #include "extern.h" #include "Rf433MDecode.h" byte gb_RfRxStep; //IR接收步骤 word gw_RfRxCnt; //接收计数器 eword gew_RfRxData; //接收数据暂存,//同步码之后是25位数据,只取24位3个字节 byte gb_RfRxData1; //接收数据--//客户代码1 byte gb_RfRxData2; //客户代码2 byte gb_RfRxData3; //数据码 byte gb_RfRxLevel; byte gb_RfRxBitCnt; //接收数据位 bit gbit_RfRecOkFlag; //收到完整的24位数据置1,相当于g_bitKeyDownFlag bit gbit_RfRecEndCodeFlag; //收到结束码 byte g_bTimerCount word gw_RfRxKeeppingMsCnt; //接收第一个数据后开始的计数器 word gw_RfRxKeeppingIntervalCount; bit gbit_ResetFlag; /*************************************************** 接收初始化函数 ***************************************************/ void RF433M_Init(void) { $P_RF_REC High; $P_RF_REC In, NoPull; //设置为输入模式 gb_RfRxStep = 0; gbit_RfRecOkFlag = 0; gbit_RfRecEndCodeFlag = 0; bTimerCount = 0; } /*************************************************** 第一次收到完整的24位数据的回调函数 相当于按键按下调用函数 -- OnkeyDown() 只在开始的时候进一次 ***************************************************/ void RF433M_OnRecevieFirstData(void) { gw_RfRxKeeppingMsCnt = 0; } /*************************************************** 收到完整的24位数据后的回调函数 相当于按键按下调用函数 -- OnkeyPressing() 在按下期间,会不断进入 ***************************************************/ void RF433M_OnRecevieData(void) { if(gw_RfRxKeeppingMsCnt >=C_DELAY_KEY_PRESS_LONG) { //长按 if(gb_RfRxData3 == C_RF_DATA_1_KEY) { } } } /*************************************************** 收到24位数据后,再接收到结束码的回调函数 相当于按键按下松开时调用函数 -- OnkeyUp() ***************************************************/ void RF433M_OnRecevieEndCode(void) { if(gw_RfRxKeeppingMsCnt <= C_DELAY_KEY_PRESS_SHORT) { //短按 switch(gb_RfRxData3) { case C_RF_DATA_1_KEY: { break; } case C_RF_DATA_2_KEY: { break; } case C_RF_DATA_3_KEY: { break; } case C_RF_DATA_4_KEY: { break; } } } } /*************************************************** 433接收解码函数 在24us定时中断中调用433M接收解码函数 同步码,10ms低电平 之后是25位数据,只取24位3个字节 "1"是1.1ms高+0.2ms低,"0"是0.45高+0.9低 所以可以只通过高电平判断 ***************************************************/ void RF433M_RecevieDecode(void) { g_bTimerCount++; if(g_bTimerCount == 42) //1ms=42*24us { g_bTimerCount = 0; gw_RfRxKeeppingMsCnt++; } switch(gb_RfRxStep) { case 0: if(!P_RF_REC) { //1-1.开始检测引导码10ms低电平或结束码100ms低电平 gw_RfRxCnt = 0; gb_RfRxStep = 1; } break; case 1: if(!P_RF_REC) { //1-2.引导码10ms或结束码100ms低电平计时 gw_RfRxCnt++; } else { //1-3.判断引导码9ms低电平或结束码100ms低电平 if(gw_RfRxCnt >C_RF_END_L_MIN && gbit_RfRecOkFlag) { //结束码 gbit_RfRecOkFlag = 0; //相当于按键按下松开时调用函数 -- OnkeyUp() RF433M_OnRecevieEndCode(); return ; } else if((gw_RfRxCnt > C_RF_START_L_MAX) ||(gw_RfRxCnt < C_RF_START_L_MIN)) { goto F_RfRxError; } //引导码 //gbit_RfRecOkFlag = 0; //2-1.开始接收数据,检测引导码4.5ms高电平 gb_RfRxLevel = PORT_RF_REC & _field(P_RF_REC); gw_RfRxCnt = 0; gb_RfRxBitCnt = 0; gb_RfRxStep = 2; //gew_RfRxData = 0; } break; case 2://check level change a = PORT_RF_REC & _field(P_RF_REC); if(a == gb_RfRxLevel) { //电平保持不变 gw_RfRxCnt++; } else { //level change,check current level gb_RfRxLevel = a; if(!P_RF_REC) { //数据0、1是通过高电平时间判断,所以电平跳变为低的时候, //也就获取到高电平的时间了, //就可以判断有效数据0,1 gew_RfRxData = gew_RfRxData<< 1; //slc gew_RfRxData $ 2; //"1"是1.1ms高+0.2ms低, "0"是0.45高+0.9低 //所以可以只通过高电平判断,当然用低电平判断也一样类似 if((gw_RfRxCnt < C_RF_DATA1_MAX) &&(gw_RfRxCnt > C_RF_DATA1_MIN)) {//data 1 set1 gew_RfRxData.0; goto F_RfRxCheckBit; } else if((gw_RfRxCnt < C_RF_DATA0_MAX) &&(gw_RfRxCnt > C_RF_DATA0_MIN)) {//data 0 set0 gew_RfRxData.0; goto F_RfRxCheckBit; } else { goto F_RfRxError; } F_RfRxError: gb_RfRxStep = 0; return; F_RfRxCheckBit: gb_RfRxBitCnt++; if(gb_RfRxBitCnt >= C_RF_REC_BIT_LEN) { //接收完成,设置收到数据标志 gb_RfRxData3 =gew_RfRxData $ 0; //数据码 gb_RfRxData2 = gew_RfRxData$ 1; //客户代码 gb_RfRxData1 =gew_RfRxData $ 2; //客户代码 gbit_RfRecEndCodeFlag =0; gb_RfRxStep = 0; gb_RfRxBitCnt=0; if(!gbit_RfRecOkFlag) { gbit_RfRecOkFlag = 1; //这时候相当于按键的OnkeyDown() RF433M_OnRecevieFirstData(); } //这时候相当于按键的OnkeyPressing() RF433M_OnRecevieData(); } } gw_RfRxCnt = 0; } break; } }
|