Tariky 2022-04-13 21:39 采纳率: 33.3%
浏览 935
已结题

STM32F407最小系统板HAL库定时器配置编码器模式CNT一直为0

问题遇到的现象和发生背景

STM32F407最小系统板HAL库定时器配置编码器模式CNT一直为0,编码器是AB相增量式霍尔编码器
定时器和IO口使用的是TIM3 CH1 CH2, PA6, PA7

问题相关代码,请勿粘贴截图

编码器初始化:

TIM_HandleTypeDef TIM3_Handler;
TIM_Encoder_InitTypeDef TIM3_Encoder_Handler;

void Encoder_Init(void) {
    
    TIM_Encoder_InitTypeDef sConfig = {0};
    TIM_MasterConfigTypeDef sMasterConfig = {0};

    /* USER CODE BEGIN TIM3_Init 1 */

    /* USER CODE END TIM3_Init 1 */
    TIM3_Handler.Instance = TIM3;
    TIM3_Handler.Instance->SMCR &= ~TIM_SMCR_SMS;
    TIM3_Handler.Init.Prescaler = 0;
    TIM3_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;
    TIM3_Handler.Init.Period = 65535;
    TIM3_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    TIM3_Handler.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
    sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
    sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
    sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
    sConfig.IC1Filter = 10;
    sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
    sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
    sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
    sConfig.IC2Filter = 10;
    if (HAL_TIM_Encoder_Init(&TIM3_Handler, &sConfig) != HAL_OK) {
        
        printf("TIM3 Encoder Init Error!/r/n");
        
    }
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    if (HAL_TIMEx_MasterConfigSynchronization(&TIM3_Handler, &sMasterConfig) != HAL_OK) {
        
        printf("TIM3 Master Config Error!/r/n");
        
    }
//  /* 清零计数器 */
    __HAL_TIM_SET_COUNTER(&TIM3_Handler, 0);

//    /* 清零中断标志位 */
    __HAL_TIM_CLEAR_IT(&TIM3_Handler,TIM_IT_UPDATE);
//    /* 使能定时器的更新事件中断 */
//    __HAL_TIM_ENABLE_IT(&TIM3_Handler,TIM_IT_UPDATE);
//    /* 设置更新事件请求源为:计数器溢出 这个地方可能会忘记设置 */
//    __HAL_TIM_URS_ENABLE(&TIM3_Handler);

//    /* 设置中断优先级 */
//    HAL_NVIC_SetPriority(TIM3_IRQn, 1, 0);
//    /* 使能定时器中断 */
//    HAL_NVIC_EnableIRQ(TIM3_IRQn);

    HAL_TIM_Encoder_Start(&TIM3_Handler, TIM_CHANNEL_ALL);

}

void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim) {
    
    if (htim->Instance == TIM3) {
        printf("TIM3 Encoder Msp Init\r\n");
        GPIO_InitTypeDef GPIO_Initure;
        __HAL_RCC_TIM3_CLK_ENABLE();
        __HAL_RCC_GPIOA_CLK_ENABLE();
        
        GPIO_Initure.Pin = GPIO_PIN_6 | GPIO_PIN_7;
        GPIO_Initure.Mode = GPIO_MODE_AF_PP;
        GPIO_Initure.Pull = GPIO_PULLUP;
        GPIO_Initure.Speed = GPIO_SPEED_FREQ_LOW;
        GPIO_Initure.Alternate = GPIO_AF2_TIM3;
        HAL_GPIO_Init(GPIOA, &GPIO_Initure);
        
//        HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
//        HAL_NVIC_EnableIRQ(TIM3_IRQn);
        
    }
    
}

主循环代码:

Encoder_Init();
while (1) {
    CaptureNumber = ( int16_t )TIM3->CNT;
    printf("输入捕获值:%d \r\n", CaptureNumber);
    // 4 : 使用定时器编码器接口捕获AB相的上升沿和下降沿,一个脉冲*4.
    // 11:编码器线数(转速一圈输出脉冲数)
    // 34:电机减数比,内部电机转动圈数与电机输出轴转动圈数比,即减速齿轮比
    printf("电机实际转动速度:%0.2f(圈/s)\r\n",(float) CaptureNumber/4/11/34);
    TIM3->CNT = 0;
    delay_ms(200);
}
运行结果及报错内容

