l1491645057 2024-09-30 15:37 采纳率: 25%
浏览 43

HX1838红外遥控编码问题

使用HX1838红外接收模块,遥控器按下后接收模块的输出端可以输出高低电平,用输入捕获捕获到低电平后,获取捕获计时器的值,计算出高电平的时间,但是val的值一直达不到引导码的值(4200~4700)。

void Remote_Init(void)                  
{        
  GPIO_InitTypeDef  GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_ICInitTypeDef  TIM1_ICInitStructure;
    
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//TIM1时钟使能 

  //GPIOA8  复用功能,上拉
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
    
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_TIM1); //GPIOA8复用为TIM1
    
    TIM_TimeBaseStructure.TIM_Prescaler=167;  ////预分频器,1M的计数频率,1us加1.    
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
    TIM_TimeBaseStructure.TIM_Period=10000;   //设定计数器自动重装值 最大10ms溢出  
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
    TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure); 
        
     //初始化TIM2输入捕获参数
    TIM1_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01     选择输入端 IC1映射到TI1上
  TIM1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;    //上升沿捕获
  TIM1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
  TIM1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;     //配置输入分频,不分频 
  TIM1_ICInitStructure.TIM_ICFilter = 0x03;//IC1F=0003 8个定时器时钟周期滤波
  TIM_ICInit(TIM1, &TIM1_ICInitStructure);//初始化定时器2输入捕获通道
     
 
    
    TIM_ITConfig(TIM1,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断 ,允许CC1IE捕获中断    
  TIM_Cmd(TIM1,ENABLE );          //使能定时器1
 
  NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;        //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //初始化NVIC寄存器

  NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;        //子优先级2
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //初始化NVIC寄存器
}

//遥控器接收状态
//[7]:收到了引导码标志
//[6]:得到了一个按键的所有信息
//[5]:保留    
//[4]:标记上升沿是否已经被捕获                                   
//[3:0]:溢出计时器
u8     RmtSta=0;            
u16 Dval;        //下降沿时计数器的值
u32 RmtRec=0;    //红外接收到的数据                   
u8  RmtCnt=0;    //按键按下的次数     
//定时器1溢出中断
void TIM1_UP_TIM10_IRQHandler(void)
{
         printf("val =  %d\n\r",TIM_GetCapture1(TIM1));
  if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET) //溢出中断
    {
        printf("定时器溢出\r\n ");
        if(RmtSta&0x80)//上次有数据被接收到了
        {    
            RmtSta&=~0X10;                        //取消上升沿已经被捕获标记
            if((RmtSta&0X0F)==0X00)RmtSta|=1<<6;//标记已经完成一次按键的键值信息采集
            if((RmtSta&0X0F)<14)RmtSta++;
            else
            {
                RmtSta&=~(1<<7);//清空引导标识
                RmtSta&=0XF0;    //清空计数器    
            }                                    
        }                                
    }
    TIM_ClearITPendingBit(TIM1,TIM_IT_Update);  //清除中断标志位 
} 
//定时器1输入捕获中断服务程序     
void TIM1_CC_IRQHandler(void)
{                  
    if(TIM_GetITStatus(TIM1,TIM_IT_CC1)==SET) //处理捕获(CC1IE)中断
    {      
        if(RDATA)//上升沿捕获
        {
            
            TIM_OC1PolarityConfig(TIM1,TIM_ICPolarity_Falling);        //CC1P=1 设置为下降沿捕获
            TIM_SetCounter(TIM1,0);           //清空定时器值
            RmtSta|=0X10;                    //标记上升沿已经被捕获
        }else //下降沿捕获
        {
                printf("二 RADTA = %d\r\n",RDATA);
            Dval=TIM_GetCapture1(TIM1);//读取CCR1也可以清CC1IF标志位
                        printf("一 Dvla = %d\r\n",Dval);
            TIM_OC1PolarityConfig(TIM1,TIM_ICPolarity_Rising); //CC1P=0    设置为上升沿捕获
            if(RmtSta&0X10)                    // 0X10 = 16 完成一次高电平捕获 
            {
                        printf("RmtSta = %d \r\n",RmtSta);
                 if(RmtSta&0X80)// 128 = 1000 0000 接收到了引导码
                {

                    if(Dval>300&&Dval<800)            //560为标准值,560us
                    {
                        RmtRec<<=1;    //左移一位.
                        RmtRec|=0;    //接收到0       
                    }else if(Dval>1400&&Dval<1800)    //1680为标准值,1680us
                    {
                        RmtRec<<=1;    //左移一位.
                        RmtRec|=1;    //接收到1
                    }else if(Dval>2200&&Dval<2600)    //得到按键键值增加的信息 2500为标准值2.5ms
                    {
                        RmtCnt++;         //按键次数增加1次
                        RmtSta&=0XF0;    //清空计时器        
                    }
                 }else if(Dval>4200&&Dval<4700)        //4500为标准值4.5ms
                {
                        printf("接收到引导码\r\n");
                    RmtSta|=1<<7;    //标记成功接收到了引导码
                    RmtCnt=0;        //清除按键次数计数器
                }                         
            }
        
            RmtSta &=~(1<<4); //第四位清零,高电平捕获标志位
        }                                                             
    }
    TIM_ClearITPendingBit(TIM1,TIM_IT_CC1);  //清除中断标志位 
}

