无线433发送接收数据测试程序原理,有杂波解决方案

🎯 365bet手机在线注册 📅 2025-07-19 03:04:46 👤 admin 👀 5038 ❤️ 14
无线433发送接收数据测试程序原理,有杂波解决方案

无线433发送接收测试程序

433Mhz无线通信相关知识不做介绍,网上很多

避坑:MCU的接收引脚Data脚,是否配置上拉要参考MCU内部上拉电阻的大小,使用时最好拿示波器测量高低电平对应的电压。

用轮询的方式解码:大多数情况接收端在没收到数据时也会有很多杂波,用中断的方式会造成MCU频繁进入中断,浪费资源;

此测试程序的433编码规则如下:

引导码:4.5ms低电平

逻辑1:560us高+1690us低

逻辑0:560us高 +560us低 ----- 只计算低电平时间可以判断逻辑

引导码—用户码—用户反码—键码—键码反码 --=实际数据32位有效

(和NEC协议差不多 ---- 程序也适合给NEC使用)

在50us定时器的中断服务函数中采样(在软件定时器中采样会收到部分干扰),根据实际波形做软件滤波处理。

采样逻辑:

因为高电平时间一样,在引脚为低电平时计数变量++,50*x为低电平时间,当跳转到高电平时,"根据低电平的时间判断是否为引导码,确定引导码后,跳到接收数据的步骤",继续对低电平计数,完成32位后判断用户码,确定键值

"本文分两部分写:接收解码和发送"

主要看注释部分

======================接收解码部分

1.低电平计数/滤波

接收解码扫描函数,每50us对433接收到的波形计数一次

采样扫描程序

void Recevie433DecodeScan(void) //放在50us定时器中断服务函数中

{

static unsigned char Su8FilterCnt = 0;

static bit SbJumpFlag = 0; //高低电平跳变标志,记录上一次引脚的状态,来反应从高到低或从低到高

if(bRfDecodeOk == 0) //解码不成功的时候需连续解码,解码成功后延时150ms再次解码

{

if(!PIN_DATA) //引脚输入低电平

{

Gu8RfRxLowCnt++; //计时低电平个数来算时间,只通过低电平时间判断逻辑1或逻辑0

Su8FilterCnt = 0; //高电平滤波计算

if(SbJumpFlag && Gu8RfRxLowCnt >= 2) //两个50us的低电平后才判断电平从高到低,忽略部分杂波

{

SbJumpFlag = 0; //高到低跳变

// Su8FilterCnt = 0;

}

}

else //引脚检测到高电平时,判断高高电平是否有效,高电平有效后,计算进入解码程序

{

if(!SbJumpFlag && Su8FilterCnt++ >= 2) //可滤波

{

SbJumpFlag = 1; //低到高跳变

Rf433SoftDecode(); //对上后解码,一次一位

Gu8RfRxLowCnt = 0;

Su8FilterCnt = 0;

}

}

}

}

2.接收步骤并判断用户类型

void Rf433SoftDecode(void)

