0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于STM32F103C8T6对红外遥控信号解码 实现HX1838接收头接收数据

jf_88434166 来源:jf_88434166 作者:jf_88434166 2026-01-30 19:53 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、红外遥控简介

红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是家用电器广泛采用,并越来越多的应用到计算机系统中。由于红外线遥控不具有像无线电遥控那样穿过障碍物去控制被控对象的能力,所以,在设计红外线遥控器时,不必要像无线电遥控器那样,每套(发射器和接收器)要有不同的遥控频率或编码(否则就会隔墙控制或干扰邻居的家用电器),所以同类产品的红外线遥控器,可以有相同的遥控频率或编码,而不会出现遥控信号“串门”的情况。这对于大批量生产以及在家用电器上普及红外线遥控提供了极大的方便。由于红外线为不可见光,因此对环境影响很小,再由红外光波动波长远小于无线电波的波长,所以红外线遥控不会影响其他家用电器,也不会影响临近的无线电设备。

HW1.jpg

二、红外遥控特性

红外遥控的情景中,必定会有一个红外发射端和红外接收端。要使两者通信成功,收/发红外波长与载波频率需一致,在这里波长就是940nm,载波频率就是38kHz。
红外发射管也是属于二极管类,红外发射电路通常使用三极管控制红外发射器的导通或者截至,在导通的时候,红外发射管会发射出红外光,反之,就不会发射出红外光。虽然用肉眼看不到红外光,但是可以借助手机摄像头就能看到红外光。但是红外接收管的特性是当接收到红外载波信号时,OUT引脚输出低电平;假如没有接收到红外载波信号时,OUT引脚输出高电平。
红外载波信号其实就是由一个个红外载波周期组成。在频率为38KHz下,红外载波周期约等于26.3us(1s/38KHz≈26.3us)。在一个红外载波发射周期里,发射红外光时间8.77us和不发射红外光17.53us,发射红外光的占空比一般为1/3。相对的,整个周期内不发射红外光,就是载波不发射周期。在红外遥控器内已经把载波和不载波信号处理好,只需要做的就是识别遥控器按键发射出的信号,信号也是遵循某种协议的。

三、红外编解码协议介绍

红外遥控的编码方式目前广泛使用的是:PWM(脉冲宽度调制)的NEC协议和PhilipsPPM(脉冲位置调制)的RC-5协议的。以NEC协议为例,其特征如下:

1、8位地址和8位指令长度;
2、地址和命令2次传输(确保可靠性);
3、PWM脉冲位置调制,以发射红外载波的占空比代表“0”和“1”;
4、载波频率为38Khz;
5、位时间为1.125ms或2.25ms;

在NEC协议中,如何为协议中的数据‘0’或者‘1’?这里分开红外接收器和红外发射器。
红外发射器:
发送协议数据‘0’=发射载波信号560us+不发射载波信号560us
发送协议数据‘1’=发射载波信号560us+不发射载波信号1680us
红外发射器的位定义如下图所示:

红外接收器:
接收到协议数据‘0’=560us低电平+560us高电平
接收到协议数据‘1’=560us低电平+1680us高电平
红外接收器的位定义如下图所示:

NEC遥控指令的数据格式为:同步码头、地址码、地址反码、控制码、控制反码。同步码由一个9ms的低电平和一个4.5ms的高电平组成,地址码、地址反码、控制码、控制反码均是8位数据格式。按照低位在前,高位在后的顺序发送。采用反码是为了增加传输的可靠性 (可用于校验)。除了上面的数据格式,NEC还规定了一个连发码(由9ms低电平+2.5ms高电平+0.56ms低电平+97.94ms高电平组成),如果在一帧数据发送完毕之后,按键仍然没有放开,则发射重复码,即连发码可以通过统计连发码的次数来标记按键按下的长短/次数。红外NEC协议编码如图所示:

当遥控器的按键按下时,从红外接收头端收到的波形如图所示,从图中可以看到,其地址码为0,控制码为21(正确解码后00010101)。

