简单的红外解码方式 -输入捕获

        我用的是国民技术N32L436的MCU来接收红外的信号,大概有3种方式来接收解码。方式1:用8k的中断轮询检测IO口,然后把数据保存进一个128字节大小的数组,然后再解码;反式2:采用外部中断+定时器的方式;方式3:使用定时器自带的输入捕获功能,这种方式适合定时器资源比较多的时候,用起来简单。

        因为我需要解码的信号比较多,有自定义的,还有红外遥控器的,所以我就用方式3;输入捕获解码红外信号。

        38k红外发射灯有4组,需要间隔发送5个不同的信号来区别4个方向和一个近点信号,目前接收灯只有一个,后期可能要增加2个,如果接收灯多的话,就要使用IO轮询的方式。

 这是红外发射的信号,红外发射用pwm发送射频率38k,占空比1/3就可以了。

红外接收头外部上拉,接收到的信号刚好和发射信号相反。

这是配置输入捕获的的代码,和STM32配置是一样的

static void Inpwm_Config(void)//��ˮˮ�����
{
	
	 GPIO_InitType 			GPIO_InitStructure;
 	 TIM_TimeBaseInitType  TIM_TimeBaseStructure;
	 TIM_ICInitType			TIM_ICInitStructure;
 	 NVIC_InitType			NVIC_InitStructure;

	RCC_EnableAPB2PeriphClk(IR_LED_CLK,ENABLE);//GPIOA时钟使能
	RCC_EnableAPB1PeriphClk(IR_LED_TIM_CLK,ENABLE);//定时器2时钟使能
	
	GPIO_InitStruct(&GPIO_InitStructure);//初始化填充数据

	GPIO_InitStructure.Pin=IR_LED_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Input;//输入模式
	//GPIO_InitStructure.GPIO_Pull=GPIO_Pull_Down;//下拉
	GPIO_InitStructure.GPIO_Current = GPIO_DC_4mA;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF2_TIM2;//复用AF2
	GPIO_InitPeripheral(IR_LED_GPIO_PORT, &GPIO_InitStructure);
	
//-------------------------------------------------------------------------------
	TIM_TimeBaseStructure.Period=IR_LED_Period;//周期
	TIM_TimeBaseStructure.Prescaler=IR_LED_Prescaler;//分频因子
	TIM_TimeBaseStructure.ClkDiv = TIM_CLK_DIV1;//1分频	
	TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;//向上计数
	TIM_InitTimeBase(IR_LED_TIM, &TIM_TimeBaseStructure);
//-----------------------------------------------------------------------------
    TIM_ICInitStructure.Channel     = IR_LED_CHANNEL;//定时器2通道2
    TIM_ICInitStructure.IcPolarity  = TIM_IC_POLARITY_FALLING;//下降沿触发
    TIM_ICInitStructure.IcSelection = TIM_IC_SELECTION_DIRECTTI;//
    TIM_ICInitStructure.IcPrescaler = TIM_IC_PSC_DIV1;//1分频
    TIM_ICInitStructure.IcFilter    = 0x0;//
	TIM_ICInit(IR_LED_TIM,&TIM_ICInitStructure);
	
//--------------------------------------------------------------------------------
	NVIC_InitStructure.NVIC_IRQChannel                   = IR_LED_TIM2_IRQ;//定时器2中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 1;//子优先级1
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

	TIM_Enable(IR_LED_TIM, ENABLE);//使能定时器2

	
	TIM_ConfigInt(IR_LED_TIM, TIM_INT_CC2, ENABLE);//使能定时器中断源TIM_INT_CC2
	//TIM_ConfigInt(TIM2, TIM_INT_UPDATE, ENABLE);

	TIM_ClearFlag(IR_LED_TIM,TIM_FLAG_CC2);
	TIM_ClrIntPendingBit(IR_LED_TIM,TIM_FLAG_CC2);

}

不同的MCU需要不同的配置,例如N32L436的

定时器2不分频是27Mx2=54MHZ.

#define IR_LED_GPIO_PORT          GPIOA				              
#define IR_LED_CLK 	        	RCC_APB2_PERIPH_GPIOA|RCC_APB2_PERIPH_AFIO		
#define IR_LED_GPIO_PIN           GPIO_PIN_1

             
#define IR_LED_TIM                TIM2
#define IR_LED_CHANNEL            TIM_CH_2
#define IR_LED_TIM_CLK            RCC_APB1_PERIPH_TIM2
#define IR_LED_Period            	0xffff//������
#define IR_LED_Prescaler         	54-1  //1us
#define IR_LED_TIM2_IRQ          	TIM2_IRQn

 外设配置完成后,开始接收红外解码了。