{

static uchar Su8RfRxBitCnt = 0; //接收数据位

static ulong Su32RfRxData = 0; //数据缓冲区

if(bRfRecStartFlag == 0) //第一步,检测引导码,获取到引导码后开始检测数据

{

if((Gu8RfRxLowCnt > RF_START_L_MIN)&&(Gu8RfRxLowCnt < RF_START_L_MAX)) //引导码判断4.5ms低电平

{

bRfRecStartFlag = 1; //下次循环跳过此if,开始接收数据

Su32RfRxData = 0; //数据缓存清零

Su8RfRxBitCnt = 0; //数据长度清零

Gu8RfRxUserCode = 0;

Gu8RfRxKeyValue = 0;

}

}

else if((bRfRecStartFlag == 1)&&(Su8RfRxBitCnt < RF_REC_BIT_LEN)) //用接收位数判断暂停

{

if((Gu8RfRxLowCnt > RF_LOGIC0_L_MIN)&&(Gu8RfRxLowCnt < RF_LOGIC0_L_MAX))//逻辑0时长判断,低电平时间范围需稍微加宽

{

Su32RfRxData = Su32RfRxData<<1; //LSB,从低位开始传数据,数据0直接位移

Su8RfRxBitCnt++; //总位数++

}

else if((Gu8RfRxLowCnt > RF_LOGIC1_L_MIN)&&(Gu8RfRxLowCnt < RF_LOGIC1_L_MAX))

{

Su32RfRxData = Su32RfRxData<<1;

Su32RfRxData |= 1; //最低位赋值为1

Su8RfRxBitCnt++;

}

else //某一位的时长不符合协议要求,丢弃整个数据

{

bRfRecStartFlag = 0;

Su8RfRxBitCnt = 0;

}

}

if(Su8RfRxBitCnt == 32) //接受完32位后解析用户码

{

Su8RfRxBitCnt = 0;

bRfRecStartFlag = 0; //下一次重新检测引导码

Gu8RfRxUserCode = Su32RfRxData >> 24; //用户码的8位

if(Gu8RfRxUserCode == RF_NEC_USER_CODE)

{

Gu8RfRxKeyValue = Su32RfRxData >> 8; //按键值第二个8位,此处可以判断最低8位是否为其反码

bRfRecCodeOk = 1; //接收到一个NEC/433按键码,上报

}

else if(Gu8RfRxUserCode == RF_433_USER_CODE)//另一种用户码

{

Gu8RfRxKeyValue = Su32RfRxData >> 8;

bRfRecCodeOk = 1;

}

}

}

3.任务处理

void Rf433RecevieDecodeTask(void)

{

static uchar Su8RfRxTimeCnt = 0; //接收时间计数

uchar u8KeyValueHigh = 0;

uchar u8KeyValueLow = 0;

if(bRfRecCodeOk) //发送接收到的命令即可

{

bRfRecCodeOk = 0;

switch(Gu8RfRxKeyValue) //键值判断部分

{

////////////////////////////////UserTask()

}

Gu8RfRxKeyValue = 0;

}

if(bRfDecodeOk) //150ms后再次接受遥控码,可减小时间

{

Su8RfRxTimeCnt++;

if(Su8RfRxTimeCnt >= 150)

{

Su8RfRxTimeCnt = 0;

bRfDecodeOk = 0;

}

}

}

///////////全局与宏

uchar Gu8RfRxLowCnt = 0; //低电平接收计时器

uchar Gu8RfRxHighCnt = 0; //高电平接收计时器

uchar Gu8RfRxUserCode = 0; //客户代码

uchar Gu8RfRxUserCode1 = 0; //客户代码

uchar Gu8RfRxKeyValue = 0; //按键值

bit bRfDecodeOk = 0; //解码是否成功标志位

bit bRfRecStartFlag = 0; //接收同步码成功标志位

bit bRfRecCodeOk = 0;

//引导码低电平时间,4.5ms低电平

#define RF_START_L_MAX 100 //100*50us=5ms

#define RF_START_L_MIN 75 //75*50us=3.9ms

#define RF_START_H_MAX 100 //100*50us=5ms

#define RF_START_H_MIN 75 //75*50us=3.9ms

#define RF_REC_BIT_LEN 32

//逻辑0:560us高+560us低

//逻辑1:560us高+1690us低

#define RF_LOGIC0_L_MAX 18 //18*50us=900us

#define RF_LOGIC0_L_MIN 5 //5*50us=250us

#define RF_LOGIC1_L_MAX 40 //40*50us=2000us

#define RF_LOGIC1_L_MIN 25 //25*50us=1300us

#define RF_NEC_USER_CODE 0x55 //用户码

#define RF_433_USER_CODE 0x5A