四、STM32F103解码接收红外信号

准备工作

STM32F103C8T6开发板,940nm波长 38kHz载波频率的红外遥控器,HX1838接收头,OLED屏幕

接线说明

STM32F103C8T6HX1838接收头
3.3V接收头的+ 和 OLED的VCC
GND共地
PA0S
PB8OLED->SCL
PB9OLED->SDA

代码示例

HX1838.c

#include "IR.h"
#include "timer.h"

// 遥控器接收状态
//[7]:收到了引导码标志
//[6]:得到了一个按键的所有信息
//[5]:保留
//[4]:标记上升沿是否已经被捕获
//[3:0]:溢出计时器
uint8_t RmtSta = 0;
uint16_t Dval;		// 下降沿时计数器的值
uint32_t RmtRec = 0; // 红外接收到的数据
uint8_t RmtCnt = 0;	// 按键按下的次数

void IR_Init(void)
{
	Timer_Init();
}

void TIM2_IRQHandler(void)
{
 	if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
	{
		if (RmtSta & 0x80) // 上次有数据被接收到了
		{
			RmtSta &= ~0X10; // 取消上升沿已经被捕获标记
			if ((RmtSta & 0X0F) == 0X00)
				RmtSta |= 1 < < 6; // 标记已经完成一次按键的键值信息采集
			if ((RmtSta & 0X0F) < 14)
				RmtSta++;
			else
			{
				RmtSta &= ~(1 < < 7); // 清空引导标识
				RmtSta &= 0XF0;		 // 清空计数器
			}
		}
	}
	
	if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
	{
		if (RDATA) // 上升沿捕获
		{
			TIM_OC1PolarityConfig(TIM2, TIM_ICPolarity_Falling); // CC4P=1	设置为下降沿捕获
			TIM_SetCounter(TIM2, 0);							 // 清空定时器
			RmtSta |= 0X10;										 // 标记上升沿已经被捕获
		}
		else // 下降沿捕获
		{
			Dval = TIM_GetCapture1(TIM2);						// 读取CCR4也可以清CC4IF标志位
			TIM_OC1PolarityConfig(TIM2, TIM_ICPolarity_Rising); // CC4P=0	设置为上升沿捕获
			if (RmtSta & 0X10)									// 完成一次高电平捕获
			{
				if (RmtSta & 0X80) // 接收到了引导码
				{
 
					if (Dval > 300 && Dval < 800) // 560为标准值,560us
					{
						RmtRec < <= 1; // 左移一位.
						RmtRec |= 0;  // 接收到0
					}
					else if (Dval > 1400 && Dval < 1800) // 1680为标准值,1680us
					{
						RmtRec < <= 1; // 左移一位.
						RmtRec |= 1;  // 接收到1
					}
					else if (Dval > 2200 && Dval < 2600) // 得到按键键值增加的信息 2500为标准值2.5ms
					{
						RmtCnt++;		// 按键次数增加1次
						RmtSta &= 0XF0; // 清空计时器
					}
				}
				else if (Dval > 4200 && Dval < 4700) // 4500为标准值4.5ms
				{
					RmtSta |= 1 < < 7; // 标记成功接收到了引导码
					RmtCnt = 0;		  // 清除按键次数计数器
				}
			}
			RmtSta &= ~(1 < < 4);
		}
	}
	TIM_ClearITPendingBit(TIM2, TIM_IT_Update | TIM_IT_CC1);
}
 
// 处理红外键盘
// 返回值:
//	 0,没有任何按键按下
// 其他,按下的按键键值.
uint8_t Remote_Scan(void)
{
	uint8_t sta = 0;
	uint8_t t1, t2;
	if (RmtSta & (1 < < 6)) // 得到一个按键的所有信息了
	{
		t1 = RmtRec > > 24;						// 得到地址码
		t2 = (RmtRec > > 16) & 0xff;				// 得到地址反码
		if ((t1 == (uint8_t)~t2) && t1 == REMOTE_ID) // 检验遥控识别码(ID)及地址
		{
			t1 = RmtRec > > 8;
			t2 = RmtRec;
			if (t1 == (uint8_t)~t2)
				sta = t1; // 键值正确
		}

		RmtSta &= ~(1 < < 6); // 清除接收到有效按键标识
		RmtCnt = 0;			 // 清除按键次数计数器
	}
	return sta;
}

