STM32HAL----红外遥控(NEC)

整理了一个NEC协议的红外程序,NEC协议,物理环境为F103原子战舰V3,使用STM32CubeMX生成初始程序。

定时器配置72分频,9999装载值(10MS)

NEC协议:

数据格式: 同步码头 + 地址码 +地址反码 + 按键码 + 按键反码 (LSB先行

同步码头:9ms低电平 + 4.5ms高电平

连发码 :   9ms低电平 + 2.5ms高电平

逻辑1:      560us  +  1680us

逻辑0:      560us  +  560us

程序:

头文件:

#ifndef __Fun_Infrared_H
#define __Fun_Infrared_H


#include "stm32f1xx_hal.h"
#include "tim.h"


#define  RangJudge(val,min,max)   (val>min? (val<max? 1 : 0) : 0)


typedef struct T4_Infrared
{
        uint32_t  KEY_VALUE;   //记录32位地址以及按键码
	uint16_t  TriTime[2];  //记录电平持续时间 0:低电平  1:高电平
	uint8_t   DataBit;
	uint8_t   FrameStart;
        uint8_t   KEY_Count;	
	uint8_t   TriPolarity;
	
}T4_InfraredDev;


extern T4_InfraredDev  *T4Infra;






void T4InfraInit(void);

void TIM4_InfraPeriodHandle(void);

void TIM4_InfraCaptureHandle(void);

uint8_t  GetInfraredKey(void);
	
uint8_t  GetInfraredAddr(void);

#endif

源文件:

#include "Fun_Infrared.h"


T4_InfraredDev  T4Infra_S, *T4Infra = &T4Infra_S;


void T4InfraInit(void)
{
        HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_4);
	__HAL_TIM_ENABLE_IT(&htim4, TIM_IT_UPDATE);  //使能更新中断
	
	T4Infra->TriPolarity = 0;
	T4Infra->FrameStart = 0;
}


//改变TIM4 CHANNEL4的捕获极性
void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
{
  uint16_t tmpccer = 0;

  tmpccer = TIMx->CCER;

  tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC4P);
  tmpccer |= (uint16_t)(TIM_OCPolarity << 12);

  TIMx->CCER = tmpccer;
}


//捕获中断处理函数
void TIM4_InfraPeriodHandle(void)
{
	T4Infra->TriPolarity = 0;
        T4Infra->FrameStart = 0;
	T4Infra->TriTime[0] = 0;
	T4Infra->TriTime[1] = 0;
}


//捕获中断处理函数
void TIM4_InfraCaptureHandle(void)
{

	  T4Infra->TriPolarity = !T4Infra->TriPolarity;
	
	  /************************** 切换极性以及捕获电平持续时间 **************************/
	
	     if(!T4Infra->TriPolarity)  //上升沿触发
		{
			TIM_OC4PolarityConfig(TIM4, TIM_INPUTCHANNELPOLARITY_FALLING);			
			
			T4Infra->TriTime[T4Infra->TriPolarity] = \
                        HAL_TIM_ReadCapturedValue(&htim4, TIM_CHANNEL_4);			
		}
		else  //下降沿触发
		{
			TIM_OC4PolarityConfig(TIM4, TIM_INPUTCHANNELPOLARITY_RISING);
			
                         if(T4Infra->FrameStart == 1) 
			{
                             T4Infra->TriTime[T4Infra->TriPolarity] = \
                             HAL_TIM_ReadCapturedValue(&htim4, TIM_CHANNEL_4);
			}					
			
                        T4Infra->FrameStart = 1;	//开始接收帧	   			
		}	
		
		TIM4->CNT = 0; 	//清除TIM4计数值

	  /**************************** 判断同步码以及重复码 ***************************/
		
		if(RangJudge(T4Infra->TriTime[0],8500,9500) && \
                   RangJudge(T4Infra->TriTime[1],4000,5000) ) 
		{
			 T4Infra->KEY_VALUE = 0;  //同步码
			 T4Infra->KEY_Count = 0;  
                         T4Infra->DataBit = 0;  		
		}		
		else if(RangJudge(T4Infra->TriTime[0],8500,9500) && \
                        RangJudge(T4Infra->TriTime[1],2000,3000) ) 
		{
			 if(++T4Infra->KEY_Count > 250) T4Infra->KEY_Count = 250;    //连发码
		}
	
	  /********************************* 接收数据 *********************************/		
		if( T4Infra->TriPolarity == 1) 
		{
                      if(RangJudge(T4Infra->TriTime[0],450,650) && \
                         RangJudge(T4Infra->TriTime[1],450,650) ) 
			{
			   T4Infra->KEY_VALUE &= ~(1<T4Infra->DataBit++);
			}
			 
                        else if(RangJudge(T4Infra->TriTime[0],450,650) && \
                              RangJudge(T4Infra->TriTime[1],1450,1750) ) 
			{
			   T4Infra->KEY_VALUE |= 1<<T4Infra->DataBit++;
			}
		}	
		
		
}


//获取按键值
uint8_t  GetInfraredKey(void)
{
   //通过与反码异或,验证按键码的正确性
   if( (uint8_t)( (T4Infra->KEY_VALUE >> 24) ^ (T4Infra->KEY_VALUE >> 16) ) == 0xff  )
   return (uint8_t)(T4Infra->KEY_VALUE>>16);
	 
   else  return 0;
}


//获取地址
uint8_t  GetInfraredAddr(void)
{
   if( (uint8_t)( (T4Infra->KEY_VALUE ) ^ (T4Infra->KEY_VALUE >> 8) ) == 0xff  )
   return (uint8_t)(T4Infra->KEY_VALUE);
	 
   else  return 0;
}

主函数:

#include "Fun_Infrared.h"

int main(void)
{
  HAL_Init();


  SystemClock_Config();

  MX_GPIO_Init();
  MX_TIM4_Init();
  MX_USART1_UART_Init();

  T4InfraInit();  //启动TIM4

  while (1)
  {
		printf("按键次数:%d\r\n",T4Infra->KEY_Count);
                printf("键值:0x%02X\r\n",GetInfraredKey() );
		printf("地址:0x%02X\r\n",GetInfraredAddr() );
		HAL_Delay(2000);
  }

}



//更新中断
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM4)
	{
	  TIM4_InfraPeriodHandle();
	}
}



//捕获中断
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{

    if(htim->Instance == TIM4)
	{
		TIM4_InfraCaptureHandle();
	}
}

实验现象:

猜你喜欢

转载自blog.csdn.net/a3748622/article/details/81302686