//======================发送测试程序,需要连接433接收模块测试

1.发送的主要程序是计算 高和低电平的总时间,再分时间设置引脚的高/低电平;

2.部分宏定义可自定义;

3.根据MCU堆栈大小结构自行解耦,若资源多就用结构体,否则将结构体打散,单个位用位域和联合体解决;

typedef struct

{

unsigned char State; //步骤

unsigned char TxEnable:1; //发送使能位置 //可判断首字节是否为空替代

unsigned char TxTimes; //发送次数 //可宏替代

unsigned char TxTimesCnt; //次数计数器

unsigned char TxBufLength; //数据长度 //可宏替代

unsigned char TxCnt; //高低电平计数、间隔时间计数

unsigned char NowByte;

unsigned char NowByteIndex;

unsigned char NowBit:1;

unsigned char NowBitIndex;

unsigned char FirstSegTime; //第一段时间

unsigned char AllTime; //总时间

}RemoteNecObject_t;

extern RemoteNecObject_t xdata Rm433Info;

//enum ENUM_RemoteNecStep{RF_IDLE,RF_REPEATED,RF_HEAD,RF_SDATA}; //状态表

void RfSendData(uchar KeyValue);

void RfTask_50uS(void);

//对象初始化

RemoteNecObject_t xdata Rm433Info =

{

0,// unsigned char State; //步骤

0,// unsigned char TxEnable:1; //发送使能位置

TX_433_REPEAT_TIMES+1,// unsigned char TxTimes; //发送次数 //可宏替代

0,// unsigned char TxTimesCnt; //次数计数器

6,// unsigned char TxBufLength; //数据长度 //可宏替代

0,// unsigned char TxCnt; //发送计数器

0,// unsigned char NowByte;

0,// unsigned char NowByteIndex;

0,// unsigned char NowBit:1;

0,// unsigned char NowBitIndex;

0,// unsigned char FirstSegTime; //第一段时间

0,// unsigned char AllTime; //一位总时间

};

#if 1 //调用一次测试

uchar TxBuf[6] = {0xA2,0X55,0X55,0X55,0X00,0X5A};

void RfSendData(uchar KeyValue)

{

uchar i = 0;

TxBuf[i++] = 0xA2; //头码

TxBuf[i++] = 0x55;

TxBuf[i++] = 0x55;

TxBuf[i++] = 0x55;

TxBuf[i++] = KeyValue; //键值

TxBuf[i] = 0x5A; //尾码

Rm433Info.State = RF_IDLE; //强制发送

Rm433Info.TxEnable = 1; //使能发送

}

50us一次任务处理

/*

T = 50uS

*/

void RfTask_50uS(void)

