我使用的模块是stm32F103R8T6,配合STM32CudeMX实现的红外遥控串口通讯
一、 红外编码
1、实物设备
发射管,红外发光二极管,发出的是红外线而不是可见光,红外线波长为940nm左右。(在遥控器上面): 接收管是红外接收二极管VS1838B,在实际应用中要给红外接收二极管加反向偏压,它才能正常工作,亦即红外接收二极管在电路中应用时是反向运用,这样才能获得较高的灵敏度。和主控芯片具有定时器输入捕获功能的I/O引脚连接在一起: 遥控器: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210329144533595.png)
2、基本原理
调制:将数据能够发送更远,并且数据的损耗在合理范围内,大致过程如下1–》2–》3。 解调:将接收到的已调数据重新恢复并获取出来,大致过程如下的3–》2–》1。 红外通信是利用950nm近红外波段的红外线作为传递信息的媒体, 即通信信道。 发送端采用脉时调制(PPM) 方式, 将二进制数字信号调制成某一频率的脉冲序列, 并驱动红外发射管以光脉冲的形式发送出去; 接收端将接收到的光脉转换成电信号, 再经过放大、 滤波等处理后送给解调电路进行解调, 还原为二进制数字信号后输出。 简而言之, 红外通信的实质就是对二进制数字信号进行调制与解调, 以便利用红外信道进行传输, 红外通信接口就是针对红外信道的调制解调器。 特点: 红外遥控的特点是不影响周边环境、不干扰其它电器设备。由于其无法穿透墙壁,故不同房间的家用电器可使用通用的遥控器而不会产生相互干扰;电路调试简单,只要按给定电路连接无误,一般不需任何调试即可投入工作;编解码容易,可进行多路遥控。因此,红外遥控在家用电器、室内近距离(小于10米)遥控中得到了广泛的应用。
3、红外编码原理
NEC编码原理(还有一种Philips RC5协议) NEC格式的特征: 1:使用38 kHz载波频率 2:引导码间隔是9 ms + 4.5 ms 3:使用16位客户代码 4:使用8位数据代码和8位取反的数据代码 NEC编码的一帧(通常按一下遥控器按钮所发送的数据) 由引导码、 地址码及数据码组成,如下图所示, 把地址码及数据码取反的作用是加强数据的正确性。 NEC 协议通过脉冲串之间的时间间隔来实现信号的调制(英文简写PPM)。逻辑“0”是由0.56ms的38KHZ载波和0.560ms的无 载波间隔组成;逻辑“1”是由0.56ms的38KHZ载波和1.68ms的无载波间隔组成;结束位是0.56ms的38K载波。
二、红外遥控模块程序
1、红外遥控模块头文件
//红外遥控模块头文件
#ifndef __IR_H
#define __IR_H
#include "main.h"
#define IR_TIM TIM2
#define MAX_DATALEN 5
typedef struct{
uint8_t mode;
uint8_t Ir_Data[MAX_DATALEN];
uint16_t Ir_Length;
}IR_DATA_TypeDef;
extern uint8_t IR_code;
uint8_t Ir_RecvAnalysis(void);
#endif
2、红外遥控模块函数实现代码
//红外遥控模块函数实现代码
#include "ir.h"
#define RCKeyNum 17
#define RCIRLength 4
uint8_t IR_key[17] ="123456789*0#+LOR-";
uint8_t RemoteControl_Table[RCKeyNum][RCIRLength] = {
{0x00,0xFF,0x45,0xBA},
{0x00,0xFF,0x46,0xB9},
{0x00,0xFF,0x47,0xB8},
{0x00,0xFF,0x44,0xBB},
{0x00,0xFF,0x40,0xBF},
{0x00,0xFF,0x43,0xBC},
{0x00,0xFF,0x07,0xF8},
{0x00,0xFF,0x15,0xEA},
{0x00,0xFF,0x09,0xF6},
{0x00,0xFF,0x16,0xE9},
{0x00,0xFF,0x19,0xE6},
{0x00,0xFF,0x0D,0xF2},
{0x00,0xFF,0x18,0xE7},
{0x00,0xFF,0x08,0xF7},
{0x00,0xFF,0x1C,0xE3},
{0x00,0xFF,0x5A,0xA5},
{0x00,0xFF,0x52,0xAD},
};
uint16_t ir_buf[1024] = {0};
uint16_t ir_count = 0;
uint16_t ir_flag = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim==&htim2)
{
ir_flag = 1;
Ir_RecvAnalysis(); //接收红外信号
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2 )
{
if(ir_flag == 0)
{
ir_buf[ir_count++] = IR_TIM->CCR2;
__HAL_TIM_SET_COUNTER(&htim2,0);
IR_TIM->CCER ^= (1
uint8_t i=0;
int retn;
// if(buff[0] != RemoteControl_Table[0][0] || buff[1] != RemoteControl_Table[0][1])
if((buff[0]!=0x00) || (buff[1]!=0xFF))
retn = -1;//地址错误
for(i=0; i
retn = i;
break;
}
}
if(i>=RCKeyNum) retn = -2;
return retn;
}
//返回值
//0 解析成功
//1 没有接收完成
//2 引导码错误
//3 前半段数据错误
//4 后半段数据错误
IR_DATA_TypeDef ir = {0};
uint8_t IR_code = 0XFF;
uint8_t Ir_RecvAnalysis(void)
{
uint16_t i = 0;
uint8_t err;
if(ir_flag == 0) return 1;
// for(i=0; i
err = 2;
goto error;
}
for(i=3; i
i++;
if(Time_Range(ir_buf[i],560,200,200))
{
//数据0 0-7 data[0] 8-15 data[1]
//先收到低位保存到低位,也可以反着
ir.Ir_Data[ir.Ir_Length/8] &= ~(1
err = 4;
goto error;
}
}
else{
err = 3;
goto error;
}
}
// for(i=0; i |