main.c

#include "stm32f10x.h"                  // Device header
#include "oled.h" 
#include "delay.h"  
#include "IR.h" 

uint8_t IR_Address;
uint8_t IR_Command;
uint8_t IR_Count;  
uint8_t *str = 0;
uint8_t key;
	
int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	OLED_Init();
	IR_Init();
	
	OLED_ShowString(1,1,"ADDR HEX CMD NUM");
	OLED_ShowString(2,1,"00   00   0  000");
	
	while(1)
	{
		IR_Address = (RmtRec > > 24) & 0xFF;
        IR_Command = (RmtRec > > 8)  & 0xFF;
		
		key = Remote_Scan();
        if (key) {
            switch (key) {
                case IR_1:
                    str = "1";
                    break;
                case IR_2:
                    str = "2";
                    break;
                case IR_3: 
                    str = "3";
                    break;
                case IR_4: 
                    str = "4";
                    break;
                case IR_5: 
                    str = "5";
                    break;
                case IR_6: 
                    str = "6";
                    break;
                case IR_7: 
                    str = "7";
                    break;
                case IR_8: 
                    str = "8";
                    break;
                case IR_9: 
                    str = "9";
                    break;
                case IR_0:
                    str = "0";
                    break;
                case IR_SP1:
                    str = "*";
                    break;
                case IR_SP2:
                    str = "#";
                    break;
                case IR_UP:			//"↑"
                    IR_Count++;
                    break;
                case IR_LEFT:		//"←"
					//
                    break;
                case IR_DOWN:		//"↓"
                    IR_Count--;
                    break;
                case IR_RIGHT:		//"→"
					//
                    break;
                case IR_CONFIRM:
                    str = "OK ";
                    break;
                default:
                    str = "EMOURE";
                    break;
            }
			
			OLED_ShowHexNum(2, 1,  IR_Address, 2);
			OLED_ShowHexNum(2, 6,  IR_Command, 2);
			OLED_ShowString(2,12," ");
			OLED_ShowString(2,11,str);
			OLED_ShowNum(2, 14, IR_Count,   3);
        }
		Delay_ms(10);
	}
}

