STM32学习笔记一一红外遥控

前言:

为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长。

在这里插入图片描述


1. 简述

红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,低功耗,低成本。

红外遥控的编码方式目前广泛使用的是: PWM (脉冲宽度调制)的 NEC 协议和 Philips PPM(脉冲位置调制) 的 RC-5 协议的。

1.1 NEC 协议定义

NEC 码的位定义: 一个脉冲对应 560us 的连续载波,一个逻辑 1 传输需要2.25ms(560us 脉冲+1680us 低电平),一个逻辑 0 的传输需要1.125ms(560us 脉冲+560us 低电平)。而遥控接收头在收到脉冲的时候为低电平,在没有脉冲的时候为高电平,这样,我们在接收头端收到的信号为:逻辑 1 应该是 560us 低+1680us 高,逻辑 0 应该是 560us 低 + 560us 高。

发射端逻辑:
在这里插入图片描述

在这里插入图片描述

遥控接收头逻辑:

在这里插入图片描述

在这里插入图片描述

1.2 NEC 协议特点

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

1.3 NEC 遥控指令的数据格式

在这里插入图片描述

采用反码是为了增加传输的可靠性。NEC 码规定的连发码(由 9ms 低电平+2.5m 高电平+0.56ms 低电平+97.94ms 高电平组成),如果在一帧数据发送完毕之后,按键仍然没有放开,则发射重复码,即连发码。

2. 软件实现

上面我们基本了解了 NEC 格式的红外发码和收码的格式,就可以根据通信的协议来完成对应的程序。

程序逻辑:

在这里插入图片描述

2.1 初始化

void Remote_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_ICInitTypeDef TIM_ICInitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;	//下拉输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	GPIO_SetBits(GPIOA,GPIO_Pin_1);
	
	TIM_TimeBaseStructure.TIM_Period = 10000;//设定自动重装值,10ms溢出
	TIM_TimeBaseStructure.TIM_Prescaler = (72-1);//预分频器,1MHz的计数频率,1us加一
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分割
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
	TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);
	
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;//IC2映射到TI5
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿捕获
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//不分频
	TIM_ICInitStructure.TIM_ICFilter = 0x03;//IC4F=0011,输入滤波器8个定时器时钟周期滤波
	TIM_ICInit(TIM5,&TIM_ICInitStructure);//初始化定时器输入捕获通道
	TIM_Cmd(TIM5,ENABLE);//使能定时器5
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;//TIM5中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//从优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC2,ENABLE);//允许更新中断,允许CC2IE捕获中断
}

2.2 中断捕获

u8 RmtSta=0;
u16 Dval;
u32 RmtRec=0;
u8 RmtCnt=0;
void TIM5_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM5,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(TIM5,TIM_IT_CC2)!=RESET)
	{
		if(RDATA)//上升沿已经捕获
		{
			TIM_OC2PolarityConfig(TIM5,TIM_ICPolarity_Falling);//CC1P=1,设置为下降沿捕获
			TIM_SetCounter(TIM5,0);//清空定时器数值
			RmtSta |= 0x10;//标记上升沿已经被捕获
		}
		else
		{
			Dval = TIM_GetCapture2(TIM5);//读取CCR1的值
			TIM_OC2PolarityConfig(TIM5,TIM_ICPolarity_Rising);//设置为上升沿捕获
			if(RmtSta&0x10)
			{
				if(RmtSta&0x80)//接收到引导码
				{
					if(Dval>300&&Dval<800)//高电平为560us
					{
						RmtRec <<= 1;
						RmtRec |= 0;//接收到0码
					}
					else if(Dval>1400&&Dval<1800)//高电平为1680us
					{
						RmtRec <<= 1;
						RmtRec |= 1;//接收到1码
					}
					else if(Dval>2200&&Dval<2600)//连发码判断
					{
						RmtCnt++;
						RmtSta &= 0xF0;//清空计数器
					}
				}		
					else if(Dval>4200&&Dval<4700)
					{
						RmtSta |= 1<<7;//记录接收到引导码
						RmtCnt = 0;
					}
			}
			RmtSta &= ~(1<<4);
		}
	}
	TIM_ClearFlag(TIM5,TIM_IT_Update|TIM_IT_CC2);
}

2.3 遥控键值扫描

u8 Remote_Scan(void)
{
	u8 sta=0;
	u8 t1,t2;
	
	if(RmtSta&(1<<6))//得到一个按键的信息
	{
		t1 = RmtRec>>24;//地址码
		t2 = (RmtRec>>16) &  0xFF;//地址反码
		if((t1==(u8)~t2)&&t1==REMOTE_ID)//校验遥控识别码以及遥控接收地址
		{
			t1 = RmtRec >> 8;//控制码
			t2 = RmtRec;//控制反码
			if(t1==(u8)~t2)
				sta = t1;
		}
		if((sta==0)||((RmtSta&0x80)==0))//接收错误或者按键没有按下
		{
			RmtSta &= ~(1<<6);//清除接收按键有效标志位
			RmtCnt = 0;
		}
	}
	return sta;
}

我的公众号:分享一些属于我的,属于我们的故事。 欢迎你来一起聆听。

在这里插入图片描述


参考:

1.原子库函数参考手册

  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值