单片机学习小组
直播中

潘飘稚

7年用户 880经验值
私信 关注

如何实现4路红外的38KHz载波编码发送?

如何实现4路红外的38KHz载波编码发送?

回帖(1)

李永清

2022-2-15 13:55:49
1、NEC协议简介

利用红外传输信息,编码协议有很多,我采用了常用的NEC协议进行编码。
NEC协议构成包括引导码、地址码、地址反码、控制码、控制反码。其采用PWM脉冲位置调制,以发射红外载波的占空比代表“0”和“1”。
NEC码的位定义:一个脉冲对应560us的连续载波,一个逻辑1传输需要2.25ms(560us脉冲+1680us低电平),一个逻辑0的传输需要1.125ms(560us脉冲+560us低电平)。一体化红外接收头HS0038B在收到脉冲时为低电平,没有脉冲时为高电平。这样的话,在接收头端收到的信号是:逻辑1对应560us低+1680us高,逻辑0对应560us低+560us高。
NEC同步码由9ms高电平和4.5ms低电平组成。另外,如果一直按住按键,遥控器会发送重复码(9ms高电平+2.5m低电平+0.56ms高电平+97.94ms低电平)。


2、载波实现及TIM配置
TIM_HandleTypeDef         TIM3_Handler;              //定时器句柄
TIM_OC_InitTypeDef         TIM3_CH2Handler;        //定时器3通道2句柄




//TIM3 PWM部分初始化
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
void TIM3_PWM_Init(u16 arr,u16 psc)
{  
    TIM3_Handler.Instance=TIM3;                  //定时器3
    TIM3_Handler.Init.Prescaler=psc;       //定时器分频
    TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;//向上计数模式
    TIM3_Handler.Init.Period=arr;          //自动重装载值
    TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_PWM_Init(&TIM3_Handler);       //初始化PWM
   
    TIM3_CH2Handler.OCMode=TIM_OCMODE_PWM1; //模式选择PWM1
    TIM3_CH2Handler.Pulse=arr/2;            //设置比较值,此值用来确定占空比
    TIM3_CH2Handler.OCPolarity=TIM_OCPOLARITY_HIGH; //输出比较极性为高
       
        HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH2Handler,TIM_CHANNEL_1);//配置TIM3通道1
        HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH2Handler,TIM_CHANNEL_2);//配置TIM3通道2
        HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH2Handler,TIM_CHANNEL_3);//配置TIM3通道3
    HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH2Handler,TIM_CHANNEL_4);//配置TIM3通道4
       
    HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_1);//开启PWM通道1
        HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_2);//开启PWM通道2
        HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_3);//开启PWM通道3
        HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_4);//开启PWM通道4
                   
}


//定时器底层驱动,时钟使能,引脚配置
//此函数会被HAL_TIM_PWM_Init()调用
//htim:定时器句柄
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
        GPIO_InitTypeDef GPIO_Initure;
       
    if(htim->Instance==TIM3)
        {
                __HAL_RCC_TIM3_CLK_ENABLE();                        //使能定时器3
                __HAL_RCC_GPIOA_CLK_ENABLE();                        //开启GPIOA时钟
                __HAL_RCC_GPIOB_CLK_ENABLE();                        //开启GPIOB时钟
       
                GPIO_Initure.Pin=GPIO_PIN_6 | GPIO_PIN_7;//PA6,PA7
                GPIO_Initure.Mode=GPIO_MODE_AF_PP;          //复用推挽输出
                GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
                GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
                HAL_GPIO_Init(GPIOA,&GPIO_Initure);


                GPIO_Initure.Pin=GPIO_PIN_0 | GPIO_PIN_1;//PB0, PB1
                HAL_GPIO_Init(GPIOB,&GPIO_Initure);
        }
}


//设置TIM3通道1~4的占空比
//compare:比较值
void TIM_SetTIM3Compare(u32 compare, u8 CH)
{
        if(CH == 1)                        TIM3->CCR1=compare;
        else if(CH == 2)        TIM3->CCR2=compare;
        else if(CH == 3)        TIM3->CCR3=compare;
        else if(CH == 4)        TIM3->CCR4=compare;
}


3、编码发送
void IRSend(u8 num, u8 CH){
        u8 addr = REMOTE_ID;
        /* 发送引导码 */
        NEC_Start(CH);
        /* 发送地址码 */
        NEC_Send_Byte(addr, CH);
        /* 发送地址反码 */
        NEC_Send_Byte(~addr, CH);
        /* 发送控制码 */
        NEC_Send_Byte(num, CH);
        /* 发送控制反码 */
        NEC_Send_Byte(~num, CH);
        Logical_0(CH);//停止位,如果没有这个的话,上面发的最后一位的时长检测会出问题;
                                //理论上给个电平跳变就行,不一定发逻辑0。跳变完恢复为空闲状态
}


void NEC_Start(u8 CH){
        TIM_SetTIM3Compare(947, CH);
        delay_us(9000);
        TIM_SetTIM3Compare(0, CH);
        delay_us(4500);


}


void NEC_Send_Byte(u8 value, u8 CH){
        u8 i;
        for(i = 0; i < 8; i++){
                if(value & 0x80){
                        Logical_1(CH);
                }else {
                        Logical_0(CH);
                }
                value <<= 1;
        }
}


void Logical_0(u8 CH){
        TIM_SetTIM3Compare(947, CH);
        delay_us(560);
        TIM_SetTIM3Compare(0, CH);
        delay_us(560);
}


void Logical_1(u8 CH){
        TIM_SetTIM3Compare(947, CH);
        delay_us(560);
        TIM_SetTIM3Compare(0, CH);
        delay_us(1680);
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分