效果展示

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 红外遥控
    +关注

    关注

    22

    文章

    353

    浏览量

    47799
  • STM32F103C8T6
    +关注

    关注

    116

    文章

    166

    浏览量

    89601
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    基于STM32与机智云的智能家居系统(完整项目)

    显示、ESP8266-01S接入云端,实现手机APP远程监测、模式切换、手动/自动控制与报警提醒。本文设计基于STM32F103C8T6与机智云的智能家居控制系统
    的头像 发表于 05-15 18:04 194次阅读
    基于<b class='flag-5'>STM32</b>与机智云的智能家居系统(完整项目)

    Vishay红外接收器模块:优化短脉冲遥控系统设计

    Vishay红外接收器模块:优化短脉冲遥控系统设计 在电子设备的遥控系统设计中,红外接收器模块起着至关重要的作用。Vishay Semiconductors推出的TSOP531、TSO
    的头像 发表于 05-12 17:10 414次阅读

    红外接收:不可或缺的光电感知核心

    随着IoT和消费电子发展,红外接收需求稳步增长,低功耗、高集成度、强抗干扰是未来技术演进方向。洲光源推出的红外接收产品,基于成熟的设计与验证,将
    的头像 发表于 04-23 16:48 407次阅读
    <b class='flag-5'>红外接收</b><b class='flag-5'>头</b>:不可或缺的光电感知核心

    基于STM32F103C8T6的智能超声波测距尺:从原理到代码的完整实现

    连接、时序逻辑以及核心代码的实现。 一、硬件连接与选型 核心硬件: - MCU: STM32F103C8T6 (蓝 pill 最小系统板) - 传感器: HC-SR04 超声波模块 - 显示
    发表于 02-28 02:21

    STM32驱动串口屏,STM32F103C8T6串口发送指令控制HMI串口屏

    仅是一部分常用的基础指令,更多更仔细的指令或者函数可以访问陶晶驰资料官网。 硬件和接线 硬件需要一块STM32F103C8T6的开发板,杜邦线诺干,2.4寸串口屏一块 接线 串口屏 STM32 +5V 5V TX PA10 RX PA9 GND GND 实验前准备 准备前
    的头像 发表于 02-10 17:07 735次阅读
    <b class='flag-5'>STM32</b>驱动串口屏,<b class='flag-5'>STM32F103C8T6</b>串口发送指令控制HMI串口屏

    f103c8t6使用adc采样时程序无法正常工作怎么解决?

    我在学习使用stm32f103c8t6的adc的使用时遇到了这个问题。 是按照教程一步一步操作的:这是教程地址:https://blog.csdn.net/WTF___000/article
    发表于 10-13 07:25

    stm32f103c8t6 PWM设置后不生效是怎么回事?

    参照这这篇文档 https://blog.csdn.net/2301_80066900/article/details/144024976 芯片f103c8t6,rt版本4.1.1, 定时器TIM2
    发表于 09-10 07:26

    CherryUSB +STM32F103C8 example usb cdc device不识别是怎么回事?

    stm32f103c8t6 配置cdc,使用cubeMX 配置生成xxx_msp.c 为什么 放开 CONFIG_USBDEV_SETUP_LOG_PRINT 发现 usb 中断 一直未能进入 ____usbd_event_ep0_setup_complete_hand
    发表于 09-10 07:03

    STM32项目分享:智能厨房安全系统(机智云)

    01—项目简介1.功能详解STM32智能厨房安全系统(机智云)功能如下:STM32F103C8T6单片机作为主控芯片检测功能:检测环
    的头像 发表于 09-10 00:01 1402次阅读
    <b class='flag-5'>STM32</b>项目分享:智能厨房安全系统(机智云)

    stm32f103c8t6读不到完整的MC6C遥控器Uart数据帧怎么办

    我用stm32c8t6最小系统板做飞控,时钟为72MHz,在使用Usart通信尝试读取sbus信号时,发现只能读取到16.16.16.16.16.16226.181.117.91.56.13为循环
    发表于 08-13 09:29

    STM32N6的CSI接收mipi信号时,进入数据线错误控制中断,为什么?

    使用模拟高清解码器芯片XS9950,向stm32n6传输CSI信号的时候,stm32n6发生CSI的Error control on data line中断。此根据参考手册,此中断指示
    发表于 07-28 06:36

    STM32项目分享:智能语音台灯(机智云)

    01—项目简介1.功能详解STM32智能语音台灯(机智云)功能如下:STM32F103C8T6单片机作为主控单元按键切换模式,支持自
    的头像 发表于 07-24 18:03 1966次阅读
    <b class='flag-5'>STM32</b>项目分享:智能语音台灯(机智云)

    STM32F103c8上做DLQR最优控制算法的C编程资料

    这是我近期做的一个项目--基于STM32F103c8的DLQR控制算法的C编程,涉及DLQR最优控制算法、嵌入式STM32F103编程、CMSIS-DSP库使用。    附有完整的程序。
    发表于 07-23 15:30 0次下载

    CH32F103C8T6核心板三种程序下载方式简介

    CH32F103C8T6核心板,通过USB转串口方式、USB直连方式、SWD方式下载应用程序
    的头像 发表于 06-09 09:38 1373次阅读
    CH32<b class='flag-5'>F103C8T6</b>核心板三种程序下载方式简介

    STM32F103 I2C从机接收数据的问题

    我使用STM32F103做一个I2C从机接收数据的功能,通过查阅函数手册,使用了2种方法 方法1: 1、调用HAL_I2C_EnableLi
    发表于 06-06 12:29