{

switch(Rm433Info.State)

{

case RF_IDLE: //空闲,等待使能

if(Rm433Info.TxEnable)

{

Rm433Info.State = RF_HEAD;

Rm433Info.FirstSegTime = TX_HEAD_FIRST_SEG_TIME; //Time/50 //所有时间

Rm433Info.AllTime = TX_HEAD_ALL_FRAME_TIME; //(Seg1+Seg2)/50

Rm433Info.TxCnt = 0;

Rm433Info.NowByteIndex = 0; //Buf[0]

Rm433Info.NowBitIndex = 0;

Rm433Info.TxTimesCnt = 0; //次数:和重复段不同点

}

break;

// case RF_INIT:

//

// break;

case RF_REPEATED: // 重复码

if(++Rm433Info.TxCnt >= TX_REPEAT_INTERVAL_TIME) //间隔时间

{

Rm433Info.TxCnt = 0;

Rm433Info.State = RF_HEAD;

Rm433Info.FirstSegTime = TX_REPEAT_FIRST_SEG_TIME; //Time/50 此时间根据实际需求设置

Rm433Info.AllTime = TX_REPEAT_ALL_FRAME_TIME; //(Seg1+Seg2)/50 //所有时间

Rm433Info.TxCnt = 0;

Rm433Info.NowByteIndex = 0; //Buf[0]

Rm433Info.NowBitIndex = 0;

}

break;

case RF_HEAD: // 头码

//设置第一段时间,总时间,发送一位使能,等待发送完成

if(Rm433Info.TxCnt < Rm433Info.FirstSegTime)

{

TX_GpioPIN = 1; // 预设

}

else

{

TX_GpioPIN = 0;

}

if(++Rm433Info.TxCnt > Rm433Info.AllTime)

{

Rm433Info.TxCnt = 0;

//TX_GpioPIN = 1; //此处会占用一个周期 /******************/

Rm433Info.State = RF_SDATA; //发送完头码发送数据域

Rm433Info.NowByte = TxBuf[Rm433Info.NowByteIndex++];

// MSB

Rm433Info.NowBit = (Rm433Info.NowByte&(0x80>>(Rm433Info.NowBitIndex++)))?1:0;

// LSB --- NowBit = (NowByte&(0x01<

if(Rm433Info.NowBit) //第一个bit牵引

{

Rm433Info.FirstSegTime = TX_FIRST_SEG_TIME_H;

}

else

{

Rm433Info.FirstSegTime = TX_FIRST_SEG_TIME_L;

}

Rm433Info.AllTime = TX_ONE_BIT_ALL_FRAME_TIME; //之后不用改

}

break;

case RF_SDATA:

if(Rm433Info.TxCnt < Rm433Info.FirstSegTime)

{

TX_GpioPIN = 1; // 预设

}

else

{

TX_GpioPIN = 0;

}

if(++Rm433Info.TxCnt >= Rm433Info.AllTime) //发送完 1 bit

{

Rm433Info.TxCnt = 0;

//TX_GpioPIN = 1; //Alltime -1 此行省略//此处会占用一个周期 /******************/

if(Rm433Info.NowBitIndex <= 0x07) //判断是否发送完 1 byte

{

// MSB

Rm433Info.NowBit = (Rm433Info.NowByte&(0x80>>(Rm433Info.NowBitIndex++)))?1:0;

// LSB --- Rm433Info.NowBit = (Rm433Info.NowByte&(0x01<

if(Rm433Info.NowBit)

{

Rm433Info.FirstSegTime = TX_FIRST_SEG_TIME_H;

}

else

{

Rm433Info.FirstSegTime = TX_FIRST_SEG_TIME_L;

}

}

else //Next Byte

{

Rm433Info.NowBitIndex = 0;

if(Rm433Info.NowByteIndex < Rm433Info.TxBufLength)//判断是否发送完数据域

{

Rm433Info.NowByte = TxBuf[Rm433Info.NowByteIndex++];

// MSB

Rm433Info.NowBit = (Rm433Info.NowByte&(0x80>>(Rm433Info.NowBitIndex++)))?1:0;

// LSB --- Rm433Info.NowBit = (Rm433Info.NowByte&(0x01<

if(Rm433Info.NowBit)

{

Rm433Info.FirstSegTime = TX_FIRST_SEG_TIME_H;

}

else

{

Rm433Info.FirstSegTime = TX_FIRST_SEG_TIME_L;

}

}

else

{

Rm433Info.TxTimesCnt++;

if(Rm433Info.TxTimesCnt < Rm433Info.TxTimes) //次数

{

Rm433Info.State = RF_REPEATED; //发送重复码

Rm433Info.TxCnt = 0;

}

else

{

Rm433Info.TxTimesCnt = 0;

Rm433Info.State = RF_IDLE; //空闲,等待使能

TX_GpioPIN = 0;

Rm433Info.TxEnable = 0; //一次发送完成

}

}

}

}

//设置第一段时间,总时间,发送一位使能,等待发送完成,直到第6字节发送完成

break;

}

}

🎯 相关推荐

🎁 合作伙伴