img

我的解答思路和尝试过的方法

网上大部分HAL库的都试过了

我想要达到的结果

能正常读取编码器数据就行

  • 写回答

2条回答 默认 最新

  • ilmss 2022-04-14 14:16
    关注

    注意两个问题:一个是存在相位差的信号,二是两组方波信号
    定时器配置
    注:*这种测速的情况必须开启另一个定时器,用来表示在多少时间内测得的脉冲数。例如目前使用TIM1,设为1s进行计数。
    STM32Cube MX中进行定时器配置:定时器时钟频率为80MHz。
    定时器编码器模式设置
    使用TIM3设为编码器模式,可以对两路有相位差(90°或者270°)的方波信号进行脉冲计数和方向位测试。
    在主循环开始前

    HAL_TIM_Encoder_Start_IT(&htim3,TIM_CHANNEL_ALL);//打开编码器中断
    HAL_TIM_Base_Start_IT(&htim1);//开启1S定时中断
    __HAL_TIM_ENABLE_IT(&htim3,TIM_IT_UPDATE);//更新中断用于溢出计数
    
    在中断中
    void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断中可以添加自己所需要的标志位
    {undefined
    if(htim3.Instance->CR1 == 0x01)//顺时针
    {}
    if(htim3.Instance->CR1 == 0x11)//逆时针
    {}
    }
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {undefined
    if(TIM1 == htim->Instance)
    {undefined
    t200 = 1;
    }
    if(TIM3 == htim->Instance)
    {undefined
    TIM3UP++;
    __HAL_TIM_CLEAR_IT(&htim3,TIM_IT_UPDATE);
    if(htim3.Instance->CR1 == 0x01)//顺时针
    {undefined
    circle_count++;
    }
    if(htim3.Instance->CR1 == 0x11)//逆时针
    {undefined
    circle_count–;
    }
      }
       }
    

    在主循环中

    if(t200 == 1)
      {
          t200 = 0;
          HAL_TIM_Encoder_Stop(&htim3,TIM_CHANNEL_ALL);
          __HAL_TIM_DISABLE_IT(&htim3,TIM_IT_UPDATE);
    
          directuinA = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3);//用来获取方向
          if(directuinA == 0)//顺时针,会从0开始向上计数,来一个脉冲,增加一个计数
          {
            CaptureNumberA = TIM3UP * 65535 + __HAL_TIM_GET_COUNTER(&htim3);
          }
          else if(directuinA == 1)//逆时针,会从65535开始向下计数,来一个脉冲,减去一个计数;TIM3UP 是为了计数溢出所添加的
          {
            CaptureNumberA = TIM3UP * 65535  - __HAL_TIM_GET_COUNTER(&htim3) + 1;
          }
          //除以4是由于四倍频的缘故,PULSE_CIRCLE是指一圈有多少脉冲,*60是为了换算成r/min
          T_SPEED = (CaptureNumberA / 4.0) / PULSE_CIRCLE * 60;
          
          HAL_TIM_Base_Stop(&htim3);
          __HAL_TIM_SET_COUNTER(&htim3,0);
          TIM3UP = 0;
          HAL_TIM_Base_Start(&htim3);
      }
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 4月23日
  • 已采纳回答 4月15日
  • 赞助了问题酬金10元 4月14日
  • 修改了问题 4月13日
  • 展开全部

悬赏问题

  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同
  • ¥50 如何openEuler 22.03上安装配置drbd
  • ¥20 ING91680C BLE5.3 芯片怎么实现串口收发数据
  • ¥15 无线连接树莓派,无法执行update,如何解决?(相关搜索:软件下载)
  • ¥15 Windows11, backspace, enter, space键失灵