專案中使用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****/
雖然問題解決了,但是還要深入探究調整順序能夠解決問題的具體原因,內容參見在下一篇文章,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/356177.html
標籤:其他
下一篇:物聯網 - 從零到一實作新手入門
