读取STM32定时器的值

3
我正在使用STM32F103芯片,试图配置和使用其中一个定时器。我已经使用STM32CubeMX生成了初始化Timer 2的代码。我通过调用HAL_TIM_Base_Start来启动计时器。然后,在循环中,我通过调用htim2.Instance->CNT或调用宏__HAL_TIM_GetCounter(我认为它只返回相同的值)来打印出当前的计时器值。但无论我做什么,计数值都显示为零。我也尝试在开头调用__TIM2_CLK_ENABLE(),但没有任何区别。
我已经搜索了解决方案,发现了一些关于这个问题的问题,但没有找到解决方法。
有人知道我做错了什么吗?
谢谢。
这是初始化定时器的例程。此代码由STM32CubeMX生成,我没有修改它:
/* TIM2 init function */
static void MX_TIM2_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 0;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

然后在主函数中,我尝试启动计时器并打印出它的值。这是我用来执行此操作的代码:

__TIM2_CLK_ENABLE();;
HAL_TIM_Base_Start(&htim2);

while (true)
{
    Serial.println((long) __HAL_TIM_GetCounter(&htim2));
    delay(100);
}

“Serial”类是我编写的一个类,通过USB串口与我的电脑通信。

发布代码比描述代码更清晰明了。 - chux - Reinstate Monica
你是否在任何地方启用了tim2的时钟?如果你正在使用HAL,它将是一个名为RCCAPB1ClkCmd的调用。 - Colin
如果你有调试器,请尝试更改任何TIM2寄存器的值。如果它发生了变化,那么时钟就被启用了。 - 0___________
我在代码中找不到名为RCCAPB1ClkCmd的任何函数,而在互联网上搜索也没有返回结果。你能给我更多关于它的信息吗? - John Gaby
请原谅我,我不熟悉ST库(我不使用它们,只是遵循数据手册),该函数可能是 RCC_APB1PeriphClockCmd - Colin
显示剩余4条评论
4个回答

7
< p > 不使用 HAL 也不复杂,请试试。 < /p >
void start_TIM2() {
  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
  TIM2->CR1 |= TIM_CR1_EN;
}

uint16_t read_TIM2() {
  return TIM2->CNT;
}

TIM_CR1_EN 没有定义,但我发现 TIM_CR1_CEN,其注释表明它是计时器使能。我尝试了一下,但计数总是得到零。此外,在查看 HAL 代码时,我已经拥有的两行代码似乎与上面的代码执行相同的操作。这里必定有些基础知识我没有掌握。 - John Gaby
实际上,我最终通过注释由STM32CubeMX生成的计时器初始化代码来使其正常工作,因此看起来它所做的任何事情都是不正确的。 - John Gaby

2

Setting the value of

htim2.Init.Period = 0;

“zero initializes the auto reload register (ARR)”的意思是将自动重装载寄存器(ARR)初始化为0,这并不是CubeMX中一个非常方便的默认选择,你可能想要一个ARR值为0xFFFFFFFF

接受的回答依赖于复位后ARR值为0xFFFFFFFF,但没有提到它,如果你问我,那只是运气比智慧更重要。


1

ARR(htim2.Init.Period)不应该为0。它会尝试计数直到... 0!在那里放置一些16位整数。祝好运!


最好在你的回答旁边放一些代码。 - Masoud Rahimi

0

我会向您展示一些需要记住的公式:(参考:AN4776)

. Frequency = Fclk(timer) / (prescaler + 1)

例如,您选择了预分频器=0,这意味着您的计时器在1 / 80MHz的周期内完成计数[0:count),如果系统时钟配置为此(您应该检查时钟和预分频器的值以确定更新频率)。
. #1_count(s) = 1 / Frequency

. period(s) = #1_count * (counter + 1) 

--> 让我们通过一个例子来看看:

系统时钟为72MHz,需要一个1微秒分辨率的计时器和1毫秒周期。

. 对于1微秒的分辨率 -> 频率=1MHz

'1MHz = 72MHz / (prescaler + 1)' -> prescaler = 71 

为了让定时器每毫秒中断一次,我们必须计算它应该计数多少:
'1ms = 1us * (counter + 1)' -> count = 999

使用这些值,我们配置如下:

htim2.Init.Prescaler = 71;

htim2.Init.Period = 999;

计时器将从0:999开始,每步为1微秒。

您的代码存在两个问题,计时器频率过高且仅从0:1开始计数,因此您永远无法看到计数增加。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接