STM32F769I-DISCO上的1s定时器

STM32F769I-DISCO上的1s定时器,c,timer,embedded,stm32,stm32f7,C,Timer,Embedded,Stm32,Stm32f7,我正在尝试使用STM32 HAL库在STM32F69I发现板上设置1s led闪烁。我已按以下方式设置计时器: __TIM2_CLK_ENABLE(); s_TimerInstance.Init.Prescaler = (216000); s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP; s_TimerInstance.Init.Period = (1000); s_TimerInstance.Init.ClockDivision =

我正在尝试使用STM32 HAL库在STM32F69I发现板上设置1s led闪烁。我已按以下方式设置计时器:

__TIM2_CLK_ENABLE();
s_TimerInstance.Init.Prescaler = (216000);
s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP;
s_TimerInstance.Init.Period = (1000);
s_TimerInstance.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
s_TimerInstance.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&s_TimerInstance);
HAL_TIM_Base_Start(&s_TimerInstance);
然后我用以下方式切换LED:

int main() {
    for (;;) {
        int timerValue = __HAL_TIM_GET_COUNTER(&s_TimerInstance);
        if (timerValue == 800)
            HAL_GPIO_WritePin(GPIOJ, (LED_GREEN | LED_RED), GPIO_PIN_SET);
        if (timerValue == 1000)
            HAL_GPIO_WritePin(GPIOJ, (LED_GREEN | LED_RED), GPIO_PIN_RESET);
        }
}
MCU时钟应为216 mHz。我的逻辑是,如果我将预分频器设置为216000,这意味着我的计时器将每秒增加2160000/216000=1000。也就是说,如果我将周期设置为1000,我的LED应该每秒钟闪烁一次。但是,它们每1.1-1.2秒闪烁一次

我对预分频器和周期的理解是否完全错误,或者我遗漏了什么


编辑:216000-1和&1000-1没有任何明显的区别。老实说,我在这方面是一个完全的初学者,所以我通过看到它不同于普通的“挂钟”来确认这一点,因为我不知道如何调试它。代码中没有其他部分,只有这些。我在216mHz上运行,因为STM网站上说STM32F769I的MCU在216上运行,所以我假设我的计时器也是。不管是不是真的,我都无法破译。我也没有在timer结构中找到任何可以设置时钟频率的设置。

请尝试以下非常复杂的代码:

TIM2 -> PSC = 21600 - 1;
TIM2 -> EGR = TIM_EGR_UG;
TIM2 -> CR1 |= TIM_CR1_CEN;

while(1) {
    if(TIM2 -> CNT >= 10000) 
    {
        TIM2 -> CNT = 0;
        ToggleLed();
    }
}

用您的实际代码替换Toggled(这当然会切换LED)

STM32F769NI可以在最大216 MHz的频率下运行,但重置时默认选择16 MHz内部RC振荡器。见本文件第2.15节

TIM2有一个16位预分频器。见数据表第2.23.2节

216000(0x34BC0)太大,无法装入16位预分频器。在您的程序中,它将被截断为0x4BC0或19392

16 MHz/19392=825.1 Hz或每秒0.001212滴答声

每秒0.001212个滴答声乘以1000个滴答声=1.212秒


将您的预分频器更改为(16000-1),因为您的时钟实际运行频率为16 MHz,而不是216 MHz。

我不使用API,因为外围设备通常更容易直接编程(其他人不同意)(我建议尝试这两种方式并选择您自己的偏好)。所以我会将计时器设置为自由运行,并在最大计数时翻滚,然后可能会选择一些位,如果设置了led,则清除led,取出计算器(是的,带有真实按钮和所有内容),并进行数学运算,以确认它是合理的。然后让计时器计数到某个值并在那里滚动,轮询滚动/中断位,重复实验,然后最终进入中断。led闪烁是裸机的printf(“hello world”)。像这样的练习是一次性代码,但您可以查看系统时钟和外围设备之间是否有预定标器。如果是这样的话,你可以在文档中翻找,看看它是否有文档记录,是否可编程,是否有规则(没有理由假设外围设备可以在216Mhz下运行,也许只有arm核心可以运行那么快),等等等等等等……用足够长的led闪烁率(比如整整一分钟)对n对n-1进行编程相对于秒表,你通常可以算出n对n-1。你的错误对于一秒钟的超时216mhz或不超时来说有点大……因此这很奇怪,但可能是非常简单的事情,一旦你找到它,它就会有意义。没有什么是显而易见的,因此所有的问题。基本问题。那么,你的一个时钟是不是错了,芯片上的那一个是你手里的那一个,你怎么用你手里的那一个呢?你有没有可能在十分之一秒的时间内关机(不过这并不一致,而且会回答这个问题)。是芯片上的时钟吗?可能不是,是设置,可能是…所以我假设这是一个32位的定时器,而不是16位的定时器?如果您将216000发送给一个16位或更少的预分频器,或者一个不接受特定值但仅接受2的幂的预分频器,人们希望init调用会抱怨。这些init调用是否有返回值,如果检查这些返回值是否有错误,该怎么办?@Nirri:-1因为这样说:“计数器时钟频率CK_CNT等于fCK_PSC/(PSC[15:0]+1)。”这只是另一个计数器,它从预设值下降到0,并在溢出时使主计数器前进,有效地将输入频率除以x+1。当预分频器为0时,它被1除,而不是0。@Nirri:用这种方式截断是C语言中的标准行为,@PeterJ:这是一个完整且合理的答案,解决了原始帖子中的问题和其他问题。这正是SO的目的,以获得正确答案时可以投票的答案,而不必费力地浏览30多条评论以找到一些可能有用的提示。@berendi好的,看来STM32F7Cube手册中有更多关于更改时钟速度的信息,谢谢。你看了吗?它们位于董事会的
Projects/STM32F769I Discovery/Examples
目录中。谢谢你,威尔,想先编写HAL版本,也一定会做到这一点:)忘记用于GPIO、SPI、U(S)ART、定时器和其他类似设备的HAL。即使是以太网或usb也必须非常小心地使用,因为它过去/现在充满了漏洞。我只在这两个外设上使用它。@PeterJ:不确定USB,但如果没有HAL/STlib膨胀软件,以太网也会更容易。作为另一个好处,它的速度要快得多(如果使用基于中断/事件的编程,则与此相关)。