对应上篇RF433发送:APT32F1023X 发送RF433处理-CSDN博客
1.硬件
接收芯片来自华普微:
CMT2210LB_OOK射频接收芯片_315/433/8686/915MHz无线接收芯片 - RF射频、数字传感器产品专业设计生产商-深圳市华普微电子股份有限公司
2.代码示例
rf433.c
#include "rf433.h"
/*
* ------- -- ----
* | | | | |
* -------- ---- --
* */
//引导码低电平时间,4ms低电平 1ms高电平
#define RF_START_L_MAX 90 //80*50us=4ms
#define RF_START_L_MIN 70 //
#define RF_START_H_MAX 15 //
#define RF_START_H_MIN 5 //
#define RF_REC_BIT_LEN 32 //32位数据 4个字节
// 准备就绪:高电平1ms,4ms低电平
// 逻辑0:高电平1ms,低电平2ms
// 逻辑1:高电平2ms,低电平1ms
#define RF_LOGIC0_L_MAX 45//27 //50us 2ms 40
#define RF_LOGIC0_L_MIN 35//12 //50us
#define RF_LOGIC1_L_MAX 25//14 //50us 1ms 20
#define RF_LOGIC1_L_MIN 15//7 //
#define RF_433_USER_CODE 0xA2
volatile U8_T Su8RfRxBitCnt = 0; //接收数据位
volatile U32_T Su32RfRxData = 0; //数据缓冲区
///全局与宏
volatile U8_T Gu8RfRxLowCnt = 0; //低电平接收计时器
volatile U8_T Gu8RfRxHighCnt = 0; //高电平接收计时器
volatile U8_T Gu8RfRxUserCode = 0; //客户代码
volatile U8_T Gu8RfRxUserCode1 = 0; //客户代码
volatile U8_T Gu8RfRxKeyValue = 0; //按键值
volatile U8_T bRfDecodeOk = 0; //解码是否成功标志位
volatile U8_T bRfRecStartFlag = 0; //接收同步码成功标志位
volatile U8_T bRfRecCodeOk = 0;
/*
*********************************************************************************************************
* 函 数 名: user_create
* 功能说明: 校验函数
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
unsigned char user_create (unsigned char *p1, unsigned short int len)
{
unsigned char sum = 0;
for(;len > 0; len--)
{
sum += *p1++;
}
//return sum;
return (sum & 0xFF);// 只保留最低的8位
}
/*
*********************************************************************************************************
* 函 数 名: Rf433SoftDecode
* 功能说明: 解码函数
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void Rf433SoftDecode(void)
{
//临时变量
volatile char *pa;
//
if(bRfRecStartFlag == 0) //第一步,检测引导码,获取到引导码后开始检测数据
{
if((Gu8RfRxLowCnt > RF_START_L_MIN)&&(Gu8RfRxLowCnt < RF_START_L_MAX)) //引导码判断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;
Su32RfRxData |= 1; //最低位赋值为1
Su8RfRxBitCnt++;
}
else //某一位的时长不符合协议要求,丢弃整个数据
{
bRfRecStartFlag = 0;
Su8RfRxBitCnt = 0;
}
}
if(Su8RfRxBitCnt == 32) //接受完32位后解析用户码
{
Su8RfRxBitCnt = 0;
bRfRecStartFlag = 0; //下一次重新检测引导码
//
pa =(char *)&Su32RfRxData;
//
g_rxBuffer[0] = *((char *)pa+3);
g_rxBuffer[1] = *((char *)pa+2);
g_rxBuffer[2] = *((char *)pa+1);
g_rxBuffer[3] = *((char *)pa+0);
//验证是否正确
if(g_rxBuffer[3] == (user_create(g_rxBuffer,3)))
{
bRfRecCodeOk = 1;
//my_printf("g_rxBuffer[0] = %x",g_rxBuffer[0]);
//my_printf("g_rxBuffer[1] = %x",g_rxBuffer[1]);
//my_printf("g_rxBuffer[2] = %x",g_rxBuffer[2]);
//my_printf("g_rxBuffer[3] = %x",g_rxBuffer[3]);
}
}
}
/*
*********************************************************************************************************
1.低电平计数/滤波
接收解码扫描函数,每50us对433接收到的波形计数一次
采样扫描程序
*********************************************************************************************************
*/
void Recevie433DecodeScan(void) //放在50us定时器中断服务函数中
{
static U8_T Su8FilterCnt = 0;
static U8_T SbJumpFlag = 0; //高低电平跳变标志,记录上一次引脚的状态,来反应从高到低或从低到高
if(bRfDecodeOk == 0) //解码不成功的时候需连续解码,解码成功后延时150ms再次解码
{
if(!RF_IO_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;
}
}
}
}
rf433.h
#ifndef _RF433_H_
#define _RF433_H_
//.H之中声明,在外部调用时,只需要#include包含相对应的.h
//需要用到的头文件
#include "apt32f102.h"
#include "my_printf.h"
#include "apt32f102_gpio.h"
//IO
#define RF_IO_DATA GPIO_Read_Status(GPIOB0,3)
//
#define RF_PACKET_SIZE 4//32 /* Define the payload size here */
U8_T g_rxBuffer[RF_PACKET_SIZE]; /* RF Rx buffer */
extern volatile U8_T Su8RfRxBitCnt ; //接收数据位
extern volatile U32_T Su32RfRxData ; //数据缓冲区
extern volatile U8_T bRfDecodeOk ; //解码是否成功标志位
extern volatile U8_T bRfRecStartFlag ; //接收同步码成功标志位
extern volatile U8_T bRfRecCodeOk ;
//函数声明
unsigned char user_create (unsigned char *p1, unsigned short int len);
void Rf433SoftDecode(void);
void Recevie433DecodeScan(void) ;
#endif
3.实际处理
解码函数定时50us中断中
if((GPT0->MISR&GPT_INT_PEND)==GPT_INT_PEND) //End of cycle interrupt
{
GPT0->ICR = GPT_INT_PEND;//定时器中断
//50us
Recevie433DecodeScan(); //433接收处理。
}
解码成功后,进行逻辑处理。
void rf_pro(void)
{
if(bRfRecCodeOk) //解码成功,接收到的命令按照命令进行解析。
{
bRfRecCodeOk = 0;
//
Su8RfRxTimeCnt= 0;
bRfDecodeOk = 1; //成功标志,间隔一段时间去解码。
switch(g_rxBuffer[1])
{
case 0x01:
buzzer_en(1); //蜂鸣器响1次
break;
casw 0x02:
break;
}
}
if(bRfDecodeOk) //110ms后再次接受遥控码,可减小时间
{
Su8RfRxTimeCnt++;
if(Su8RfRxTimeCnt >= 200) //1ms
{
Su8RfRxTimeCnt = 0;
bRfDecodeOk = 0;
//bRfRecCodeOk = 0;
}
}
}