1. 例程背景
用的步进电机,功能调试完成,能走能停的。但是出现 走的距离并不是实际的物理长度,总是出现或大或小的偏差,造成精度不高。 由于没有用到编码器,作为输出反馈,只能决定先做个实验,捕获下实际输出的脉冲数量。用的 TIM ETR。
STM32F429IGT6, 根据板子情况,选择PA5,TIM2_ETR,
2.配置
parameter settings 默认。 gpio settings 中的上下拉根据自己的电路情况设置。 NVIC 用到的,也要设置。 另外,根据自己电路情况,输入有光耦隔离的,要注意自己光耦器件的电源要不要代码控制,我电路的光耦电源是要自己写代码驱动的。默认板子光耦是无电源的。因此输入是无效的。
3. 生成代码
直接生成代码就可以了。引脚重映射代码里也自动配置好,不用额外代码
#include "tim.h"
TIM_HandleTypeDef htim2;
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 0xffffffff;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE2;
sClockSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_NONINVERTED;
sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;
sClockSourceConfig.ClockFilter = 0;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_Base_Start(&htim2);
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(tim_baseHandle->Instance==TIM2)
{
__HAL_RCC_TIM2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM2)
{
__HAL_RCC_TIM2_CLK_DISABLE();
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5);
}
}
使用的使用,需启动定时器
HAL_TIM_Base_Start(&htim2);
uint32_t n_Counter1;
static void TIM2_ETRGetCounter(void)
{
n_Counter1 = htim2.Instance->CNT;
}
4. 补充
4.1.HAL库不需要重映射
标准库中 F4 需要 GPIO_PinAFConfig(ETR_GPIO_PORT,GPIO_PinSource5,GPIO_AF_TIM2); 但是 HAL库不用,因为HAL_GPIO_Init时,已经做好
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{
..........................
if((GPIO_Init->Mode & GPIO_MODE) == MODE_AF)
{
assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
temp = GPIOx->AFR[position >> 3U];
temp &= ~(0xFU << ((uint32_t)(position & 0x07U) * 4U)) ;
temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & 0x07U) * 4U));
GPIOx->AFR[position >> 3U] = temp;
}
temp = GPIOx->MODER;
temp &= ~(GPIO_MODER_MODER0 << (position * 2U));
temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2U));
GPIOx->MODER = temp;
..........................
}
4.2 HAL库不需要添加TIM ETR设置代码
标准库中 TIM_ETRClockMode2Config(GENERAL_TIM, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0); HAL库中 定时器时钟源配置时,已经设置
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE2;
sClockSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_NONINVERTED;
sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;
sClockSourceConfig.ClockFilter = 0;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, TIM_ClockConfigTypeDef *sClockSourceConfig)
{
switch (sClockSourceConfig->ClockSource)
{
case TIM_CLOCKSOURCE_ETRMODE2:
{
assert_param(IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(htim->Instance));
assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler));
assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
TIM_ETR_SetConfig(htim->Instance,
sClockSourceConfig->ClockPrescaler,
sClockSourceConfig->ClockPolarity,
sClockSourceConfig->ClockFilter);
htim->Instance->SMCR |= TIM_SMCR_ECE;
break;
}
}
}
所以STM32CubeMX生成代码后,直接启动定时器就可以了。
HAL_TIM_Base_Start(&htim2);
|