使用STM32外部中断实现红外接收器

一、红外遥控的原理

红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传 输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是 家用电器广泛采用,并越来越多的应用到计算机系统中。 红外遥控通信系统一般由红外发射装置和红外接收设备两大部分组成

(1)
红外发射装置

红外发射装置,也就是通常我们说的红外遥控器是由键盘电路、红外编码电路、电源电路和红外发射电路组成。

通常红外遥控为了提高抗干扰性能和降低电源消耗,红外遥控器常用 载波的方式传送二进制编码,常用的载波频率为38kHz,这是由发射端所使用的455kHz晶振来决定的。在发射端要对晶振进行整数分频,分频系数一般取12,所以455kHz÷12≈37.9kHz≈38kHz。也有一些遥控系统采用36kHz、40 kHz、56 kHz等,一般由发射端晶振的振荡频率来决定。所以,通常的红外遥控器是将遥控信号(二进制脉冲码)调制在38KHz的载波上,经缓冲放大后送至红外发光二极管,转化为红外信号发射出去的

二进制脉冲码的形式有多种,其中最为常用的是NEC Protocol 的PWM码(脉冲宽度调制)和 Philips RC-5 Protocol 的 PPM码(脉冲位置调制码,脉冲串之间的时间间隔来实现信号调制)。如果要开发红外接收设备,一定要知道红外遥控器的编码方式和载波频率,我们才可以选取一体化红外接收头和制定解码方案。我们配套的红外遥控器使用的是NEC协议,其特征如下:

1、8 位地址和 8 位指令长度;

2、地址和命令 2 次传输(确保可靠性);

3、 PWM 脉冲位置调制,以发射红外载波的占空比代表“ 0”和“ 1”;

4、载波频率为 38Khz;

5、位时间为 1.125ms 或 2.25ms;

二、NEC码的位定义

一个脉冲对应 560us 的连续载波,一个逻辑 1 传输需要 2.25ms( 560us脉冲+1680us 低电平),一个逻辑 0 的传输需要 1.125ms(560us 脉冲+560us 低电平)。而红外接收头在收到脉冲的时候为低电平,在没有脉冲的时候为高电平,这样,我们在接收头端收到的信号为:逻辑 1 应该是 560us 低+1680us 高,逻辑 0 应该是 560us 低+560us 高。所以可以通过计算高电平时间判断接收到的数据是0还是1。

NEC码位定义时序图如图:

简单来说就是,红外发送器这边,发送脉冲信号时是高电平,发送的不是脉冲信号就是低电平,红外接收器这边,接收脉冲信号是低电平,接收的不是脉冲信号就是高电平

由于红外接收头在没有脉冲的时候为高电平,当收到脉冲的时候为低电平,所以可以通过外部中断的下降沿触发中断,在中断内通过计算高 电平时间来判断接收到的数据是0还是1。

NEC 遥控指令的数据格式为:引导码、地址码、地址反码、控制码、控制反码。引导码由一9ms 的低电平和一个 4.5ms 的高电平组成,地址码、地址反码、控制码、控制反码均是8 位数据格式。按照低位在前,高位在后的顺序发送。采用反码是为了增加传输的可靠性(可用于校验)。数据格式如下:

NEC码还规定了连发码(由 9ms 低电平+2.5m 高电平+0.56ms 低电平 +97.94ms 高电平组成),如果在一帧数据发送完毕之后,红外遥控器按键仍然没有放开,则发射连发码,可以通过统计连发码的次数来标记按键按下的长短或次数。

代码实现:(这里使用的是stm32f103rct6单片机)

u32 inf_val;
u8 inf_flag;
void Infrared_Remote_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	EXTI_InitTypeDef  EXTI_InitStruct;
	NVIC_InitTypeDef  NVIC_InitStruct;
	/*1、打开外设时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);

	/*2、配置GPIO*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
	GPIO_Init(GPIOB, &GPIO_InitStruct);

	/*3、中断线的映射*/
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource15);

	/*4、配置EXTI*/
	EXTI_InitStruct.EXTI_Line = EXTI_Line15;
	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_InitStruct.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStruct);

	/*5、配置NVIC*/
	NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);
	
	EXTI_ClearITPendingBit(EXTI_Line15);
}

u8 Infrared_Remote_Delay(void)
{
	u8 tim = 0;
	while(PBin(15))
	{
		delay_us(50);
		tim++;
		if(tim == 255)
		{
			return tim;
		}
	}
	return tim;
}

void EXTI15_10_IRQHandler(void)
{
	u8 high_time,flag,data = 0,n = 0;
	while(1)
	{
		if(PBin(15))
		{
			high_time = Infrared_Remote_Delay();
			if(high_time == 255)
				break;
			if(high_time > 70 && high_time < 100)//收到引导码
			{
				flag = 1;
			}
			else if(high_time > 6 && high_time < 12)//收到0
			{
				data = 0;
			}
			else if(high_time > 30 && high_time < 36)//收到1
			{
				data = 1;
			}
			if(flag)//如果收到引导码
			{
				inf_val <<= 1;
				inf_val += data;
				
				if(n == 32)//因为inf_val是32位的
				{
					inf_flag = 1;
					break;
				}
			}
			n++;
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line15);
}

作者:钜锋王老师

物联沃分享整理
物联沃-IOTWORD物联网 » 使用STM32外部中断实现红外接收器

发表评论