NEC红外协议编码,38K红外遥控编码,红外遥控发射接收电路选型设计

NEC为红外遥控最常用的编码,红外载波频率为38KHz,其协议小巧简单,非常适合家电设备的控制。其他的还有 Phillips(RCA)的RC-5RC-6,但那只是IR协议的少数。

本篇博文参照国外博客或论坛资料并汇总:(原链接可能需要翻墙)
NEC协议
红外遥控工具(NEC)
DFU IR协议(NEC)- PDF
NEC红外传输协议 - PDF
带微控制器的NEC协议IR(红外)遥控器

我的有些翻译并不准确,对码文字段的命名可参照:
NEC编码格式(百度文库)

本片仅介绍NEC编码协议的部分,硬件电路设计及选型请见:
38K红外遥控发射与接收电路设计与选型、正向压降、限流电阻、半值角

1. NEC编码方式

NEC协议采用脉冲间隔的方式编码每一位数据,用不同数据位的时间间隔来表示不同的逻辑位。与众多单总线IC的通信方式很相似。

NEC编码的载波频率为38KHz,对应的单脉冲周期约等于26.3us
在这里插入图片描述
每一数据位起始于562.5µs的载波,约为21.25个38 kHz脉冲组成。 脉冲的占空比通常为1/4或1/3,以减少电流消耗:
在这里插入图片描述

1.1 数据位的逻辑0/1

逻辑"0":562.5µs的有效脉冲 + 562.5µs的空闲间隔,总时长为1.125ms
逻辑"1":562.5µs的有效脉冲 + 1.6875ms的空闲间隔,总时长为2.25ms(为逻辑0的一倍)。
在这里插入图片描述

2. 命令帧

命令帧由 起始位 + 地址码 + 地址码反码 + 命令码 + 命令码反码 组成。

2.1 起始位

每个序列均以9ms的脉冲(称为AGC脉冲)(是逻辑数据位使用的脉冲562.5us的16倍)开始。 接下来是4.5毫秒的空闲:(可以理解这一过程是每一帧的起始标志)
在这里插入图片描述

2.2 地址码 + 命令码

起始位之后会传输4个字节共32Bit的数据位,分别是 地址码 + 地址码反码 + 命令码 + 命令码反码。字面上是4个字节,而实际只有2个字节有效,多余的2字节为冗余的反码。一方面可以用于校验是否出错。另一方面,因为总有相同数量的反码的存在,每帧的总消息时长保持恒定

2.3 结束位

结束位为末尾的562.5µs的有效脉冲。

3. 重复码

即使一直按住遥控器上的一个键,命令帧也只会发送一次。 只要按键保持按下状态,就会每110毫秒发送一次重复码。 该重复码的组成为 9ms的AGC脉冲 + 2.25ms的空闲间隔 + 560µs的脉冲

3.1 重复码组成

在这里插入图片描述

3.2 重复码发送时序

在这里插入图片描述

4. 扩展的NEC协议

NEC协议的使用如此广泛,以至于所有可能的地址都会很快被用完。 通过牺牲地址冗余,地址范围的值可以从256个扩展到65536个。 这样,地址范围就能从8位扩展到16位,而无需更改协议的任何其他属性。

通过这种方式扩展地址范围总的消息时间不再恒定,只取决于消息中1和0的总数。 如果要使总的消息时间保持恒定,则必须确保地址字段中的逻辑1数目为8个(这同样表示逻辑0的数目也为8个)。 这会将不同地址的最大数量减少到大约13000个。

命令冗余仍然保留。 因此,每个地址仍可以处理256个不同的命令。

5. 38K红外发射接收电路选型设计

本片仅介绍NEC编码协议的部分,硬件电路设计及选型请见:
38K红外遥控发射与接收电路设计与选型、正向压降、限流电阻、半值角

6. 注意事项:电平取反

格外注意的是:VS1838PC638IRM-5638436380038这些38K红外接收管的输出方式为开漏,故与上文的时序为反相,coding的代码内要记得取反

并且因为OUTPUT引脚是开漏输出,需要外置上拉电阻,或者将MCU的GPIO配置为上拉输入

### 实现NEC红外遥控协议编程 #### 解码部分 为了实现在STM32上对接收到的NEC红外信号进行解码,需要理解NEC帧格式以及如何编写相应的接收端程序[^1]。NEC协议规定了一种特定的时间间隔模式用来表示逻辑0和逻辑1,在接收到这些脉冲之后,通过测量时间长度来判断所代表的数据位。 下面是一个简单的解码函数示例: ```c void IR_Decode(void){ uint8_t i; uint16_t data = 0; //等待9ms引导脉冲 while(Timer_GetCounter() < 9); Timer_Reset(); //跳过4.5ms低电平间隙 while(!IR_PIN && (Timer_GetCounter()<4.5)); Timer_Reset(); for(i=0; i<32; ++i){ //等待0.56ms高电平 while(IR_PIN && (Timer_GetCounter()<0.56)); Timer_Reset(); //检测下一个下降沿到来之前计数值决定高低位 if((Timer_GetCounter()>1.6)&&(Timer_GetCounter()<2.3)){ data <<= 1; data |= 1; }else{ data <<= 1; } //等待相应宽度的低电平结束 while(!IR_PIN); Timer_Reset(); } //处理得到的数据... } ``` 此代码片段展示了基本的解码流程,实际应用中可能还需要加入更多的错误校验机制以提高可靠性[^2]。 #### 发送部分 对于发送方而言,则是要按照NEC规定的编码方式生成对应的载波调制后的PWM波形并输出到指定引脚上去[^4]。这里给出一段简化版的例子用于说明怎样构建这样一个发送过程: ```c #define CARRIER_FREQ 38000 /* 载频 */ #define BIT_TIME_0 562 /* '0' bit duration(us) */ #define BIT_TIME_1 1687 /* '1' bit duration(us) */ void Send_NEC_Code(uint16_t address, uint16_t command){ GPIO_InitTypeDef GPIO_InitStruct={0}; TIM_OCInitTypeDef sConfigOC ={0}; __HAL_RCC_TIMx_CLK_ENABLE(); //使能定时器时钟 __HAL_RCC_GPIOx_CLK_ENABLE(); //使能GPIO时钟 HAL_Delay(9); //9ms引导脉冲 PWM_Start(CARRIER_FREQ,BIT_TIME_0*2); //开启PWM输出 HAL_Delay(BIT_TIME_0 * 2); //传输地址字节 for(int i=0;i<8;++i){ if(address & (1<<i)) Send_Bit_High(); else Send_Bit_Low(); } //传输反向地址字节 for(int i=0;i<8;++i){ if(!(address & (1<<i))) Send_Bit_High(); else Send_Bit_Low(); } //传输命令字节 for(int i=0;i<8;++i){ if(command & (1<<i)) Send_Bit_High(); else Send_Bit_Low(); } //传输反向命令字节 for(int i=0;i<8;++i){ if(!(command & (1<<i))) Send_Bit_High(); else Send_Bit_Low(); } PWM_Stop(); //停止PWM输出 } //辅助函数定义 static void Send_Bit_High(){ PWM_Start(CARRIER_FREQ,BIT_TIME_1); HAL_Delay(BIT_TIME_1); } static void Send_Bit_Low(){ PWM_Start(CARRIER_FREQ,BIT_TIME_0); HAL_Delay(BIT_TIME_0); } ``` 上述代码实现了完整的NEC数据包发送操作,包括起始标志、地址及其补码、命令及其补码四个组成部分,并且利用了硬件PWM模块来进行精确的载波频率控制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值