APT32F1023X 发送RF433处理

本文详细介绍了如何使用CMT2110A配合MCU进行数据发送,包括设置发送频率匹配、使用华普微工具检查配置、RF433传输协议的实现,以及GPT定时器在1ms间隔下的应用,以降低空闲时的功耗问题。
摘要由CSDN通过智能技术生成

1.硬件电路--CMT2110A

需要注意:发射端MCU写数据的频率要匹配,如果MCU发送中时间最小脉宽是1MS,那么它的发送需要设置为1kbps。

 通过华普微USB调试工具+PC软件RFPDK_V1.55查看设置是否正确。

2.RF433发送

用到的发送和接收代码来自“无线433发送接收数据测试程序原理,有杂波解决方案_433无线协议-CSDN博客”,我在此基础做了修改方便识别。

发送波形:

空闲电平为 高

引导码 高1ms 低4ms

 逻辑1  高电平时间2ms 低电平时间 1ms
 逻辑0 高电平时间1ms 低电平时间 2ms

重复间隔时间 5ms

3.代码示例

rf.h文件

#ifndef _RF_H_
#define _RF_H_

#include "apt32f102.h"
#define RF_DATA_INIT() 	    	{GPIO_Init(GPIOA0,8,0),GPIO_Write_High(GPIOA0,8);}
#define TX_GpioPIN_H			GPIO_Write_High(GPIOA0,8)
#define TX_GpioPIN_L			GPIO_Write_Low(GPIOA0,8)


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

#define TX_FIRST_SEG_TIME_H  2		//逻辑1的高电平时间
#define TX_FIRST_SEG_TIME_L  1		//逻辑1的低电平时间

#define TX_HEAD_FIRST_SEG_TIME 1		//引导码的低电平时间,基准时间1ms 
#define TX_HEAD_ALL_FRAME_TIME 4	

#define TX_REPEAT_INTERVAL_TIME 5	    //Tx重复间隔时间

#define TX_REPEAT_FIRST_SEG_TIME 1		//重复第一段时间
#define TX_REPEAT_ALL_FRAME_TIME 4		//Tx重复所有帧时间

#define TX_ONE_BIT_ALL_FRAME_TIME TX_FIRST_SEG_TIME_L+TX_FIRST_SEG_TIME_H		//每帧时间Tx 1位  逻辑1或逻辑0的总时间

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  Rm433Info;




#endif

  rf.c 

#include "rf.h"

#define RF_PACKET_SIZE   4//6               		/* Define the payload size here */

#define  TX_433_REPEAT_TIMES 			3		//发送次数
u8 TxBuf[RF_PACKET_SIZE];

RemoteNecObject_t  Rm433Info = 
{
	0,//	unsigned char State;				//步骤
	0,//	unsigned char TxEnable:1;			//发送使能位置
	TX_433_REPEAT_TIMES,//	unsigned char TxTimes;				//发送次数 //可宏替代
	0,//	unsigned char TxTimesCnt;   		//次数计数器
	4,//	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;				//一位总时间
};

static unsigned char user_create (unsigned char *p1, unsigned short int len)
{
    unsigned char sum = 0;	//用于存储累加和的值,初始值为0。
    for(;len > 0; len--)	
    {
        sum += *p1++;
    }
	//return sum;
	return (sum & 0xFF);	// 只保留最低的8位
}

void rf_send_value(U8_T command,U8_T value)
{
	if(Rm433Info.TxEnable == 0 )			//发送是否繁忙
	{
		//
		memset(TxBuf,0x00,sizeof(TxBuf));
		TxBuf[0] = 0x55;
		TxBuf[1] = command;
		TxBuf[2] = value;
		TxBuf[3] = user_create(TxBuf,3);    //校验值;
		
		Rm433Info.State = RF_IDLE; 		 	//发送状态
			
		Rm433Info.TxEnable = 1;     		//使能发送
	}
}

