项目中使用STM32F405RGT6作为主芯片,Tim2和Tim8分别输出驱动两路电机的PWM(每个Timer两个通道),Tim5和Tim3分别用作两路电机上编码器的计数(同样是每个Timer两个通道)。
关于如何通过Cube MX进行引脚以及Timer的配置在此不细说了,网上尤其是CSDN上有很多文章可以借鉴和参考,如:STM32CUBEMX F103 HAL库开发 两路定时器的Encoder编码器模式 - 简书。
实际上编码器的例程也有很多,步骤也都是大同小异,可以参考:STM32 HAL库学习系列第5篇 定时器TIM---编码器接口模式配置 - CodeAllen - 博客园
其实就是先配置好GPIO以及Timer,之后调用HAL_TIM_Encoder_Start(&htimx_Encoder, TIM_CHANNEL_ALL);开启编码器计数。如果是两路编码器,则一共调用两次这个函数,开启两路,如:
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL);
之后或是在主循环中(得到脉冲数和方向,只计算圈数),或是在SysTick或单独的定时器中断中进行脉冲数的读取(得到脉冲数和方向,计算转速)。例如:
DirectionA = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3);
DirectionB = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim4);
__HAL_TIM_IS_TIM_COUNTING_DOWN?可以获得当前电机的转向?0为正、1为反。
CaptureNumberA=__HAL_TIM_GET_COUNTER(&htim3);
CaptureNumberB=__HAL_TIM_GET_COUNTER(&htim4);
??__HAL_TIM_GET_COUNTER?获取计数器的计数值,即编码器的脉冲数。
一切看起来很简单。更有利的是,除了网上的例程,笔者还拿到了野火电机编码器测速例程,里边有完整的在野火骄阳电机开发板上验证通过的代码。笔者基于这个代码编写了以下代码:
/**
******************************************************************************
* File Name : TIM.c
* Description : This file provides code for the configuration
* of the TIM instances.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "tim.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim5;
TIM_HandleTypeDef htim7;
TIM_HandleTypeDef htim8;
/* TIM2 init function */
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 1-1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 8400-1;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 6300;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim2);
}
/* TIM3 init function */
void MX_TIM3_Init(void)
{
TIM_Encoder_InitTypeDef sConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 65535;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0;
sConfig.IC2Polarity = TIM_ICPOLARITY_FALLING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0;
if (HAL_TIM_Encoder_Init(&htim3, &sConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
/* TIM5 init function */
void MX_TIM5_Init(void)
{
TIM_Encoder_InitTypeDef sConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim5.Instance = TIM5;
htim5.Init.Prescaler = 0;
htim5.Init.CounterMode = TIM_COUNTERMODE_UP;
htim5.Init.Period = 65535;
htim5.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim5.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0;
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0;
if (HAL_TIM_Encoder_Init(&htim5, &sConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim5, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
/* TIM7 init function */
void MX_TIM7_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim7.Instance = TIM7;
htim7.Init.Prescaler = 8400-1;
htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
htim7.Init.Period = 1000-1;
htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim7) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim7, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
/* TIM8 init function */
void MX_TIM8_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
htim8.Instance = TIM8;
htim8.Init.Prescaler = 2-1;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 8400-1;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim8) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim8) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 6300;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim8);
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */
/* USER CODE END TIM2_MspInit 0 */
/* TIM2 clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
/* USER CODE BEGIN TIM2_MspInit 1 */
/* USER CODE END TIM2_MspInit 1 */
}
else if(tim_baseHandle->Instance==TIM7)
{
/* USER CODE BEGIN TIM7_MspInit 0 */
/* USER CODE END TIM7_MspInit 0 */
/* TIM7 clock enable */
__HAL_RCC_TIM7_CLK_ENABLE();
/* TIM7 interrupt Init */
HAL_NVIC_SetPriority(TIM7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM7_IRQn);
/* USER CODE BEGIN TIM7_MspInit 1 */
/* USER CODE END TIM7_MspInit 1 */
}
else if(tim_baseHandle->Instance==TIM8)
{
/* USER CODE BEGIN TIM8_MspInit 0 */
/* USER CODE END TIM8_MspInit 0 */
/* TIM8 clock enable */
__HAL_RCC_TIM8_CLK_ENABLE();
/* USER CODE BEGIN TIM8_MspInit 1 */
/* USER CODE END TIM8_MspInit 1 */
}
}
void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(tim_encoderHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* TIM3 clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM3 GPIO Configuration
PA6 ------> TIM3_CH1
PA7 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* TIM3 interrupt Init */
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_MspInit 1 */
//清零计数器
__HAL_TIM_SET_COUNTER(&htim3, 0);
//清零中断标志位
__HAL_TIM_CLEAR_IT(&htim3, TIM_IT_UPDATE);
//使能定时器的更新事件中断
__HAL_TIM_ENABLE_IT(&htim3, TIM_IT_UPDATE);
//设置更新事件请求源为:计数器溢出
__HAL_TIM_URS_ENABLE(&htim3);
//设置中断优先级
HAL_NVIC_SetPriority(TIM3_IRQn, 5, 0);
//使能定时器中断
HAL_NVIC_EnableIRQ(TIM3_IRQn);
//使能编码器接口
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
/* USER CODE END TIM3_MspInit 1 */
}
else if(tim_encoderHandle->Instance==TIM5)
{
/* USER CODE BEGIN TIM5_MspInit 0 */
/* USER CODE END TIM5_MspInit 0 */
/* TIM5 clock enable */
__HAL_RCC_TIM5_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM5 GPIO Configuration
PA0-WKUP ------> TIM5_CH1
PA1 ------> TIM5_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM5;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN TIM5_MspInit 1 */
//清零计数器
__HAL_TIM_SET_COUNTER(&htim5, 0);
//清零中断标志位
__HAL_TIM_CLEAR_IT(&htim5, TIM_IT_UPDATE);
//使能定时器的更新事件中断
__HAL_TIM_ENABLE_IT(&htim5, TIM_IT_UPDATE);
//设置更新事件请求源为:计数器溢出
__HAL_TIM_URS_ENABLE(&htim5);
//设置中断优先级
HAL_NVIC_SetPriority(TIM5_IRQn, 5, 1);
//使能定时器中断
HAL_NVIC_EnableIRQ(TIM5_IRQn);
//使能编码器接口
HAL_TIM_Encoder_Start(&htim5, TIM_CHANNEL_ALL);
/* USER CODE END TIM5_MspInit 1 */
}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(timHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspPostInit 0 */
/* USER CODE END TIM2_MspPostInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**TIM2 GPIO Configuration
PB10 ------> TIM2_CH3
PB11 ------> TIM2_CH4
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN TIM2_MspPostInit 1 */
/* USER CODE END TIM2_MspPostInit 1 */
}
else if(timHandle->Instance==TIM8)
{
/* USER CODE BEGIN TIM8_MspPostInit 0 */
/* USER CODE END TIM8_MspPostInit 0 */
__HAL_RCC_GPIOC_CLK_ENABLE();
/**TIM8 GPIO Configuration
PC6 ------> TIM8_CH1
PC7 ------> TIM8_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* USER CODE BEGIN TIM8_MspPostInit 1 */
/* USER CODE END TIM8_MspPostInit 1 */
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspDeInit 0 */
/* USER CODE END TIM2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM2_CLK_DISABLE();
/* USER CODE BEGIN TIM2_MspDeInit 1 */
/* USER CODE END TIM2_MspDeInit 1 */
}
else if(tim_baseHandle->Instance==TIM7)
{
/* USER CODE BEGIN TIM7_MspDeInit 0 */
/* USER CODE END TIM7_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM7_CLK_DISABLE();
/* TIM7 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM7_IRQn);
/* USER CODE BEGIN TIM7_MspDeInit 1 */
/* USER CODE END TIM7_MspDeInit 1 */
}
else if(tim_baseHandle->Instance==TIM8)
{
/* USER CODE BEGIN TIM8_MspDeInit 0 */
/* USER CODE END TIM8_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM8_CLK_DISABLE();
/* USER CODE BEGIN TIM8_MspDeInit 1 */
/* USER CODE END TIM8_MspDeInit 1 */
}
}
void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef* tim_encoderHandle)
{
if(tim_encoderHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspDeInit 0 */
/* USER CODE END TIM3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM3_CLK_DISABLE();
/**TIM3 GPIO Configuration
PA6 ------> TIM3_CH1
PA7 ------> TIM3_CH2
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_6|GPIO_PIN_7);
/* TIM3 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_MspDeInit 1 */
/* USER CODE END TIM3_MspDeInit 1 */
}
else if(tim_encoderHandle->Instance==TIM5)
{
/* USER CODE BEGIN TIM5_MspDeInit 0 */
/* USER CODE END TIM5_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM5_CLK_DISABLE();
/**TIM5 GPIO Configuration
PA0-WKUP ------> TIM5_CH1
PA1 ------> TIM5_CH2
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1);
/* USER CODE BEGIN TIM5_MspDeInit 1 */
/* USER CODE END TIM5_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/*
* @brief 定时器更新事件回调函数
* @param 无
* @retval 无
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *tim_baseHandle) //定时器中断回调
{
if(tim_baseHandle->Instance == TIM6)
{
}
else if(tim_baseHandle->Instance == TIM7)
{
static uint16_t i = 0;
i++;
if(i >= 5) //500ms计算一次
{
i = 0;
if(encoder_init_finished == 1)
{
//电机1旋转方向 = 计数器1计数方向
motor1_direction = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim5);
//当前时刻总计数值 = 计数器值 + 计数溢出次数 * ENCODER_TIM_PERIOD
capture_count1 = __HAL_TIM_GET_COUNTER(&htim5) + (encoder1_overflow_count * 65535);
//转轴转速1 = 单位时间内的计数值 / 编码器总分辨率 * 时间系数
//shaft1_speed = (float)(capture_count1 - last_count1) / ENCODER_TOTAL_RESOLUTION * 10;
shaft1_speed = (float)(capture_count1 - last_count1) / ENCODER_TOTAL_RESOLUTION * 2;
//电机2旋转方向 = 计数器2计数方向
motor2_direction = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3);
//当前时刻总计数值 = 计数器值 + 计数溢出次数 * ENCODER_TIM_PERIOD
capture_count2 = __HAL_TIM_GET_COUNTER(&htim3) + (encoder2_overflow_count * 65535);
//转轴转速2 = 单位时间内的计数值 / 编码器总分辨率 * 时间系数
//shaft2_speed = (float)(capture_count2 - last_count2) / ENCODER_TOTAL_RESOLUTION * 10;
shaft2_speed = (float)(capture_count2 - last_count2) / ENCODER_TOTAL_RESOLUTION * 2;
printf("电机1方向:%d\r\n", motor1_direction);
printf("单位时间内有效计数值:%d\r\n", capture_count1 - last_count1); //单位时间计数值 = 当前时刻总计数值 - 上一时刻总计数值
printf("电机1转轴处转速:%.2f 转/秒\r\n", shaft1_speed);
printf("电机1输出轴转速:%.2f 转/秒\r\n", shaft1_speed / REDUCTION_RATIO); //输出轴转速 = 转轴转速 / 减速比
printf("电机2方向:%d\r\n", motor2_direction);
printf("单位时间内有效计数值:%d\r\n", capture_count2 - last_count2); //单位时间计数值 = 当前时刻总计数值 - 上一时刻总计数值
printf("电机2转轴处转速:%.2f 转/秒\r\n", shaft2_speed);
printf("电机2输出轴转速:%.2f 转/秒\r\n\n", shaft2_speed / REDUCTION_RATIO); //输出轴转速 = 转轴转速 / 减速比
//记录当前总计数值,供下一时刻计算使用
last_count1 = capture_count1;
last_count2 = capture_count2;
}
}
}
else if(tim_baseHandle->Instance == TIM3)
{
//判断当前计数器计数方向
if(__HAL_TIM_IS_TIM_COUNTING_DOWN(tim_baseHandle))
{
//下溢
encoder2_overflow_count--;
}
else
{
//上溢
encoder2_overflow_count++;
}
}
else if(tim_baseHandle->Instance == TIM5)
{
//判断当前计数器计数方向
if(__HAL_TIM_IS_TIM_COUNTING_DOWN(tim_baseHandle))
{
//下溢
encoder1_overflow_count--;
}
else
{
//上溢
encoder1_overflow_count++;
}
}
}
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
需要添加的语句没有几条,网上资料又很多,而且还借鉴了例程,应该说一把就应该能跑通。但是实际烧录到板子上测试的时候,意想不到的事情发生了,完全读不到转速以及编码器脉冲数!
为什么会读不到脉冲?笔者首先想到的是,看一下硬件上有没有脉冲发过来。结果通过示波器测量,相应引脚始终为低电平,正常的情况下应该是源源不断的脉冲。
到这里就有两条路需要怀疑:硬件和软件。
先检查硬件上是不是有问题,发现如果编码器不接到相应的MCU引脚上,当电机旋转时,是可以产生脉冲的。这就排除了硬件的问题。
既然已经明确了是软件的问题,那么就需要仔细检查问题出在哪里,好在有能够正确工作的例程作为参考。仔细对比上述程序和例程的区别,将有区别的语句一一向例程看齐,尤其是GPIO初始化以及Timer初始化部分。代码部分包括了GPIO的Mode,Pull以及Timer的IC2Polarity等,都与例程保持了一致。再次编译并烧录程序,结果和之前一样,问题依旧!
又经过了反复调试,最终定位到,如果将上边代码中的HAL_TIM_Encoder_Start(&htim5, TIM_CHANNEL_ALL);及HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);封掉,则即使将编码器接到相应引脚上,脉冲也是OK的,不会出现之前始终为低电平的情况。但这两句话是开启编码器计数,是至关重要的。而且野火例程中,即使这两句程序不注释掉,也没有问题。这是什么原因?为什么同样的代码在人家的例程上就能够正确跑,而自己的代码却不行?
又经过了一番“折腾”,最终定位到是关键代码的位置放置得不对所导致的。将上边代码中HAL_TIM_Encoder_MspInit函数中的?/* USER CODE BEGIN TIM5_MspInit 1 */与?/* USER CODE END TIM5_MspInit 1 */之间的代码以及?/* USER CODE BEGIN TIM3_MspInit 1 */与/* USER CODE END TIM3_MspInit 1 */之间的代码(如下代码所示)分别挪到void MX_TIM5_Init(void)和void MX_TIM3_Init(void)的最后,这样就可以了。
void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(tim_encoderHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* TIM3 clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM3 GPIO Configuration
PA6 ------> TIM3_CH1
PA7 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* TIM3 interrupt Init */
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_MspInit 1 */
//清零计数器
__HAL_TIM_SET_COUNTER(&htim3, 0);
//清零中断标志位
__HAL_TIM_CLEAR_IT(&htim3, TIM_IT_UPDATE);
//使能定时器的更新事件中断
__HAL_TIM_ENABLE_IT(&htim3, TIM_IT_UPDATE);
//设置更新事件请求源为:计数器溢出
__HAL_TIM_URS_ENABLE(&htim3);
//设置中断优先级
HAL_NVIC_SetPriority(TIM3_IRQn, 5, 0);
//使能定时器中断
HAL_NVIC_EnableIRQ(TIM3_IRQn);
//使能编码器接口
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
/* USER CODE END TIM3_MspInit 1 */
}
else if(tim_encoderHandle->Instance==TIM5)
{
/* USER CODE BEGIN TIM5_MspInit 0 */
/* USER CODE END TIM5_MspInit 0 */
/* TIM5 clock enable */
__HAL_RCC_TIM5_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM5 GPIO Configuration
PA0-WKUP ------> TIM5_CH1
PA1 ------> TIM5_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM5;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN TIM5_MspInit 1 */
//清零计数器
__HAL_TIM_SET_COUNTER(&htim5, 0);
//清零中断标志位
__HAL_TIM_CLEAR_IT(&htim5, TIM_IT_UPDATE);
//使能定时器的更新事件中断
__HAL_TIM_ENABLE_IT(&htim5, TIM_IT_UPDATE);
//设置更新事件请求源为:计数器溢出
__HAL_TIM_URS_ENABLE(&htim5);
//设置中断优先级
HAL_NVIC_SetPriority(TIM5_IRQn, 5, 1);
//使能定时器中断
HAL_NVIC_EnableIRQ(TIM5_IRQn);
//使能编码器接口
HAL_TIM_Encoder_Start(&htim5, TIM_CHANNEL_ALL);
/* USER CODE END TIM5_MspInit 1 */
}
}
修改后的完整代码如下:
/**
******************************************************************************
* File Name : TIM.c
* Description : This file provides code for the configuration
* of the TIM instances.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "tim.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim5;
TIM_HandleTypeDef htim7;
TIM_HandleTypeDef htim8;
/* TIM2 init function */
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 1-1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 8400-1;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 6300;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim2);
}
/* TIM3 init function */
void MX_TIM3_Init(void)
{
TIM_Encoder_InitTypeDef sConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 65535;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0;
sConfig.IC2Polarity = TIM_ICPOLARITY_FALLING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0;
if (HAL_TIM_Encoder_Init(&htim3, &sConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
//清零计数器
__HAL_TIM_SET_COUNTER(&htim3, 0);
//清零中断标志位
__HAL_TIM_CLEAR_IT(&htim3, TIM_IT_UPDATE);
//使能定时器的更新事件中断
__HAL_TIM_ENABLE_IT(&htim3, TIM_IT_UPDATE);
//设置更新事件请求源为:计数器溢出
__HAL_TIM_URS_ENABLE(&htim3);
//设置中断优先级
HAL_NVIC_SetPriority(TIM3_IRQn, 5, 0);
//使能定时器中断
HAL_NVIC_EnableIRQ(TIM3_IRQn);
//使能编码器接口
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
}
/* TIM5 init function */
void MX_TIM5_Init(void)
{
TIM_Encoder_InitTypeDef sConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim5.Instance = TIM5;
htim5.Init.Prescaler = 0;
htim5.Init.CounterMode = TIM_COUNTERMODE_UP;
htim5.Init.Period = 65535;
htim5.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim5.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0;
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0;
if (HAL_TIM_Encoder_Init(&htim5, &sConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim5, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
//清零计数器
__HAL_TIM_SET_COUNTER(&htim5, 0);
//清零中断标志位
__HAL_TIM_CLEAR_IT(&htim5, TIM_IT_UPDATE);
//使能定时器的更新事件中断
__HAL_TIM_ENABLE_IT(&htim5, TIM_IT_UPDATE);
//设置更新事件请求源为:计数器溢出
__HAL_TIM_URS_ENABLE(&htim5);
//设置中断优先级
HAL_NVIC_SetPriority(TIM5_IRQn, 5, 1);
//使能定时器中断
HAL_NVIC_EnableIRQ(TIM5_IRQn);
//使能编码器接口
HAL_TIM_Encoder_Start(&htim5, TIM_CHANNEL_ALL);
}
/* TIM7 init function */
void MX_TIM7_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim7.Instance = TIM7;
htim7.Init.Prescaler = 8400-1;
htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
htim7.Init.Period = 1000-1;
htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim7) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim7, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
/* TIM8 init function */
void MX_TIM8_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
htim8.Instance = TIM8;
htim8.Init.Prescaler = 2-1;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 8400-1;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim8) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim8) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 6300;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim8);
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */
/* USER CODE END TIM2_MspInit 0 */
/* TIM2 clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
/* USER CODE BEGIN TIM2_MspInit 1 */
/* USER CODE END TIM2_MspInit 1 */
}
else if(tim_baseHandle->Instance==TIM7)
{
/* USER CODE BEGIN TIM7_MspInit 0 */
/* USER CODE END TIM7_MspInit 0 */
/* TIM7 clock enable */
__HAL_RCC_TIM7_CLK_ENABLE();
/* TIM7 interrupt Init */
HAL_NVIC_SetPriority(TIM7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM7_IRQn);
/* USER CODE BEGIN TIM7_MspInit 1 */
/* USER CODE END TIM7_MspInit 1 */
}
else if(tim_baseHandle->Instance==TIM8)
{
/* USER CODE BEGIN TIM8_MspInit 0 */
/* USER CODE END TIM8_MspInit 0 */
/* TIM8 clock enable */
__HAL_RCC_TIM8_CLK_ENABLE();
/* USER CODE BEGIN TIM8_MspInit 1 */
/* USER CODE END TIM8_MspInit 1 */
}
}
void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(tim_encoderHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* TIM3 clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM3 GPIO Configuration
PA6 ------> TIM3_CH1
PA7 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* TIM3 interrupt Init */
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_MspInit 1 */
/* USER CODE END TIM3_MspInit 1 */
}
else if(tim_encoderHandle->Instance==TIM5)
{
/* USER CODE BEGIN TIM5_MspInit 0 */
/* USER CODE END TIM5_MspInit 0 */
/* TIM5 clock enable */
__HAL_RCC_TIM5_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM5 GPIO Configuration
PA0-WKUP ------> TIM5_CH1
PA1 ------> TIM5_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM5;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN TIM5_MspInit 1 */
/* USER CODE END TIM5_MspInit 1 */
}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(timHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspPostInit 0 */
/* USER CODE END TIM2_MspPostInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**TIM2 GPIO Configuration
PB10 ------> TIM2_CH3
PB11 ------> TIM2_CH4
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN TIM2_MspPostInit 1 */
/* USER CODE END TIM2_MspPostInit 1 */
}
else if(timHandle->Instance==TIM8)
{
/* USER CODE BEGIN TIM8_MspPostInit 0 */
/* USER CODE END TIM8_MspPostInit 0 */
__HAL_RCC_GPIOC_CLK_ENABLE();
/**TIM8 GPIO Configuration
PC6 ------> TIM8_CH1
PC7 ------> TIM8_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* USER CODE BEGIN TIM8_MspPostInit 1 */
/* USER CODE END TIM8_MspPostInit 1 */
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspDeInit 0 */
/* USER CODE END TIM2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM2_CLK_DISABLE();
/* USER CODE BEGIN TIM2_MspDeInit 1 */
/* USER CODE END TIM2_MspDeInit 1 */
}
else if(tim_baseHandle->Instance==TIM7)
{
/* USER CODE BEGIN TIM7_MspDeInit 0 */
/* USER CODE END TIM7_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM7_CLK_DISABLE();
/* TIM7 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM7_IRQn);
/* USER CODE BEGIN TIM7_MspDeInit 1 */
/* USER CODE END TIM7_MspDeInit 1 */
}
else if(tim_baseHandle->Instance==TIM8)
{
/* USER CODE BEGIN TIM8_MspDeInit 0 */
/* USER CODE END TIM8_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM8_CLK_DISABLE();
/* USER CODE BEGIN TIM8_MspDeInit 1 */
/* USER CODE END TIM8_MspDeInit 1 */
}
}
void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef* tim_encoderHandle)
{
if(tim_encoderHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspDeInit 0 */
/* USER CODE END TIM3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM3_CLK_DISABLE();
/**TIM3 GPIO Configuration
PA6 ------> TIM3_CH1
PA7 ------> TIM3_CH2
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_6|GPIO_PIN_7);
/* TIM3 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_MspDeInit 1 */
/* USER CODE END TIM3_MspDeInit 1 */
}
else if(tim_encoderHandle->Instance==TIM5)
{
/* USER CODE BEGIN TIM5_MspDeInit 0 */
/* USER CODE END TIM5_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM5_CLK_DISABLE();
/**TIM5 GPIO Configuration
PA0-WKUP ------> TIM5_CH1
PA1 ------> TIM5_CH2
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1);
/* USER CODE BEGIN TIM5_MspDeInit 1 */
/* USER CODE END TIM5_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/*
* @brief 定时器更新事件回调函数
* @param 无
* @retval 无
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *tim_baseHandle) //定时器中断回调
{
if(tim_baseHandle->Instance == TIM6)
{
}
else if(tim_baseHandle->Instance == TIM7)
{
static uint16_t i = 0;
i++;
if(i >= 5) //500ms计算一次
{
i = 0;
if(encoder_init_finished == 1)
{
//电机1旋转方向 = 计数器1计数方向
motor1_direction = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim5);
//当前时刻总计数值 = 计数器值 + 计数溢出次数 * ENCODER_TIM_PERIOD
capture_count1 = __HAL_TIM_GET_COUNTER(&htim5) + (encoder1_overflow_count * 65535);
//转轴转速1 = 单位时间内的计数值 / 编码器总分辨率 * 时间系数
//shaft1_speed = (float)(capture_count1 - last_count1) / ENCODER_TOTAL_RESOLUTION * 10;
shaft1_speed = (float)(capture_count1 - last_count1) / ENCODER_TOTAL_RESOLUTION * 2;
//电机2旋转方向 = 计数器2计数方向
motor2_direction = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3);
//当前时刻总计数值 = 计数器值 + 计数溢出次数 * ENCODER_TIM_PERIOD
capture_count2 = __HAL_TIM_GET_COUNTER(&htim3) + (encoder2_overflow_count * 65535);
//转轴转速2 = 单位时间内的计数值 / 编码器总分辨率 * 时间系数
//shaft2_speed = (float)(capture_count2 - last_count2) / ENCODER_TOTAL_RESOLUTION * 10;
shaft2_speed = (float)(capture_count2 - last_count2) / ENCODER_TOTAL_RESOLUTION * 2;
printf("电机1方向:%d\r\n", motor1_direction);
printf("单位时间内有效计数值:%d\r\n", capture_count1 - last_count1); //单位时间计数值 = 当前时刻总计数值 - 上一时刻总计数值
printf("电机1转轴处转速:%.2f 转/秒\r\n", shaft1_speed);
printf("电机1输出轴转速:%.2f 转/秒\r\n", shaft1_speed / REDUCTION_RATIO); //输出轴转速 = 转轴转速 / 减速比
printf("电机2方向:%d\r\n", motor2_direction);
printf("单位时间内有效计数值:%d\r\n", capture_count2 - last_count2); //单位时间计数值 = 当前时刻总计数值 - 上一时刻总计数值
printf("电机2转轴处转速:%.2f 转/秒\r\n", shaft2_speed);
printf("电机2输出轴转速:%.2f 转/秒\r\n\n", shaft2_speed / REDUCTION_RATIO); //输出轴转速 = 转轴转速 / 减速比
//记录当前总计数值,供下一时刻计算使用
last_count1 = capture_count1;
last_count2 = capture_count2;
}
}
}
else if(tim_baseHandle->Instance == TIM3)
{
//判断当前计数器计数方向
if(__HAL_TIM_IS_TIM_COUNTING_DOWN(tim_baseHandle))
{
//下溢
encoder2_overflow_count--;
}
else
{
//上溢
encoder2_overflow_count++;
}
}
else if(tim_baseHandle->Instance == TIM5)
{
//判断当前计数器计数方向
if(__HAL_TIM_IS_TIM_COUNTING_DOWN(tim_baseHandle))
{
//下溢
encoder1_overflow_count--;
}
else
{
//上溢
encoder1_overflow_count++;
}
}
}
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
?虽然问题解决了,但是还要深入探究调整顺序能够解决问题的具体原因。内容参见在下一篇文章。
|