u8 ir_led_status_flag=0x00;
u16 Cnt_H=0;
u16 Cnt_L=0;

void TIM2_IRQHandler(void)
{
	
	//if(ir_led_status_flag)
	if(TIM_GetIntStatus(TIM2,TIM_INT_CC2) != RESET)//
	{
		switch (ir_led_status_flag)
		{
			case 0x00:
				TIM_SetCnt(TIM2,0);
				Cnt_L=0;
				Cnt_H=0;
				ir_led_status_flag=0x01;
				TIM_ConfigOc2Polarity(TIM2,TIM_IC_POLARITY_RISING);//转换成上升沿
				break;
			case 0x01:
				Cnt_L=TIM_GetCap2(TIM2);//获取高电平时间
				if((Cnt_L>2950)&&(Cnt_L<3050))//高电平3ms座子信号
				{
					ir_led_status_flag=0x02;

				//	printf("====3ms\r\n");
				//	TIM_ConfigOc2Polarity(TIM2,TIM_IC_POLARITY_RISING);
				}
				else if((Cnt_L>5700)&&(Cnt_L<6100))//高电平6ms座子近卫信号
				{
					ir_led_status_flag=0x00;
					printf("====f0\r\n");
				}
				else if((Cnt_L>8950)&&(Cnt_L<9050))//高电平9ms,遥控器信号
				{
					ir_led_status_flag=0x02;
					printf("==9\r\n");
				}
				else 
				{					
					ir_led_status_flag=0x00;				
				}
				//Cnt_H=0;
				//Cnt_L=0;
				TIM_SetCnt(TIM2,0); 			
				TIM_ConfigOc2Polarity(TIM2,TIM_IC_POLARITY_FALLING);//下降沿触发

				break;
			case 0x02:
				Cnt_H=TIM_GetCap2(TIM2);//获取高电平时间
				if((Cnt_H>900)&&(Cnt_H<1100))//电平1ms
				{
					ir_led_status_flag=0x04;
					//printf("-------1\r\n");
				}
				else if((Cnt_H>2950)&&(Cnt_H<3050))//电平3ms
				{
					ir_led_status_flag=0x04;
					//printf("-------2\r\n");
				}
				else if((Cnt_H>4950)&&(Cnt_H<5050))//电平5ms
				{
					ir_led_status_flag=0x04;
					//printf("-------3\r\n");
				}
				else if((Cnt_H>6950)&&(Cnt_H<7050))//电平7ms
				{
					ir_led_status_flag=0x04;
					//printf("-------4\r\n");
				}
				else{
					ir_led_status_flag=0x00;//接收信号错误
									Cnt_H=0;
					Cnt_L=0;
					TIM_SetCnt(TIM2,0);
					printf("Cnt_H=%d-------0000\r\n",Cnt_H);
					break;
				}
				Cnt_H=0;
				Cnt_L=0;
				TIM_SetCnt(TIM2,0);
				TIM_ConfigOc2Polarity(TIM2,TIM_IC_POLARITY_RISING);//
				break;
			case 0x04:
				Cnt_L=TIM_GetCap2(TIM2);
				if((Cnt_L>950)&&(Cnt_L<1050))
				{
					//接收信号正确
					
				}
				else
				{
					ir_led_status_flag=0x00;
				}
				Cnt_H=0;
				Cnt_L=0;
				TIM_SetCnt(TIM2,0);
				TIM_ConfigOc2Polarity(TIM2,TIM_IC_POLARITY_FALLING);//上升沿触发
				break;
		}

		
	}
	//TIM_ClearFlag(QSSL_DEF_TIM,TIM_FLAG_CC2);
	TIM_ClrIntPendingBit(TIM2,TIM_INT_CC2);//
	
}

这解码自定义的红外信号,因为是测试用的,写的乱了点,大概思路就是这样子,后面还会增加遥控器的解码,选型还没选好,预留个接口就好。

如果是pwm够用的情况下用输入捕获会比较简单些,如果要多组红外解码的话,比如6个红外接收头,那就使用轮询IO口的电平,然后保存数据再解码。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值