一、红外遥控简介
红外遥控,顾名思义,就是利用红外线实现遥控。这里就不单独对红外线做介绍了,红外线的波长再可见光范围外,所以人眼是看不到的。红外遥控的原理就是利用红外线进行通讯,比如生活中常用的电视遥控器,空调遥控器等,大多都是红外通讯实现的遥控功能。
二、红外遥控的原理
红外遥控是一种非接触,无线控制技术。具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等特点。红外遥控系统一般有红外发射装置和红外接收设备两大部分组成。
红外发射装置就是我们常见的遥控器,由键盘电路,红外编码电路,电源电路和红外发射电路组成。
红外接收设备是由红外接收电路,红外解码,电源和应用电路组成。红外接收装置有三个引脚,VDD,GND和数据输出VOUT。通常正对接收头凸起处看,从左到右引脚顺序为VOUT,GND,VDD
通常红外遥控为了提高抗干扰性能和降低电源消耗,红外遥控器常用载波的方式传送二进制编码,常用的载波频率为38kHz,这是由发射端所使用的455kHz晶振来决定的。在发射端要对晶振进行整数分频,分频系数一般取12,所以为38kHz。
也有一些遥控系统采用36kHz、40 kHz、56 kHz等,一般由发射端晶振的振荡频率来决定。所以,通常的红外遥控器是将遥控信号(二进制脉冲码) 调制在38KHz的载波上,经缓冲放大后送至红外发光二极管,转化为红外信号发射出去的。
三、二进制脉冲编码
二进制脉冲码的形式有多种,其中最为常用的是NEC Protocol 的PWM码(脉冲宽度调制)和 Philips RC-5 Protoco 的 PPM码(脉冲位置调制码,脉冲串之间的时间间隔来实现信号调制)。如果要开发红外接收设备,一定要知道红外遥控器的编码方式和载波频率,
才可以选取一体化红外接收头和制定解码方案。这里针对NEC编码形式做一个详细介绍。NEC编码形式有以下特点
8 位地址和 8 位指令长度
地址和命令 2次传输(确保可靠性)
PWM 脉冲位置调制,以发射红外载波的占空比代表“ 0”和“1”
载波频率为 38Khz
位时间为 1.125ms 或 2.25ms
3.1 NEC码的位定义
一个脉冲对应 560us 的连续载波,一个逻辑1传输需要 2.25ms(560us脉冲+1680us 低电平) ,一个逻辑 0的传输需要 1.125ms (560us脉冲+560us 低电平)。而红外接收头在收到脉冲的时候为低电平,在没有脉冲的时候为高电平,这样,
我们在接收头端收到的信号为: 逻辑 1应该是 560us 低+1680us 高,逻辑 0 应该是 560us 低+560us 高。所以可以通过计算高电平时间判断接收到的数据是0还是1。NEC码位定义时序图如下
特别标注一下,上图逻辑0和逻辑1的时序图对应的是接收端的时序图。
3.2 NEC遥控指令的数据格式
NEC遥控指令的数据格式为:引导码、地址码、地址反码、控制码控制反码。引导码由一个 9ms 的低电平和一个 4.5ms 的高电平组成地址码、地址反码、控制码、控制反码均是8 位数据格式。按照低位在前,高位在后的顺序发送。
采用反码是为了增加传输的可靠性 (可用于校验)。数据格式如下
特别标注一下,上图为发送端的时序图。
NEC码还规定了连发码(由 9ms 低电平+2.5m 高电平+0.5ms 低电平+97.94ms 高电平组成),如果在一帧数据发送完毕之后,红外遥控器按键仍然没有放开,则发射连发码,可以通过统计连发码的次数来标记按键按下的长短或次数。
四、红外遥控程序设计思路
红外发射装置只需要按键按下即可产生红外信号,我们只需要针对红外接收设备编写程序即可。上面介绍了,红外接收设备在收到脉冲的时候为低电平,在没有脉冲的时候为高电平。根据“0”和“1”的时序图可知,我们只需要监测红外接收
设备的数据输出引脚的高电平持续时间就可以判断接收到的是“0”还是“1”。
另外,没有按键按下时,也就是没有发红外信号,没有脉冲,红外接收设备的数据输出引脚一直为高电平。只有接收到脉冲时,说明有按键按下,此时红外接收设备的数据输出引脚为低电平。因此,可以利用外部中断的下降沿出发来判断是否有
按键按下,在中断中测量高电平持续时间来判断接收到的是“0”还是“1”。
五、红外遥控程序设计
5.1 红外遥控初始化程序
需要初始化GPIO和外部中断,GPIO配置为上拉输入模式
/* *============================================================================== *函数名称:Drv_Hw_Init *函数功能:初始化红外遥控模块 *输入参数:无 *返回值:无 *备 注:红外端口初始化函数,时钟端口及外部中断初始化 *============================================================================== */ void Drv_Hw_Init (void) { // 结构体定义 GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; // 开启时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE); // 配置GPIO结构体 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11; // 红外接收 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; // 上拉输入模式 GPIO_Init(GPIOB,&GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11); // 选择GPIO管脚用作外部中断线路 EXTI_ClearITPendingBit(EXTI_Line11); // 配置外部中断 EXTI_InitStructure.EXTI_Line=EXTI_Line11; EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd=ENABLE; EXTI_Init(&EXTI_InitStructure); // 配置NVIC结构体 NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 抢占优先级为0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 响应优先级为1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能 NVIC_Init(&NVIC_InitStructure); }
5.2 记录高电平持续时间函数
利用记录延时次数的方法测量高电平持续时间
/* *============================================================================== *函数名称:Drv_Hw_RecordHightTime *函数功能:记录高电平持续时间并返回 *输入参数:无 *返回值:t:高电平持续时间 *备 注:无 *============================================================================== */ u8 Drv_Hw_RecordHightTime (void) { u8 t = 0; while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 1) // 高电平 { t ++; delay_us(20); if(t >= 250) { return t; // 超时溢出 } } return t; }
5.3 中断服务函数
中断服务函数中接收数据,接收完成后对应的接收完成标志位置1
/* *============================================================================== *函数名称:EXTI15_10_IRQHandler *函数功能:外部中断服务函数 *输入参数:无 *返回值:无 *备 注:无 *============================================================================== */ void EXTI15_10_IRQHandler(void) // 红外遥控外部中断 { u8 Tim = 0,Ok = 0,Data,Num = 0; while(1) { if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 1) { Tim = Drv_Hw_RecordHightTime(); //获得此次高电平时间 if(Tim>=250) { break; // 不是有用的信号 } if(Tim >= 200 && Tim < 250) { Ok = 1; // 收到起始信号 } else if(Tim >= 60 && Tim < 90) { Data = 1; // 收到数据 1 } else if(Tim >= 10 && Tim < 50) { Data = 0; // 收到数据 0 } if(Ok == 1) { hw_jsm <<= 1; hw_jsm += Data; // 接收完成 if(Num >= 32) { hw_jsbz = 1; break; } } Num ++; } } // 清除中断标志位 EXTI_ClearITPendingBit(EXTI_Line11); }
5.4 读取键值
判断键盘上按下的是哪个按键。不同的遥控器,按键对应的红外编码可能不同,可以通过串口打印接收到的键值的方法来读出每一个按键的键值。
/* *============================================================================== *函数名称:Med_Hw_ReadKeyValue *函数功能:读取键值 *输入参数:无 *返回值:红外键值 *备 注:每一个键值是测试出来的,不同遥控器键值可能不同 *============================================================================== */ u8 Med_Hw_ReadKeyValue (void) { if(hw_jsm == 0x00FF9867) { return 0; } else if(hw_jsm == 0x00FFA25D) { return 1; } else if(hw_jsm == 0x00FF629D) { return 2; } else if(hw_jsm == 0x00FFE21D) { return 3; } else if(hw_jsm == 0x00FF22DD) { return 4; } else if(hw_jsm == 0x00FF02FD) { return 5; } else if(hw_jsm == 0x00FFC23D) { return 6; } else if(hw_jsm == 0x00FFE01F) { return 7; } else if(hw_jsm == 0x00FFA857) { return 8; } else if(hw_jsm == 0x00FF906F) { return 9; } else if(hw_jsm == 0x00FF6897) // 按键*按下 { return 10; } else if(hw_jsm == 0x00FFB04F) // 按键#按下 { return 11; } else if(hw_jsm == 0x00FF38C7) // 按键OK按下 { return 12; } else if(hw_jsm == 0x00FF18E7) // 按键"上"按下 { return 13; } else if(hw_jsm == 0x00FF4AB5) // 按键"下"按下 { return 14; } else if(hw_jsm == 0x00FF10EF) // 按键"左"按下 { return 15; } else if(hw_jsm == 0x00FF5AA5) // 按键"右"按下 { return 16; } return 17; }
5.5 参数定义
定义了以下两个参数
u32 hw_jsm; // 定义一个32位数据变量,保存接收码 u8 hw_jsbz; // 定义一个8位数据的变量,用于指示接收标志
六、应用实例
利用红外遥控控制LED的亮灭,按下“1”点亮,按下“0”熄灭。每次执行完对应按键的内容后,需要清除接收完成标志位和接收码。main函数如下
u8 gHwKeyValue = 0; // 红外键值 int main(void) { Med_Mcu_Iint(); // 系统初始化 while(1) { if (hw_jsbz == 1) { // 获取红外键值 gHwKeyValue = Med_Hw_ReadKeyValue(); // 按下按键“1” if (gHwKeyValue == 1) { // 点亮LED Med_Led_StateCtrl(LED1,LED_ON); } // 按下按键“0” if (gHwKeyValue == 0) { // 熄灭LED Med_Led_StateCtrl(LED1,LED_OFF); } hw_jsbz = 0; // 清除接收完成标志位 hw_jsm = 0; // 清零接收码 } } }
————————————————
版权声明:本文为CSDN博主「二土电子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45217381/article/details/131425665