记录一个小项目,两种方法解码433,包括24Bit数据帧结构和32Bit数据帧结构
1、433接收模块
本文用两种方法解析433Mhz模块的信号,分别是扫描和定时器输入捕获。解析信号首先要了解433信号的编码格式。以24Bit格式帧为例,包含同步码,20位地址码和4位数据码。
数据帧格式如下:同步码 + 20Bit地址码 + 4Bit按键码
可以看出,每组信息都是紧跟在一个同步码后面,所以需要找到这个同步信号,然后解析出后面的24位数据。而同步信号、数据“1”和数据“0”的高低电平持续时间不同,可以根据这一点进行区分。
下图左一是本文使用到的433接收模块,从右到左三个引脚分别是VCC,DATA,GND。再左边是天线。给433模块供电(3.3V),然后把DATA引脚与GND引脚接上示波器,查看数据波形。右图是两个433遥控器,棕色是24位编码格式,黑色是32位编码格式。
通过示波器查看接收模块收到的两个遥控器的数据,整理如下:
棕色遥控器:
上:同步信号 + 0000 0001 0000 0000 0111 + 0100
下:同步信号 + 0000 0001 0000 0000 0111 + 1000
锁:同步信号 + 0000 0001 0000 0000 0111 + 0001
方块:同步信号 + 0000 0001 0000 0000 0111 + 0010
四个按键前20位数据相同,为棕色遥控器的地址码,后面4位数据不同,为数据码,分别对应不同的按键。
高低电平持续时间:
同步信号: 高电平 408us 低电平 12.4ms
数据“1”: 高电平 1.2ms 低电平 410us
数据“0”: 高电平 410us 低电平 1.2ms
黑色遥控器:
上:同步信号 + 1111 0111 1100 1100 1111 0000 0000 + 1000
下:同步信号 + 1111 0111 1100 1100 1111 0000 0000 + 0001
方块:同步信号 + 1111 0111 1100 1100 1111 0000 0000 + 0100
圆圈:同步信号 + 1111 0111 1100 1100 1111 0000 0000 + 0010
黑色遥控器的数据编码为32位,解析方法跟上面的基本一致。
高低电平持续时间:
同步信号: 高电平 364us 低电平 8ms
数据“1”: 高电平 1.084ms 低电平 362us
数据“0”: 高电平 362us 低电平 1.084ms
现在已经整理出了两个遥控器的编码格式,以及每个按键对应的数据。接下来就要想办法把这些数据解析出来,MCU要能够检测到遥控器的哪一个按键被按下,才能去执行对应的功能。
2、扫描方式解析数据
编程思路:
把433接收模块DATA引脚连接在一个IO上,并把IO配置为浮空输入。再配置一个定时器,50us进入一次中断。
每50us检测一下IO的电平,如果是低电平,就开始计数,是高电平的话计算低电平持续的时间(计数值*50us),判断是否符合上面介绍的电平持续时间。如果符合其中一个同步信号,就开始准备接收数据,之后每个低电平过来,都拿它的持续时间跟数据“1”和数据“0”比较,并进行记录。这样就可以把数据解析出来。
源码:
//---------------------------------------------------------------------------------------------------------------------
//一些宏定义和变量
#define RF_DATA_PORT GPIOA
#define RF_DATA_PIN GPIO_Pin_8
#define RF_DATA_RCC_PORT RCC_APB2Periph_GPIOA
//同步信号、数据'0'、数据'1'低电平持续时间范围
#define _24start_us_min 220 //低电平参考值(us)/定时器扫描周期(us)- 预留范围(us) 24Bit格式 同步信号 低电平持续时间参考值 12400us/50us == 248
#define _24start_us_max 260 //低电平参考值(us)/定时器扫描周期(us)+ 预留范围(us)
#define _24num0_us_min 23 //24Bit格式数据'0'低电平持续时间参考值 1200us/50us == 24
#define _24num0_us_max 26
#define _24num1_us_min 7 //24Bit格式数据'1'低电平持续时间参考值 410us/50us == 8
#define _24num1_us_max 10
#define _32start_us_min 155 //32Bit格式 同步信号 低电平持续时间参考值 8000us/50us == 160
#define _32start_us_max 165
#define _32num0_us_min 16 //32Bit格式 数据'0' 低电平持续时间参考值 1084us/50us == 21
#define _32num0_us_max 26
#define _32num1_us_min 6 //32Bit格式 数据'1' 低电平持续时间参考值 360us/50us == 7
#define _32num1_us_max 10
#define RF_DATA GPIO_ReadInputDataBit(RF_DATA_PORT,RF_DATA_PIN)//读取接口电平
/*
变量说明:
last_state 记录上一个电平,用来判断跳变沿 例如: last_state == 0 RF_DATA == 1 就表示上升沿
ReadStep 控制数据解析的进度 ReadStep==0,接收同步信号 ; ReadStep==1,接收24位(或32位)数据 ; ReadStep==2,数据接收完成,解析数据;
DataFram 数据帧格式 24位或者32位
BitCount 记录当前接收了多少位数据
decode32_ok 32位格式数据解析成功
decode24_ok 24位格式数据解析成功
ReadLoop 读数据的次数 需要循环两次读两组数据
CheckTime 校验计时 接收完第一组数据后,开始倒计时,如果100ms内没有接收到第二组数据,则解析失败,回到开始重新接收数据
LowTime 低电平持续时间
TempData[2]; 存放临时数据
rf_data32[4]; 存放解析成功的32位格式数据,数组前几位存放地址值,最后一位存放数据值
rf_data24[3]; 存放解析成功的24位格式数据
*/
unsigned char last_state,ReadStep,DataFram,BitCount,decode32_ok,decode24_ok,ReadLoop;
unsigned int CheckTime;
unsigned int LowTime = 0;
unsigned int TempData[2] = {0};
unsigned char rf_data32[4] = {0};
unsigned char rf_data24[3] = {0};
//---------------------------------------------------------------------------------------------------------------------
//初始化
void RF433_Init(void)
{
RF433_DATA_IO_Init();
TIM3_Int_Init(49,71);//72分频,计数50, 即50us计时器 72MHZ经过分频编程1MHZ,1s内中断1M次,1us中断1次,50us终端50次
}
void RF433_DATA_IO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RF_DATA_RCC_PORT, ENABLE); //使用PA端口时钟
GPIO_InitStructure.GPIO_Pin = RF_DATA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
//定时器TIM3初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx
}
//---------------------------------------------------------------------------------------------------------------------
//中断服务函数
void TIM3_IRQHandler(void) //TIM3中断 50us中断
{
static unsigned int TIM3_Count = 0;
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志
RF433_ReadAWord(); //解析函数
}
}
//---------------------------------------------------------------------------------------------------------------------
//解析函数
void RF433_ReadAWord(void)
{
if(RF_DATA==0) //记录低电平时间,来判断数据是'1'还是'0'
{
LowTime++;
if(last_state == 1)
{
last_state = 0;
}
}
else if(RF_DATA==1)
{
if(last_state == 0) //判断是否是上升沿
{
last_state = 1;
//进入这里说明一位数据传输结束了,现在开始判断这一位数据是什么
if(ReadStep == 0) //读同步信号
{
// if((LowTime > (7500/50)) && (LowTime < (8500/50))) 8000us/50us == 160
if((LowTime >= _32start_us_min) && (LowTime <= _32start_us_max))
{
DataFram = 32;//32 位数据格式,黑色钥匙
ReadStep = 1;
}
else if((LowTime >= _24start_us_min) && (LowTime <= _24start_us_max)) //12400us/50us == 248
{
DataFram = 24;//24 位数据格式,棕色钥匙
ReadStep = 1;
}
LowTime = 0;
}
else if(ReadStep == 1) //接收数据
{
if(DataFram == 32) //32 位数据解析
{
if((LowTime >= _32num1_us_min) && (LowTime <= _32num1_us_max))
// if((LowTime >= (300/50)) && (LowTime <= (400/50))) //数据1 360us/50us == 7
{
TempData[ReadLoop] |= 0x80000000>>BitCount;
BitCount++;
}
else if((LowTime >= _32num0_us_min) && (LowTime <= _32num0_us_max))
// else if((LowTime > (900/50)) && (LowTime < (1200/50))) //数据0 1084us/50us == 21
{
TempData[ReadLoop] &= ~(0x80000000>>BitCount);
BitCount++;
}
else //数据出错,重新接收
{
ReadStep = 0;
BitCount = 0;
}
LowTime = 0;
}
else if(DataFram == 24) //24 位数据解析
{
if((LowTime >= _24num1_us_min) && (LowTime <= _24num1_us_max)) //数据1 410us/50us == 8
{
TempData[ReadLoop] |= 0x80000000>>BitCount;
BitCount++;
}
else if((LowTime >= _24num0_us_min) && (LowTime <= _24num0_us_max)) //数据0 1200us/50us == 24
{
TempData[ReadLoop] &= ~(0x80000000>>BitCount);
BitCount++;
}
else //数据出错,重新接收
{
ReadStep = 0;
BitCount = 0;
}
LowTime = 0;
}
if(BitCount >= DataFram) //数据接收完成
{
BitCount = 0;
ReadLoop++;
if(ReadLoop < 2) //接收数据少于 2 组
{
ReadStep = 0; //重新读取同步信号,读 2 组数据
CheckTime = 100000/50; //接收完第一组,开始倒计时,设置为 100ms 内
}
else //已经读取两组了
{
ReadLoop = 0;
ReadStep = 2;
}
}
if(ReadLoop==1) //只读取到一组数据
{
CheckTime--; //校验倒计时,规定时间内没收到第二组,就是校验失败,需要重新接收
if(CheckTime == 0)
{
ReadLoop = 0;
ReadStep = 0;
}
}
}
if(ReadStep == 2) //接收完成,处理数据
{
if(TempData[0] == TempData[1]) //收到连续两组相同的数据,再开始解析
{
if(DataFram == 32) //32 位数据解析
{
rf_data32[0] = TempData[0]>>24;
rf_data32[1] = TempData[0]>>16;
rf_data32[2] = TempData[0]>>8;
rf_data32[3] = TempData[0]>>0;
decode32_ok = 1;
RfDuty_32Bit(); //黑色遥控器任务函数,这里也可以在主函数里检测decode32_ok 标志位调用
}
else if(DataFram == 24) //24 位数据解析
{
rf_data24[0] = TempData[0]>>24;
rf_data24[1] = TempData[0]>>16;
rf_data24[2] = TempData[0]>>8;
decode24_ok = 1;
RfDuty_24Bit(); //棕色遥控器任务函数
}
}
ReadStep = 0;
DataFram = 0;
}
}
}
}
//----------------------------------------------------------------------------------------------
//任务函数
void RfDuty_32Bit(void)
{
decode32_ok = 0;
if(rf_data32[3] == 0x08)
printf("黑色钥匙上三角\r\n");
else if(rf_data32[3] == 0x01)
printf("黑色钥匙下三角\r\n");
else if(rf_data32[3] == 0x04)
printf("黑色钥匙方块\r\n");
else if(rf_data32[3] == 0x02)
printf("黑色钥匙圆\r\n");
}
void RfDuty_24Bit(void)
{
Decode24_ok = 0;
if(rf_data24[2] == 0x74)
printf("棕色钥匙上三角\r\n");
else if(rf_data24[2] == 0x78)
printf("棕色钥匙下三角\r\n");
else if(rf_data24[2] == 0x71)
printf("棕色钥匙锁\r\n");
else if(rf_data24[2] == 0x72)
printf("棕色钥匙方块\r\n");
}
//--------------------------------------------------------------------------
//main函数
int main(void)
{
uart_init(115200);
RF433_Init();
printf("433遥控器\r\n");
while(1)
{
}
}
3、定时器输入捕获方式解析数据
定时器输入捕获的编程思路跟扫描方式很相似,只是把检测低电平时间的任务交给了定时器,不再用扫描的方式对变量累加,本文使用定时器5的通道1。定时器的计数部分配置为1us中断,配置过程跟上面类似,这里主要注意定时器输入捕获的一些参数。
TIM_ICInitTypeDef TIM5_ICInitStructure;
//初始化TIM5输入捕获参数
TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 选择输入端 IC1映射到TI1上
TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //下降沿捕获
TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频
TIM5_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波
TIM_ICInit(TIM5, &TIM5_ICInitStructure);
第一个参数是选择通道,选择通道1就行了。
第二个是选择上升沿还是下降沿捕获,因为要捕获低电平所以先设置为下降沿捕获,在检测到下降沿后清0定时器的计数值,再更改为上升沿捕获,这样在捕获到上升沿时,定时器的计数值就是低电平的持续时间。
第三个参数是映射,IC1可以映射到TI1,也可以映射到TI2,选择TI1就好(这里个人理解,如果映射到TI1,那么定时器的通道一电平跳变时触发捕获中断,如果映射到二,那么定时器通道二电平跳变时触发捕获中断)。
第四个是分频,可以设置检测到几个上升沿才算做一个有效上升沿,如果设置为8,就是连续8个上升沿才记一次,这里不分频,就是每一个上升沿进入中断。
第五个参数是滤波,检测到上升沿后,进行一些时钟周期的延迟,如果一直保持高电平,才算有效上升沿,把一些持续时间短的信号滤掉,这里不滤波,检测到高电平立刻进入中断。
源码:
//---------------------------------------------------------------------------------------
//宏定义和变量说明
#define h_24start_us_min 208 //24Bit格式 同步信号 高电平参考值 408us
#define h_24start_us_max 608
#define h_24num0_us_min 210 //24Bit格式数据'0'高电平持续时间参考值 410us
#define h_24num0_us_max 610
#define h_24num1_us_min 1000 //24Bit格式数据'1'高电平持续时间参考值 1200us
#define h_24num1_us_max 1400
#define l_24start_us_min 11400 //24Bit格式 同步信号 低电平参考值 12400us
#define l_24start_us_max 13400
#define l_24num0_us_min 1000 //24Bit格式数据'0'低电平持续时间参考值 1200us
#define l_24num0_us_max 1400
#define l_24num1_us_min 200 //24Bit格式数据'1'低电平持续时间参考值 410us
#define l_24num1_us_max 600
#define h_32start_us_min 164 //32Bit格式 同步信号 高电平持续时间参考值 364us
#define h_32start_us_max 564
#define h_32num0_us_min 162 //32Bit格式 数据'0' 高电平持续时间参考值 362us
#define h_32num0_us_max 562
#define h_32num1_us_min 884 //32Bit格式 数据'1' 高电平持续时间参考值 1084us
#define h_32num1_us_max 1284
#define l_32start_us_min 7000 //32Bit格式 同步信号 低电平持续时间参考值 8000us
#define l_32start_us_max 9000
#define l_32num0_us_min 884 //32Bit格式 数据'0' 低电平持续时间参考值 1084us
#define l_32num0_us_max 1284
#define l_32num1_us_min 160 //32Bit格式 数据'1' 低电平持续时间参考值 360us
#define l_32num1_us_max 560
/*
变量说明:
DataFram 数据帧格式 24位或者32位
BitCount 记录当前接收了多少位数据
decode32_ok 32位格式数据解析成功
decode24_ok 24位格式数据解析成功
ReadLoop 读数据的次数 需要循环两次读两组数据
CheckTime 校验计时 接收完第一组数据后,开始倒计时,如果100ms内没有接收到第二组数据,则解析失败,回到开始重新接收数据
TempData[2]; 存放临时数据
rf_data32[4]; 存放解析成功的32位格式数据,数组前几位存放地址值,最后一位存放数据值
rf_data24[3]; 存放解析成功的24位格式数据
*/
unsigned char DataFram,BitCount,decode32_ok,decode24_ok,ReadLoop;
unsigned int CheckTime;
unsigned int TempData[2] = {0};
unsigned char rf_data32[4] = {0};
unsigned char rf_data24[3] = {0};
/*TIM5CH1_CAPTURE_STA
Bit7 Bit6 Bit5 Bit4~Bit0
捕获完成 同步码 下降沿 保留
*/
u8 TIM5CH1_CAPTURE_STA=0; //输入捕获状态
u16 TIM5CH1_CAPTURE_LVAL; //记录低电平持续时间
u16 TIM5CH1_CAPTURE_HVAL;
//---------------------------------------------------------------------------------------
//初始化
void RF433_Init(void)
{
TIM5_Cap_Init(0xFFFF,71);//72分频 72MHZ经过分频变成1MHZ,1us中断1次
}
void TIM5_Cap_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_ICInitTypeDef TIM5_ICInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //使能TIM5时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0 清除之前设置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
//初始化定时器5 TIM5
TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
//初始化TIM5输入捕获参数
TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 选择输入端 IC1映射到TI1上
TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //下降沿捕获
TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频
TIM5_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波
TIM_ICInit(TIM5, &TIM5_ICInitStructure);
//中断分组初始化
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级2级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级0级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断 ,允许CC1IE捕获中断
TIM_Cmd(TIM5,ENABLE ); //使能定时器5
}
//---------------------------------------------------------------------------------------
//中断服务函数
//定时器5中断服务程序
void TIM5_IRQHandler(void)
{
if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
{
}
if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
{
if(TIM5CH1_CAPTURE_STA&0x20) //第二步,捕获上升沿
{
TIM5CH1_CAPTURE_STA &= ~0x20;
TIM5CH1_CAPTURE_LVAL = TIM_GetCapture1(TIM5); //读取低电平持续的时间
TIM_SetCounter(TIM5,0);
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //准备捕获下降沿
if(TIM5CH1_CAPTURE_STA&0x40) //如果接收到了同步码
{
if(DataFram == 32) //32 位数据解析
{
if((TIM5CH1_CAPTURE_LVAL >= l_32num1_us_min) && (TIM5CH1_CAPTURE_LVAL <= l_32num1_us_max) && (TIM5CH1_CAPTURE_HVAL >= h_32num1_us_min) && (TIM5CH1_CAPTURE_HVAL <= h_32num1_us_max)) //数据1
{
TempData[ReadLoop] |= 0x80000000>>BitCount;
BitCount++;
}
else if((TIM5CH1_CAPTURE_LVAL >= l_32num0_us_min) && (TIM5CH1_CAPTURE_LVAL <= l_32num0_us_max) && (TIM5CH1_CAPTURE_HVAL >= h_32num0_us_min) && (TIM5CH1_CAPTURE_HVAL <= h_32num0_us_max)) //数据0
{
TempData[ReadLoop] &= ~(0x80000000>>BitCount);
BitCount++;
}
else //数据出错,重新接收
{
TIM5CH1_CAPTURE_STA &= ~0x40; //重新读取同步信号
BitCount = 0;
}
}
else if(DataFram == 24) //24 位数据解析
{
if((TIM5CH1_CAPTURE_LVAL >= l_24num1_us_min) && (TIM5CH1_CAPTURE_LVAL <= l_24num1_us_max) && (TIM5CH1_CAPTURE_HVAL >= h_24num1_us_min) && (TIM5CH1_CAPTURE_HVAL <= h_24num1_us_max)) //数据1
{
TempData[ReadLoop] |= 0x80000000>>BitCount;
BitCount++;
}
else if((TIM5CH1_CAPTURE_LVAL >= l_24num0_us_min) && (TIM5CH1_CAPTURE_LVAL <= l_24num0_us_max) && (TIM5CH1_CAPTURE_HVAL >= h_24num0_us_min) && (TIM5CH1_CAPTURE_HVAL <= h_24num0_us_max)) //数据0
{
TempData[ReadLoop] &= ~(0x80000000>>BitCount);
BitCount++;
}
else //数据出错,重新接收
{
TIM5CH1_CAPTURE_STA &= ~0x40; //重新读取同步信号
BitCount = 0;
}
}
if(BitCount >= DataFram) //黑色钥匙 32 位数据
{
BitCount = 0;
ReadLoop++;
if(ReadLoop < 2) //接收数据少于 2 组
{
TIM5CH1_CAPTURE_STA &= ~0x40; //重新读取同步信号,读 2 组数据
CheckTime = 100000; //接收完第一组,开始倒计时,设置为 100ms 内
}
else //已经读取两组了
{
ReadLoop = 0;
TIM5CH1_CAPTURE_STA |= 0x80; //标记读取数据完成
rf433_decode();
}
}
if(ReadLoop==1) //读取到一组数据,等待第二组,倒计时
{
CheckTime--; //校验倒计时,规定时间内没收到第二组,就是校验失败,需要重新接收
if(CheckTime == 0)
{
ReadLoop = 0;
TIM5CH1_CAPTURE_STA &= ~0x40; //重新读取同步信号
}
}
}
else //没有收到同步码
{
if((TIM5CH1_CAPTURE_LVAL >= l_32start_us_min) && (TIM5CH1_CAPTURE_LVAL <= l_32start_us_max) && (TIM5CH1_CAPTURE_HVAL >= h_32start_us_min) && (TIM5CH1_CAPTURE_HVAL <= h_32start_us_max))
{
DataFram = 32;//32 位数据格式,黑色钥匙
TIM5CH1_CAPTURE_STA |= 0x40; //标记收到了同步码
}
else if((TIM5CH1_CAPTURE_LVAL >= l_24start_us_min) && (TIM5CH1_CAPTURE_LVAL <= l_24start_us_max) && (TIM5CH1_CAPTURE_HVAL >= h_24start_us_min) && (TIM5CH1_CAPTURE_HVAL <= h_24start_us_max))
{
DataFram = 24;//24 位数据格式,棕色钥匙
TIM5CH1_CAPTURE_STA |= 0x40;
}
}
TIM5CH1_CAPTURE_HVAL=0;
}
else //第一步,捕获下降沿
{
TIM5CH1_CAPTURE_HVAL = TIM_GetCapture1(TIM5); //读取高电平持续的时间
TIM5CH1_CAPTURE_LVAL=0;
TIM_SetCounter(TIM5,0);
TIM5CH1_CAPTURE_STA|=0X20; //标记捕获到了下降沿
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //准备捕获上升沿
}
}
TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
}
//---------------------------------------------------------------------------------------
//解码函数和任务函数
void rf433_decode(void)
{
if(TIM5CH1_CAPTURE_STA | 0x80) //接收到一次完整数据,开始解码
{
if(TempData[0] == TempData[1]) //收到连续两组相同的数据,再开始解析
{
if(DataFram == 32) //32 位数据解析
{
rf_data32[0] = TempData[0]>>24;
rf_data32[1] = TempData[0]>>16;
rf_data32[2] = TempData[0]>>8;
rf_data32[3] = TempData[0]>>0;
decode32_ok = 1;
RfDuty_32Bit();
}
else if(DataFram == 24) //24 位数据解析
{
rf_data24[0] = TempData[0]>>24;
rf_data24[1] = TempData[0]>>16;
rf_data24[2] = TempData[0]>>8;
decode24_ok = 1;
RfDuty_24Bit();
}
}
TIM5CH1_CAPTURE_STA = 0;//状态标志位清0
DataFram = 0;
}
}
void RfDuty_32Bit(void)
{
decode32_ok = 0;
if(rf_data32[3] == 0x08)
printf("黑色钥匙上三角\r\n");
else if(rf_data32[3] == 0x01)
printf("黑色钥匙下三角\r\n");
else if(rf_data32[3] == 0x04)
printf("黑色钥匙方块\r\n");
else if(rf_data32[3] == 0x02)
printf("黑色钥匙圆\r\n");
}
void RfDuty_24Bit(void)
{
decode24_ok = 0;
if(rf_data24[2] == 0x74)
printf("棕色钥匙上三角\r\n");
else if(rf_data24[2] == 0x78)
printf("棕色钥匙下三角\r\n");
else if(rf_data24[2] == 0x71)
printf("棕色钥匙锁\r\n");
else if(rf_data24[2] == 0x72)
printf("棕色钥匙方块\r\n");
}
//---------------------------------------------------------------------------------------
//运行结果