二 RADTA = 0
一 Dvla = 387
RmtSta = 144 
二 RADTA = 0
一 Dvla = 894
RmtSta = 144 
二 RADTA = 0
一 Dvla = 436
RmtSta = 144 
二 RADTA = 0
一 Dvla = 718
RmtSta = 144 
二 RADTA = 0
一 Dvla = 382
RmtSta = 144 
二 RADTA = 0
一 Dvla = 1090
RmtSta = 144 
二 RADTA = 0
一 Dvla = 381
RmtSta = 144 
二 RADTA = 0
一 Dvla = 772
RmtSta = 144 
二 RADTA = 0
一 Dvla = 508
RmtSta = 144 
二 RADTA = 0
一 Dvla = 382
RmtSta = 144 
二 RADTA = 0
一 Dvla = 1103
RmtSta = 144 
  • 写回答

1条回答 默认 最新

  • ChatGPTᴼᴾᴱᴺᴬᴵ 2024-10-07 14:30
    关注

    所有内容均由人工智能模型输出,其内容的准确性和完整性无法保证,不代表我的态度或观点。


    该回答引用GPT-4o mini,仅提供参考,不保证完全正确

    从你的代码和描述来看,你正在使用 HX1838 红外接收模块来捕获红外遥控信号,但你的引导码检测似乎存在问题,无法在期望的时间范围内接收到引导码。

    根据你的代码,下面是一些可能导致此问题的原因及其解决方案:

    可能的问题

    1. 捕获时间配置不当

      • 你设置的计数器周期(10ms)和预分频(167)看似没问题,但需要确保这些值符合你的系统要求。可以尝试调节预分频器和周期,以确保它们与你使用的定时器和系统时钟相匹配。
    2. 输入信号干扰

      • 确保红外接收模块的输出端信号没有噪声或其他干扰。这可能导致错误的高低电平捕获,进而导致捕获时间值不准确。
    3. 捕获模式配置问题

      • 你在 TIM1_CC_IRQHandler 中更改了捕获极性,这种切换可能导致某些情况下无法正确捕获高低电平。可以检查极性设置的时机和状态,确保它们在每次捕获前都能正确设置。
    4. 输入滤波器配置

      • 输入捕获的滤波器设置为 0x03,这个设置可能会过滤掉一些正常信号,导致无法正确捕获到数据。可以尝试将其调整到更高的值(例如 0x0F),以便能够捕获更短的脉冲。
    5. 数据处理逻辑

      • 在判断 Dval 时,确保你的逻辑没有错。检查每个条件是否能被正确执行,并确保捕获的时间值在合理范围内。

    调试建议

    • 打印调试信息

      • 可以增加一些调试输出,尤其是在 TIM1_CC_IRQHandler 中,打印出 RmtStaDval 的值,以便观察程序在捕获过程中状态的变化。
    • 使用示波器或逻辑分析仪

      • 监控 HX1838 输出的信号,确认其确实在预期的时间范围内输出高低电平。
    • 简化测试

      • 尝试只测试引导码的捕获,暂时去掉其他按键的处理,确保能够单独捕获到引导码。
    • 逐步验证

      • 确保每个状态的转移都是合理的,比如在捕获上升沿后,确保可以成功捕获到下降沿并读取到正确的计数器值。

    示例调整

    如果你想先验证引导码的捕获,以下是一个可能的简化代码片段,仅专注于引导码的检测:

    if (RmtSta & 0x10) // 检查是否有上升沿捕获
    {
        if (Dval > 4200 && Dval < 4700) // 检查引导码
        {
            printf("接收到引导码\r\n");
            RmtSta |= 1 << 7; // 标记成功接收到了引导码
            RmtCnt = 0; // 清除按键次数计数器
        }
        // 清理状态
        RmtSta &= ~(1 << 4); // 清除高电平捕获标志位
    }
    

    希望这些建议能够帮助你找到问题的根源,并成功捕获遥控信号!如果还有其他问题,欢迎随时询问。

    评论

报告相同问题?

问题事件

  • 创建了问题 9月30日