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();
	}
}

实验现象:

  • 3
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值