STM32——红外遥控

通常红外遥控为了提高抗干扰性能和降低电源消耗,红外遥控器常用载波的方式传送二进制编码,常用的载波频率为38kHz,这是由发射端所使用的455kHz晶振来决定的。在发射端要对晶振进行整数分频,分频系数一般取12,所以455kHz÷12≈37.9kHz≈38kHz。也有一些遥控系统采用36kHz、40 kHz、56 kHz等,一般由发射端晶振的振荡频率来决定。所以,通常的红外遥控器是将遥控信号(二进制脉冲码)调制在38KHz的载波上,经缓冲放大后送至红外发光二极管,转化为红外信号发射出去的。
二进制脉冲码的形式有多种,其中最为常用的是NEC Protocol 的 PWM码(脉冲宽度调制)和 Philips RC-5 Protocol 的 PPM码(脉冲位置调
制码,脉冲串之间的时间间隔来实现信号调制)。如果要开发红外接收设备,一定要知道红外遥控器的编码方式和载波频率,我们才可以选取一体化红外接收头和制定解码方案。
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码位定义时序图如图
在这里插入图片描述
NEC 遥控指令的数据格式为:引导码、地址码、地址反码、控制码、控制反码。引导码由一个 9ms 的低电平和一个 4.5ms 的高电平组成,
地址码、地址反码、控制码、控制反码均是8 位数据格式。按照低位在前,高位在后的顺序发送。采用反码是为了增加传输的可靠性(可用于校验)。数据格式如下:
在这里插入图片描述
NEC码还规定了连发码(由 9ms 低电平+2.5m 高电平+0.56ms 低电平+97.94ms 高电平组成),如果在一帧数据发送完毕之后,红外遥控器按
键仍然没有放开,则发射连发码,可以通过统计连发码的次数来标记按键按下的长短或次数。
由于红外接收头在没有脉冲的时候为高电平,当收到脉冲的时候为低电平,所以可以通过外部中断的下降沿触发中断,在中断内通过计算高电平时间来判断接收到的数据是0还是1。
hongwai.c

#include "hw.h"
#include "SysTick.h"

u32 hw_jsm;    //全局变量接受码
u32 hw_jsbz;   //全局变量接收标志

void hw_Init(void)
{
			GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量	
	    EXTI_InitTypeDef  EXTI_InitStructure; //外部中断结构体
	    NVIC_InitTypeDef NVIC_InitStructure; //定义NVIC结构体
	
			RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能端口时钟
	    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);//外部中断时钟
			SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource8);  //映射外部中断PA8
	
	    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN; //输入模式
			GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;//管脚设置PA8
			GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M
			GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
			GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化结构体
			
	
	    EXTI_ClearITPendingBit(EXTI_Line8);     //清除外部中断线标志
			EXTI_InitStructure.EXTI_Line=EXTI_Line8;    //PA8
			EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
			EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;  //下降沿触发
			EXTI_InitStructure.EXTI_LineCmd=ENABLE;      //使能中断线
			EXTI_Init(&EXTI_InitStructure);
				
	    NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;   //EXTI0中断通道
			NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;    //抢占优先级
			NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;		       //子优先级,由于要使用串口打印所以优先级要比串口要高
			NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			       //IRQ通道使能
			NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
	    
}

u8 HW_jssj(void)    //红外接受数据高电平时间
{
	      u8 t;
	      while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8) == 1){
							t++;
							myDelay_us(20);
						if(t>= 250){
								return t;
						}
				}
				
				return t;
}

void EXTI9_5_IRQHandler(void)
{
			u8 Tim = 0;
	    u8 OK = 0;
	    u8 Data;
	    u8 Num = 0;
     	while(1){
					if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8) == 1){    //读取GPIO输入引脚状态
							Tim = HW_jssj();
						if(Tim >= 250){                //超过5ms
						    break;
						}
						if(Tim>200&&Tim<250){    //引导码:4-5ms之间
						    OK = 1;
						}else if(Tim >=60&&Tim<90){    //逻辑1(1680us):高电平时间在1.2-1.8ms
						    Data = 1;
						}else if(Tim >=10 && Tim<50){   //逻辑0(560us):高电平时间在200us-1ms
								Data = 0;
						}
					if(OK == 1){
					   hw_jsm  <<= 1;
						 hw_jsm += Data;
							if(Num >= 32){
									hw_jsbz = 1;
								  break;
							}
					}
					Num++;
					}
					
			}
      EXTI_ClearITPendingBit(EXTI_Line8);     //清除外部中断线标志
}


hongwai.h

#ifndef __hw_H
#define __hw_H

#include "system.h"

extern u32 hw_jsm;
extern u32 hw_jsbz;

void EXTI9_5_IRQHandler(void);
u8 HW_jssj(void);
void hw_Init(void);

#endif

main.c

#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart.h"
#include "key.h"
#include "dma.h"
#include "rtc.h"
#include "iic.h"
#include "24cxx.h"
#include "hw.h"



int main()
{	
	u8 i=0;
	u8 key;
	u8 k = 0;
	SysTick_Init(168);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组
	LED_Init();
	USART1_Init(9600);
	KEY_Init();
	adcx_Init();
	TIM11_CH1_PWM_Init(255,0); //APB2总线,最大时钟168M,168/256 = 656.25KHz
	AT24CXX_Init();
	hw_Init();
	
	
	while(1)
	{
	  if(hw_jsbz == 1){  //标志进入中断
		  hw_jsbz = 0;    //红外标志清零
			printf("红外接收码%0.8Xd\n\r",hw_jsm);
			hw_jsm = 0;     //数据清零
		}
		i++;
		
		if(i%20==0){

			led1=!led1;
		}
		
		
		myDelay_ms(10);
	}
}

		 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值