void Radio_Send_FixedLen(void)
{
	switch(Rm433Info.State)
	{
		case RF_IDLE:   //空闲,等待使能
			if(Rm433Info.TxEnable)
			{
				Rm433Info.State = RF_HEAD;								//head
				
				Rm433Info.FirstSegTime = TX_HEAD_FIRST_SEG_TIME;		//Time/50			//所有时间  4.5ms
				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_REPEATED:		// 重复码
				TX_GpioPIN_H;	
			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_H ; // 预设
			}
			else
			{
				TX_GpioPIN_L ;
			}
			
			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<<NowBitIndex++))?1:0;
				
				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;    //之后不用改,Tx 每帧时间1位
			}
			break;
		case RF_SDATA:
			if(Rm433Info.TxCnt < Rm433Info.FirstSegTime)
			{
				TX_GpioPIN_H;  // 预设
			}
			else
			{
				TX_GpioPIN_L;
			}
			
			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<<Rm433Info.NowBitIndex++))?1:0;
					if(Rm433Info.NowBit)
					{
						Rm433Info.FirstSegTime = TX_FIRST_SEG_TIME_H;	//TX_LOGIC1_LOW_TIME
					}
					else
					{
						Rm433Info.FirstSegTime = TX_FIRST_SEG_TIME_L;	//TX_LOGIC0_LOW_TIME
					}
					
				}
				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<<Rm433Info.NowBitIndex++))?1:0;
						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.State = RF_SDATA_H;
						}
					}
				}
				
			}
			//设置第一段时间,总时间,发送一位使能,等待发送完成,直到第N字节发送完成
			break;
		case RF_SDATA_H:
				 Rm433Info.TxTimesCnt = 0;
				 Rm433Info.State = RF_IDLE;					//空闲,等待使能
				 //TX_GpioPIN_L;		
				 TX_GpioPIN_H;					
				 Rm433Info.TxEnable = 0;					//一次发送完成
			break;
		default:
			break;
	}
}


4.具体应用

GPT配置1ms 定时

void GPT0IntHandler(void) 
{
    // ISR content ...
	if((GPT0->MISR&GPT_INT_PEND)==GPT_INT_PEND)		//End of cycle interrupt 
	{
		GPT0->ICR = GPT_INT_PEND;//定时器中断

		bFixTimer = 1;			//1ms
		Radio_Send_FixedLen();	//RF发送函数	
	}
}

  调用发送函数,按键触发调用一次发送。

     rf_send_value(0x01,0x0A);        //模式1   等级10

修正:空闲时将发送脚设置为低电平。如果DATA是高电平时功耗异常,到达20ma.

		case RF_IDLE:   //空闲,等待使能
			if(Rm433Info.TxEnable)
			{
				Rm433Info.State = RF_HEAD;								//head
				
				Rm433Info.FirstSegTime = TX_HEAD_FIRST_SEG_TIME;		//Time/50			//所有时间  4.5ms
				Rm433Info.AllTime = TX_HEAD_ALL_FRAME_TIME;				//(Seg1+Seg2)/50 
				Rm433Info.TxCnt = 0;
				Rm433Info.NowByteIndex = 0;			//Buf[0]
				Rm433Info.NowBitIndex = 0;
				Rm433Info.TxTimesCnt = 0;			//次数:和重复段不同点
			}
            else
            {
                TX_GpioPIN_L ;
            }
			break;
			

本人非专业人士,只是一个小小程序员,arduino纯属爱好,所发文章仅限于本人智商,如有问题,请大家指正。 近期对智能家居比较敢兴趣,其中存在几个无线传输的模块,起初选用的2.4G的nRL24L01模块,那个东西真是折腾死人,弄了一个星期都没找到问题点。最后在收拾元件箱子的时候,发现一套以前买的433Mhz模块,就想干脆用这个吧。在各种方式的search,找到了一个lib - RCSwitch,看了例子还比较好用,可以传输24bit的值。立刻装上测试。 315\433射频模块介绍: 当发射电压为3V时,空旷地传输距离约20~50米,发射功率较小,当电压5V时约100~200米,当电压9V时约300~500米,当发射电压为12V时,为最佳工作电压,具有较好的发射效果,发射电流约60毫安,空旷地传输距离700~800米,发射功率约500毫瓦。外接天线:10cm(发射模块天线:10cm,接收模块天线:30cm)多芯或单芯普通导线。 在实际测试中,随便接了跟电线,传输能达到5米,无丢包现象。这个射频模块的穿墙效果,应该会比2.4G的好很多。我家里以前一套315Mhz的报警器,全屋传输无压力。 接线很简单,只有三个脚,两个是电源,一个是数据。 发射端 VCC GND DATA- arduino 10脚(可以变更,在代码中调整) 接收端 VCC GND DATA- arduino 2脚(使用终端2则使用3脚,在代码中调整) 程序使用RCSwitch附带示例修改,传感器值使用随机数替代。 传输思路是将24bit的值分开,前12位为传感器ID,后12位为传感器值,12bit,可以到4096,应该够用了。 其他的控制编码器的例子还没有试,下次测试好了再来。 说明: 还忘了一个重要的东西,在lib中有个代码需要修改,不然会接受到4个重复的值。由于本人对中断不是很熟悉,不知道4个重复值造成的原因,只是测试出改了一个值,请各位大师给予解答。 [pre lang="arduino" line="1"]void RCSwitch::handleInterrupt() { if (repeatCount == 6) { // 需要将 2改为 6repeatCount == 2 if (receiveProtocol1(changeCount) == false){ if (receiveProtocol2(changeCount) == false){ if (receiveProtocol3(changeCount) == false){ //failed } } } repeatCount = 0; } }[/pre] RF射频模块发射端程序部分截图: RF射频模块接收端程序部分截图:
)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 发射实际长度来 编写。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值