[STM32F429IGT6]-TIM ETR 计数

1.通用定时器时钟源

在这里插入图片描述

而我们要用的 ETR功能就属于 ,外部时钟模式2:外部触发输入ETR。

2. 外部触发输入ETR

	外部时钟模式2:外部触发输入ETR

在这里插入图片描述
在这里插入图片描述

3.TIM ETR 例程

使用步骤:

1)TIMx_SMCR寄存器中的ETF[3:0]用来设置滤波器。

2)TIMx_SMCR寄存器中的ETPS[1:0]设置预分频器,即多少个边沿触发一次计数。

3)置TIMx_SMCR寄存器中的ETP设置上升沿或下降沿计数。

4)令TIMx_SMCR寄存器中的ECE=1选定此模式。

5)启动计数器,写TIMx_CR1寄存器中的CEN=1。

3.1 例程背景

用的步进电机,功能调试完成,能走能停的。但是出现 走的距离并不是实际的物理长度,总是出现或大或小的偏差,造成精度不高。
由于没有用到编码器,作为输出反馈,只能决定先做个实验,捕获下实际输出的脉冲数量。用的 TIM ETR。

STM32F429IGT6, 根据板子情况,选择PA5,TIM2_ETR,
在这里插入图片描述
在这里插入图片描述

3.2 程序示例

3.2.1 标准库函数

1)F4和F1的复用功能部分不一样。F4要额外添加复位功能映射代码,才能开启此功能。
2)注意计数溢出处理。︿( ̄︶ ̄)︿F429IGT6 ARR是32bit 的

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_TIM2);
#define GENERAL_TIM           		TIM2
#define GENERAL_TIM_CLK       		RCC_APB1Periph_TIM2

#define GENERAL_TIM_IRQn		  TIM2_IRQn
#define GENERAL_TIM_IRQHandler    TIM2_IRQHandler

#define ETR_PIN                  GPIO_Pin_5                 
#define ETR_GPIO_PORT            GPIOA                      
#define ETR_GPIO_CLK             RCC_AHB1Periph_GPIOA
static void TIM_Mode_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    
    RCC_APB1PeriphClockCmd(GENERAL_TIM_CLK, ENABLE); 
    RCC_AHB1PeriphClockCmd ( ETR_GPIO_CLK, ENABLE); 
    
    GPIO_InitStructure.GPIO_Pin = ETR_PIN ;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // F4和F1的复用功能部分不一样
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_Init(ETR_GPIO_PORT, &GPIO_InitStructure);
    
    GPIO_PinAFConfig(ETR_GPIO_PORT,GPIO_PinSource5,GPIO_AF_TIM2); // F4和F1的复用功能部分不一样
    
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF;       
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
	
    TIM_ETRClockMode2Config(GENERAL_TIM, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);   
     
    TIM_SetCounter(GENERAL_TIM, 0);   
	TIM_Cmd(GENERAL_TIM, ENABLE);	
}
u32 n_Counter1;
int main(void) 
{
.......
  
  while(1)
  {   
        n_Counter1 = TIM_GetCounter(GENERAL_TIM); //读取CNT寄存器   
  }
}

我是对要发的脉冲数进行计数,对比看理论和实际是否一致。没有用到中断,没有处理溢出。
用中断的话,要添加代码。

static void TIMx_NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure; 
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);		
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; 	
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;	
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
TIM_ClearITPendingBit(GENERAL_TIM,TIM_IT_Update);  //清除中断标志位,避免第一次自动进入中断一次
TIM_ITConfig(GENERAL_TIM,TIM_IT_Update,ENABLE);
u32 overflow_cnt=0;
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(GENERAL_TIM,TIM_IT_Update) == SET) 
{
overflow_cnt++;
//具体的处理使用
}
TIM_ClearITPendingBit(GENERAL_TIM,TIM_IT_Update);  
}

3.2.2 HAL库函数

STM32CubeMX配置TIM ETR
在这里插入图片描述
parameter settings 默认。
gpio settings 中的上下拉根据自己的电路情况设置。
NVIC 用到的,也要设置。
另外,根据自己电路情况,输入有光耦隔离的,要注意自己光耦器件的电源要不要代码控制,我电路的光耦电源是要自己写代码驱动的。默认板子光耦是无电源的。因此输入是无效的。
在这里插入图片描述
直接生成代码就可以了。
引脚重映射代码里也自动配置好,不用额外代码

/* Includes ------------------------------------------------------------------*/
#include "tim.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

TIM_HandleTypeDef htim2;

/* TIM2 init function */
void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  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();
  }
  /* USER CODE BEGIN TIM2_Init 2 */
  HAL_TIM_Base_Start(&htim2); //非自动生成
  /* USER CODE END TIM2_Init 2 */

}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  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();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**TIM2 GPIO Configuration
    PA5     ------> TIM2_ETR
    */
    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);

  /* USER CODE BEGIN TIM2_MspInit 1 */

  /* USER CODE END TIM2_MspInit 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();

    /**TIM2 GPIO Configuration
    PA5     ------> TIM2_ETR
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5);

  /* USER CODE BEGIN TIM2_MspDeInit 1 */

  /* USER CODE END TIM2_MspDeInit 1 */
  }
}


使用的使用,需启动定时器

/* USER CODE BEGIN 1 */
/*启动定时器*/
HAL_TIM_Base_Start(&htim2);

uint32_t n_Counter1;
static void TIM2_ETRGetCounter(void)
{
    n_Counter1 = htim2.Instance->CNT;  
    /*标准库获取计数器值用TIM_GetCounter函数,HAL函数中,没找到,直接调用值即可*/
}
/* USER CODE END 1 */

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)
{
..........................
	 /* In case of Alternate function mode selection */
      if((GPIO_Init->Mode & GPIO_MODE) == MODE_AF)
      {
        /* Check the Alternate function parameter */
        assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
        /* Configure Alternate function mapped with the current IO */
        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;
      }

      /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
      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();
  }

/**
  * @brief   Configures the clock source to be used
  * @param  htim TIM handle
  * @param  sClockSourceConfig pointer to a TIM_ClockConfigTypeDef structure that
  *         contains the clock source information for the TIM peripheral.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, TIM_ClockConfigTypeDef *sClockSourceConfig)
{
	  switch (sClockSourceConfig->ClockSource)
 	 {
 	 	 case TIM_CLOCKSOURCE_ETRMODE2:
	    {
	      /* Check whether or not the timer instance supports external trigger input mode 2 (ETRF)*/
	      assert_param(IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(htim->Instance));
	
	      /* Check ETR input conditioning related parameters */
	      assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler));
	      assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
	      assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
	
	      /* Configure the ETR Clock source */
	      TIM_ETR_SetConfig(htim->Instance,
	                        sClockSourceConfig->ClockPrescaler,
	                        sClockSourceConfig->ClockPolarity,
	                        sClockSourceConfig->ClockFilter);
	      /* Enable the External clock mode2 */
	      htim->Instance->SMCR |= TIM_SMCR_ECE;
	      break;
	    }
 	 }
}

所以STM32CubeMX生成代码后,直接启动定时器就可以了。

/*启动定时器*/
HAL_TIM_Base_Start(&htim2);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值