嵌入式开发二十:定时器之基本定时器

news2025/2/25 2:40:10

        定时器是微控制器中的关键外设,用于精确控制时间和事件。通过配置时钟源、预分频器、计数周期和比较值,可以实现各种时间控制任务,如定时中断、PWM生成和时间测量。理解定时器的工作原理和配置方法是嵌入式系统开发中的基本技能。 STM32F407 有众多的定时器,其中包括 2 个基本定时器(TIM6 和 TIM7)、10 个通用定时 器(TIM2~TIM5、TIM9~TIM14)、2 个高级控制定时器(TIM1 和 TIM8),这些定时器彼此完 全独立,不共享任何资源。本篇博客我们学习如何使用 STM32F407 的基本定时器中断。我们将使用 TIM6 的定时器中断来控制 LED0的翻转。

目录

一、TIM 简介

1.1 定时器的用途

1.2 STM32F4的定时器资源

1.3 定时器的理解

二、基本定时器

2.1 基本定时器简介

2.2 基本定时器功能框图

2.2.1 时钟源

2.2.2 控制器

2.2.3 时基单元(重点)

2.3 基本定时器的寄存器

2.3.1 控制寄存器 1(TIMx_CR1)

2.3.2 DMA/中断使能寄存器(TIMx_DIER)

2.3.3 状态寄存器(TIMx_SR)

2.3.4 计数器寄存器(TIMx_CNT)

2.4.5 预分频寄存器(TIMx_PSC)

2.4.6 自动重载寄存器(TIMx_ARR)

2.5 定时器周期的计算(定时时间计算)

2.6 定时器初始化结构体详解

2.7 基本定时器中断

2.7.1 基本定时器中断应用

2.7.2 基本定时器中断配置步骤

三、使用基本定时器实现定时3秒,触发中断。


一、TIM 简介

1.1 定时器的用途

        定时器(Timer)最基本的功能就是定时了,比如定时发送 USART 数据、定时采集 AD 数据等等。如果把定时器与 GPIO 结合起来使用的话可以实现非常丰富的功能,可以测量输入信号的脉冲宽度,可以生产输出波形定时器生产 PWM 控制电机状态是工业控制普遍方法,这方面知识非常有必要深入了解。下面对定时器的用途做个简单介绍:

STM32F4系列微控制器的定时器具有广泛的用途。以下是一些常见的用途:

1. 基本定时器(TIM6 和 TIM7)

  • 简单计时:用于生成定时中断。
  • DAC 触发:用于触发数模转换(DAC)。

2. 通用定时器(TIM2, TIM3, TIM4, TIM5)

  • 输入捕获:捕获外部信号的时间戳,常用于测量脉冲宽度或频率。
  • 输出比较:生成精确的PWM信号或用于定时事件的输出控制。
  • PWM 生成:用于控制伺服电机、LED 调光等。
  • 单脉冲模式:生成精确的单个脉冲信号。
  • 编码器接口:用于连接旋转编码器,以测量旋转角度或速度。

3. 高级定时器(TIM1 和 TIM8)

  • PWM 生成:生成多通道高精度的PWM信号。
  • 死区控制:用于驱动电机的H桥,提供死区时间以避免短路。
  • 复杂的捕获/比较功能:适用于高级运动控制应用。
  • 三相互补PWM:用于控制三相电机。

具体用途示例

1. 延时和定时中断

         利用定时器产生精确的时间延时和定时中断。例如,定时器可以设置为每隔1ms触发一次中断,用于实现操作系统的滴答时钟。

2. PWM 信号生成

        PWM(脉宽调制)信号用于控制伺服电机、LED亮度等。通过调整PWM的占空比,可以精确控制电机的速度或LED的亮度。

3. 输入捕获

       捕获外部信号的时间特征,如脉冲宽度和频率。比如,可以用来测量超声波传感器的回波时间,以确定距离。

4. 脉冲计数

       用于计数外部脉冲信号,常用于旋转编码器以测量旋转角度或速度。

5. 单脉冲模式

       生成精确的单个脉冲信号,可用于雷达系统中发送脉冲信号。

6. 编码器接口

        与增量式旋转编码器接口,用于运动控制中精确测量位置和速度。

7. 触发ADC/DAC

         定时器可以用来触发ADC(模数转换)和DAC(数模转换),实现定时采样和输出。

8. 定时器同步

        多个定时器之间可以同步运行,适用于需要精确协调的控制系统。

9. 电机控制

         通过生成复杂的PWM信号和控制死区时间,实现对三相电机的精确控制。

1.2 STM32F4的定时器资源

         STM32F42xxx 系列控制器有 2 个高级定时器、10 个通用定时器和 2 个基本定时器, 还有 2 个看门狗定时器。看门狗定时器不在本次讨论范围。控制器上所有定时器都是彼此独立的,不共享任何资源。各个定时器特性参考表 如下所示。

1.3 定时器的理解

 定时器 = 精准的时基 + 硬件电路。

  1. 分频模块(PSC):对外来的时钟进⾏分频。
  2. 计数模块(CNT):对来⾃分频模块输出的时钟脉冲进⾏计数。
  3. ⾃动重装载模块(ARR):它存储的是计数器的⽬标值,计数器每次累加就⽐较⼆者,⼆者相等计数器溢 出,当计数器溢出时,然后清零计数器寄存器。

二、基本定时器

2.1 基本定时器简介

       STM32F407 有两个基本定时器 TIM6 和 TIM7,它们的功能完全相同,资源是完全独立的, 可以同时使用。其主要特性如下:16 位自动重载递增计数器,16 位可编程预分频器,预分频系数 1~65536,用于对计数器时钟频率进行分频。

  1. 可以发出⼀个触发信号,触发DAC进行数模转换的同步电路;
  2. 可以在事件更新时(计数器溢出),可以产生中断 和 DMA请求。

       基本上定时器 TIM6 和 TIM7 是一个 16 位向上递增的定时器,当我在自动重载寄存器 (TIMx_ARR)添加一个计数值后并使能 TIMx,计数寄存器(TIMx_CNT)就会从 0 开始递增, 当 TIMx_CNT 的数值与 TIMx_ARR 值相同时就会生成事件并把 TIMx_CNT 寄存器清 0, 完成一次循环过程。如果没有停止定时器就循环执行上述过程。这些只是大概的流程,希望大家有个感性认识,下面会细讲整个过程。

2.2 基本定时器功能框图

       STM32F407 基本定时器由时钟源、控制器、时基单元组成。下面先来学习基本定时器框图,通过学习基本定时器框图会有一个很好的整体掌握,同时 对之后的编程也会有一个清晰的思路。

         首先先看最下面红色框内容,第一个是带有阴影的方框,方框内容一般是一个寄存器名称,比如图中主体部分的自动重载寄存器(TIMx_ARR)或 PSC 预分频器(TIMx_PSC), 这里要特别突出的是阴影这个标志的作用,它表示这个寄存器还自带有影子寄存器,在硬件结构上实际是有两个寄存器,源寄存器是我们可以进行读写操作,而影子寄存器我们是完全无法操作的,有内部硬件使用。影子寄存器是在程序运行时真正起到作用的,源寄存器只是给我们读写用的,只有在特定时候(特定事件发生时)才把源寄存器的值拷贝给它的影子寄存器。多个影子寄存器一起使用可以到达同步更新多个寄存器内容的目的。

        接下来是一个指向右下角的图标,它表示一个事件,而一个指向右上角的图标表示中断和 DMA 输出。这个我们把它放在图中主体更好理解。图中的自动重载寄存器有影子寄存器,它左边有一个带有“U”字母的事件图标,表示在更新事件生成时就把自动重载寄存器内容拷贝到影子寄存器内,这个与上面分析是一致。寄存器右边的事件图标、中断和 DMA 输出图标表示在自动重载寄存器值与计数器寄存器值相等时生成事件、中断和 DMA 输出。

2.2.1 时钟源

       定时器的核心就是计算器,要实现计数功能,首先要给它一个时钟源基本定时器时钟挂载在 APB1 总线,所以它的时钟来自于 APB1 总线,但是基本定时器时钟不是直接由 APB1 总线直接提供,而是先经过一个倍频器。当 APB1 的预分频器系数为 1 时,这个倍频器系数为 1, 即定时器的时钟频率等于 APB1 总线时钟频率;当 APB1 的预分频器系数≥2 分频时,这个倍 频器系数就为 2 , 即定 时 器 的 时 钟 频 率 等于 APB1 总 线 时 钟 频率 的 两 倍 。回忆我们前面讲的时钟树简图如下所示:

我们知道APB1的分频系数为4,≥2,所以,倍频系数为2,基本定时器的时钟源为 42 x2=84MHZ。

【注解】:

1、为什么要在APB1总线和定时器之间加⼀个倍频器?

      首先,我们的时钟是⼀个外设且挂载 在APB1总线上,但是我们总线上又挂载着其他外设。其他外设⼯作可能不要很⾼的时钟频率,所以设计 这个倍频器就可以在保证其他外设使⽤较低时钟频率时,定时器仍可以获得较⾼的时钟频率。

 2、 定时器时钟源的选择

        基本定时器时钟只能来自内部时钟,当 TIM6 和 TIM7 控制寄存器 1(TIMx_CR1)的 CEN 位 置 1 时,启动基本定时器,并且预分频器的时钟来源就是 CK_INT。高级控制定时器和通用定时器还可以选择外部时钟源或者直接来自其他定时器等待模式。我们可以通过 RCC 专用时钟配置寄存器(RCC_DCKCFGR)的 TIMPRE 位设置所有定时器的时钟频率, 我们一般设置该位为默认值 0,即 TIMxCLK 为总线时钟的两倍,使得表中可选的最大定时器时钟为 84MHz,即基本定时器的内部时钟(CK_INT)频率为 84MHz。 

2.2.2 控制器

      定时器控制器控制实现定时器功能,控制定时器复位、使能、计数是其基础功能,基本定时器还专门用于 DAC 转换触发。

2.2.3 时基单元(重点)

       时基单元包括:计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)、自动重载寄存器 (TIMx_ARR) 。如下图所示:

        基本定时器的这三个寄存器都是 16 位有效数字,即可设置值范围是 0~65535。 时基单元中的预分频器 PSC,它有一个输入和一个输出。输入 CK_PSC 来源于控制器部分, 实际上就是来自于内部时钟(CK_INT),即 2 倍的 APB1 总线时钟频率(84MHz)。输出 CK_CNT 是分频后的时钟,它是计数器实际的计数时钟,在不同应用场所,经常需要不同的定时频率,通 过设置预分频器 PSC 的值可以非常方便得到不同的 CK_CNT,计算公式如下:

上式中,PSC[15:0]是写入预分频器寄存器(TIMx_PSC)的值。另外:预分频器寄存器(TIMx_PSC)可以在运行过程中修改它的数值,新的预分频数值将在下一个更新事件时起作用。因为更新事件发生时,会把 TIMx_PSC 寄存器值更新到其影子寄存器中,这才会起作用。

1、什么是影子寄存器?

       从框图上看,可以看到图中的预分频器PSC后面有一个影子, 自动重载寄存器也有个影子,这就表示这些寄存器有影子寄存器。影子寄存器是一个实际起作用的寄存器,不可直接访问。举个例子:我们可以把预分频系数写入预分频器寄存器(TIMx_PSC), 但是预分频器寄存器只是起到缓存数据的作用,只有等到更新事件发生时,预分频器寄存器的值才会被自动写入其影子寄存器中,这时才真正起作用。 自动重载寄存器及其影子寄存器的作用和上述同理。不同点在于自动重载寄存器是否具有缓冲作用还受到 ARPE 位的控制,当该位置 0 时,ARR 寄存器不进行缓冲,我们写入新的 ARR 值时,该值会马上被写入 ARR 影子寄存器中,从而直接生效;当该位置 1 时,ARR 寄存器进 行缓冲,我们写入新的 ARR 值时,该值不会马上被写入 ARR 影子寄存器中,而是要等到更新 事件发生才会被写入 ARR 影子寄存器,这时才生效。预分频器寄存器则没有这样相关的控制位,这就是它们不同点。

2、更新事件的产生有两种情况

       一是由软件产生,将 TIMx_EGR 寄存器的位 UG 置 1,产生更新事件后,硬件会自动将 UG 位清零。二是由硬件产生,满足以下条件即可: 计数器的值等于自动重装载寄存器影子寄存器的值。下面来讨论一下硬件更新事件。

         基本定时器的计数器(CNT)是一个递增的计数器,当寄存器(TIMx_CR1)的 CEN 位置 1,即使能定时器,每来一个 CK_CNT 脉冲,TIMx_CNT 的值就会递增加 1。当 TIMx_CNT 值 与 TIMx_ARR 的设定值相等时,TIMx_CNT 的值就会被自动清零并且会生成更新事件(如果开启相应的功能,就会产生 DMA 请求、产生中断信号或者触发 DAC 同步电路),然后下一个 CK_CNT 脉冲到来,TIMx_CNT 的值就会递增加 1,如此循环。在此过程中,TIMx_CNT 等于 TIMx_ARR 时,我们称之为定时器溢出,因为是递增计数,故而又称为定时器上溢。定时器溢出就伴随着更新事件的发生。

       由上述可知,我们只要设置预分频寄存器和自动重载寄存器的值就可以控制定时器更新事 件发生的时间。自动重载寄存器(TIMx_ARR)是用于存放一个与计数器作比较的值,当计数器的值等于自动重载寄存器的值时就会生成更新事件,硬件自动置位相关更新事件的标志位,如: 更新中断标志位,此时只要判断这个中断标志位,就会去执行中断服务函数,处理相应的事件!下图是将预分频器 PSC 的值从 1 改为 4 时计数器时钟变化过程:通过这个例子理解一下分频:原来是 1 分频, CK_PSC 和 CK_CNT 频率相同。向 TIMx_PSC 寄存器写入新值时,并不会马上更新 CK_CNT 输出频率,而是等到更新事件发生时,把 TIMx_PSC 寄存器值更新到影子寄存器中,使其真正产生效果。更新为 4 分频后,在 CK_PSC 连续出现 4 个脉冲后 CK_CNT 才产 生一个脉冲。

2.3 基本定时器的寄存器

     下面介绍 TIM6/TIM7 的几个重要的寄存器,具体如下:

2.3.1 控制寄存器 1(TIMx_CR1)

     该寄存器,我们需要注意的是:位 0(CEN)用于使能或者禁止计数器,该位置 1 计数器开始工作,置 0 则停止。还有位 7(APRE)用于控制自动重载寄存器 ARR 是否具有缓冲作用, 如果 ARPE 位置 1,ARR 起缓冲作用,即只有在更新事件发生时才会把 ARR 的值写入其影子 寄存器里;如果 ARPE 位置 0,那么修改自动重载寄存器的值时,该值会马上被写入其影子寄 存器中,从而立即生效。

2.3.2 DMA/中断使能寄存器(TIMx_DIER)

      该寄存器位 0(UIE)用于使能或者禁止更新中断,因为本实验我们用到中断,所以该位需 要置 1。位 8(UDE)用于使能或者禁止更新 DMA 请求,我们暂且用不到,置 0 即可。

2.3.3 状态寄存器(TIMx_SR)

      该寄存器位 0(UIF)是中断更新的标志位,当发生中断时由硬件置 1,然后就会执行中断 服务函数,需要软件去清零,所以我们必须在中断服务函数里把该位清零。如果中断到来后, 不把该位清零,那么系统就会一直进入中断服务函数,这显然不是我们想要的。

2.3.4 计数器寄存器(TIMx_CNT)

该寄存器位[15:0]就是计数器的实时的计数值。

2.4.5 预分频寄存器(TIMx_PSC)

该寄存器是 TIM6/TIM7 的预分频寄存器,比如我们要 8400 分频,就往该寄存器写入 8399。 注意这是 16 位的寄存器,写入的数值范围是 0 到 65535,分频系数范围:1 到 65536。 

2.4.6 自动重载寄存器(TIMx_ARR)

该寄存器可以由 APRE 位设置是否进行缓冲。计数器的值会和 ARR 寄存器影子寄存器进 行比较,当两者相等,定时器就会溢出,从而发生更新事件,如果打开更新中断,还会发生更 新中断。

2.5 定时器周期的计算(定时时间计算)

       经过上面分析,我们知道定时事件生成时间主要由 TIMx_PSC 和 TIMx_ARR 两个寄存器值决定,这个也就是定时器的周期。比如我们需要一个 1s 周期的定时器,具体这两个寄 存器值该如何设置呢?

比如我们需要一个 500ms 周期的定时器更新中断?

      一般思路是先设置预分频寄存器,然后才是自动重载寄存器。考虑到我们设置的 CK_INT 为 84MHz,我们把预分频系数设置为 8400(方便计算),即写入预分频寄存器的值为 8399,那么 fCK_CNT=84MHz/8400=10KHz。 这样就得到计数器的计数频率为 10KHz,即计数器 1 秒钟可以计 10000 个数(1毫秒可以计10个数)。我们需要 500ms 的中断周期,所以我们让计数器计数 5000 个数就能满足要求,即需要设置自动重载寄存器的值 为 4999,另外还要把定时器更新中断使能位 UIE 置 1,CEN 位也要置 1。

注意:

       这里我们设定定时器自动重装载值为 5000-1,预分频系数为 8400-1,这里减 1 是因为定时器预分频器内部会自动加 1, 所以如果要进行 8400 分频的话,就传递 8399,而重装载值是从 0 开始计数的, 所以累积 5000 的话最终传递的参数是 5000-1。

2.6 定时器初始化结构体详解

        标准库函数对定时器外设建立了四个初始化结构体,基本定时器只用到其中一个即 TIM_TimeBaseInitTypeDef,该结构体成员用于设置定时器基本工作参数,并由定时器基本初始化配置函数 TIM_TimeBaseInit 调用,这些设定参数将会设置定时器相应的寄存器,达到配置定时器工作环境的目的。这一节我们只介绍 TIM_TimeBaseInitTypeDef 结构体,其他结构体将在相关章节介绍。 初始化结构体和初始化库函数配合使用是标准库精髓所在,理解了初始化结构体每个成员意义基本上就可以对该外设运用自如了。初始化结构体定义在 stm32f4xx_tim.h 文件中, 初始化库函数定义在 stm32f4xx_tim.c 文件中,编程时我们可以结合这两个文件内注释使用。

  1. TIM_Prescaler:定时器预分频器设置,时钟源经该预分频器才是定时器时钟,它设定 TIMx_PSC 寄存器的值。可设置范围为 0 至 65535,实现 1 至 65536 分频。
  2.  TIM_CounterMode:定时器计数方式,可是在为向上计数、向下计数以及三种中心对 齐模式。基本定时器只能是向上计数,即 TIMx_CNT 只能从 0 开始递增,并且无需初 始化。
  3.  TIM_Period:定时器周期,实际就是设定自动重载寄存器的值,在事件生成时更新到 影子寄存器。可设置范围为 0 至 65535。
  4. TIM_ClockDivision:时钟分频,设置定时器时钟 CK_INT 频率与数字滤波器采样时钟 频率分频比,基本定时器没有此功能,不用设置
  5. TIM_RepetitionCounter:重复计数器,属于高级控制寄存器专用寄存器位,利用它可 以非常容易控制输出 PWM 的个数。这里不用设置

虽然定时器基本初始化结构体有 5 个成员,但对于基本定时器 TIM6 和 TIM7 的使用只需初始化两个成员即可,想想使用基本定时器就是简单。

2.7 基本定时器中断

2.7.1 基本定时器中断应用

       本实验,我们主要配置定时器产生周期性溢出,从而在定时器更新中断中做周期性的操作, 如周期性翻转 LED 灯。假设计数器计数模式为递增计数模式,那么实现周期性更新中断原理示 意图如下所示:

      如图 20.1.3.1 所示,CNT 计数器从 0 开始计数,当 CNT 的值和 ARR 相等时(t1),产生一 个更新中断,然后 CNT 复位(清零),然后继续递增计数,依次循环。图中的 t1、t2、t3 就是定时器更新中断产生的时刻。 通过修改 ARR 的值,可以改变定时时间。另外,通过修改 PSC 的值,使用不同的计数频 率(改变图中 CNT 的斜率),也可以改变定时时间。

2.7.2 基本定时器中断配置步骤

         接下来我们介绍下如何使用库函数对通用定时器进行配置。这个也是在编写 程序中必须要了解的。具体步骤如下

第一步:开启定时器时钟;

第二步:初始化定时器参数,设置自动重装值,分频系数,计数方式等;
第三步:使能定时器更新中断;
第四步:配置定时器中断优先级;
第五步:开启定时器计数;
第六步:编写中断服务函数;

三、使用基本定时器实现定时3秒,触发中断。

实现功能:我们使用基本定时器循环定时500毫秒并使能定时器中断,每到500毫秒 就在定时器中断服务函数翻转 RGB 彩灯,使得最终效果LED灯暗 0.5s,亮 0.5s,如此循环。

myled.h文件内容

#ifndef __MYLED_H
#define __MYLED_H

void LED_Init(void);

#endif

myled.c内容

#include "stm32f4xx.h"                  // Device header
#include "myled.h"

/*开时钟  打开外设对应的时钟(查看参考手册,该外设挂在哪个数据总线上),对应GPIO在哪条总线开哪条
	GPIOF外设 挂在AHB1总线上,所以要打开AHB1的时钟,双击函数,右键->go to definition*/


void LED_Init(void)
{
    //第一步:使能GPIOF的时钟 
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能 GPIOF 时钟
	
   //第二步:GPIOF9,F10 初始化设置
   GPIO_InitTypeDef GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 ;//LED1对应 IO 口
   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
   GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化 GPIO

   //第三步:设置灯的初始状态
   GPIO_SetBits(GPIOF,GPIO_Pin_10 );//GPIOF10,设置高电平,灯灭
}

mytim.h内容

#ifndef __MY_TIM_H__
#define __MY_TIM_H__

void TIM_Mode_Config(void);


#endif

mytim.c内容

#include "stm32f4xx.h"                  // Device header
#include "mytim.h"

/********定时器中断配置过程*********
       第一步:开启定时器时钟
       第二步:初始化定时器参数,设置自动重装值,分频系数,计数方式等
       第三步:使能定时器更新中断
	   第四步:配置定时器中断优先级
	   第五步:开启定时器计数
	   第六步:编写中断服务函数

************************************/

void TIM_Mode_Config(void)
{
    //第一步:TIM时钟使能
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE); 
			
	//第二步:初始化定时器参数,设置自动重装值,分频系数,计数方式等
	TIM_TimeBaseInitTypeDef Struct;
    Struct.TIM_Period = 5000-1;         //自动重载寄存器ARR,定时500毫秒
    Struct.TIM_Prescaler = 8400-1;      //预分频器PSC
    TIM_TimeBaseInit(TIM6,&Struct);     //初始化时基单元
		
	//第三步:开启定时器更新中断
	TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE); //使能定时器中断 
	
	//第四步:配置定时器中断优先级,配置NVIC
    NVIC_InitTypeDef Struct1;
    Struct1.NVIC_IRQChannel = TIM6_DAC_IRQn;
    Struct1.NVIC_IRQChannelCmd =ENABLE;
    Struct1.NVIC_IRQChannelPreemptionPriority = 0;      //实验只有一个中断,对 NVIC 配置没什么具体要求。
    Struct1.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&Struct1);
	
	//第五步:使能定时器
	TIM_Cmd(TIM6,ENABLE);                   //使能定时器
	
}


//第六步:编写中断服务函数
void TIM6_DAC_IRQHandler(void) 
{
    if(TIM_GetITStatus(TIM6,TIM_IT_Update) == SET)     //判断中断标志位
    { 
         GPIO_ToggleBits(GPIOF,GPIO_Pin_10 );    
         TIM_ClearITPendingBit(TIM6,TIM_IT_Update);  //清除中断标志位
   } 
}

      在发生中断时,中断服务函数就得到运行。在服务函数内我们先调用定时器中断标志读取函数 TIM_GetITStatus 获取当 前定时器中断位状态,确定产生中断后才运行LED灯翻转动作,并使用定时器标志位清 除函数 TIM_ClearITPendingBit 清除中断标志位。 

main.c内容

#include "stm32f4xx.h"                  // Device header
#include "mytim.h"
#include "myled.h"

int main(void)
{
      LED_Init();
     /* 初始化基本定时器定时,3s 产生一次中断*/
     TIM_Mode_Config();
      while(1)
     {
	      
     }
}

     将工程程序编译后下载到开发板内,可以看到 DS1 指示灯每隔 500ms 状态取反一次,实现 1 秒钟闪烁一次。

至此,我们的本次的学习就结束了。相信对基本定时器有了深入的理解,这一节我们就讲解到这里,希望能对大家的开发有帮助。 如有兴趣,感谢点赞、关注、收藏,若有不正地方,还请各位大佬多多指教!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1842080.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

转让神州开头的无区域科技公司需要多少钱

您好,我公司现有2家无区域神州名称的公司转让。所谓无区域名称是公司名称中不带有行政区划、及行业特点的公司名称,都是需要在工商总,局核准名称的,对于民营企业来说也比较喜欢这种名称名称很大气,现在重核更严格了,所…

期货止损口诀需牢记

实战操作难免错,心中不必一团火; 出错认输是常事,亏损不止闯大祸。 止损纪律要定死,价格不能差豪丝; 触及止损要出局,管它价格怎放肆。 强势多空价放宽,价格波动要空间; 大势不改…

OpenAI 前首席科学家 Ilya Sutskever 成立新人工智能公司

OpenAI 联合创始人之一 Ilya Sutskever 在正式离开 OpenAI 一个月后,成立了一家新公司 Safe Superintelligence Inc. (SSI)。Sutskever 是 OpenAI 的长期首席科学家,他与前 Y Combinator 合伙人 Daniel Gross 以及前 OpenAI 工程师 Daniel Levy 共同创立…

[SAP ABAP] MESSAGE消息处理

常用的MESSAGE命令的字符 信息类型描述EError 出现错误消息,应用程序在当前点暂停 WWarning 出现警告消息,用户必须按Enter键才能继续应用程序 IInformation 将打开一个弹出窗口,其中包含消息文本,用户必须按Enter键才能继续 SSu…

watcher学习小结

架构 主要是watcher-api,watcher-applier,watcher-decision-engine watcher-applier watcher-decision-engine 将DecisionEngineManager和DecisionEngineSchedulingService封装到oslo_service,然后调service的launch_service,实…

渗透测试基础(四) MS08-067 漏洞攻击

1. 漏洞介绍 漏洞描述 Microsoft Windows Server服务RPC请求缓冲区溢出漏洞Windows的Server服务在处理特质RPC请求时存在缓冲区溢出漏洞,远程攻击者可以通过发送恶意的RPC请求触发这个溢出,导致完全入侵用户系统,以SYSTEM权限执行任意指令。…

为什么3D渲染让客户无法抗拒?7个重要原因

客户通常对工程、建筑、复杂的室内外设计知之甚少,展示草图只会让他们感到难以理解。不过,现代设计师和建筑师不再需要为此烦恼。 通过使用逼真且沉浸式的3D渲染,他们可以让能够轻松地向客户传达信息和沟通想法。它对赢得客户至关重要。接下…

PyCharm新手入门

前言 在之前《Python集成开发工具的选择》一文中介绍了python初学者可以使用Jupyter Notebook,Jupyter Notebook简单易用,可以用来练习代码编写,但是实际生产开发环境使用这个工具是远远不够用的,因为实际软件开发中需要软件调试…

API接口对接的步骤流程?有哪些注意事项?

API接口对接自动化的实现方法?如何调试API接口发信? 在现代软件开发中,API接口对接已成为各个系统和应用之间进行通信和数据交换的关键技术。AokSend将详细介绍API接口对接的步骤流程,帮助开发者更好地理解和实现这一过程。 API…

在webstorm配置nodejs(从零开始)

在webstorm配置nodejs之前,需要先下载node.js和webStorm。 按下winr,输入cmd打开命令行 输入node -v和npm -v会出现相应的版本,如果报错则需要去下载node.js。 打开webStorm,File—settings 搜索node 选择node.exe安装位置 重启…

大模型日报|8 篇必读的大模型论文

大家好,今日必读的大模型论文来啦! 1.Pandora:自回归-扩散混合通用世界模型 世界模型模拟世界在不同行动下的未来状态,它们有助于创建交互式内容,并为有依据的长远推理提供基础。然而,目前的基础模型并不…

【stm32单片机应用】基于I2C协议的OLED显示(利用U82G库)

一、U8g2库 (一)U8g2简介 U8g2 是一个用于单色和彩色显示的嵌入式图形库,特别适用于单色OLED、LCD显示屏的驱动。它是对早期U8g库的扩展和改进,提供了更多功能和更广泛的硬件支持。U8g2作为一款强大而灵活的嵌入式图形库&#x…

为什么你不能下载哨兵遥感影像?Sentinel-1 和 Sentinel-2(解决)

​ 点击下方全系列课程学习 点击学习—>ArcGIS全系列实战视频教程——9个单一课程组合系列直播回放 点击学习——>遥感影像综合处理4大遥感软件ArcGISENVIErdaseCognition 今天的文章来介绍一下如何下载欧空局哨兵数据,哨兵数据是目前我们可以免费下载的全球…

海康威视-下载的录像视频浏览器播放问题

目录 1、播放异常比对 2、视频编码检查 2.1、正常视频解析 2.2、海康视频解析 2.3、比对工具 3、转码 3.1、maven依赖 3.2、实现代码 4、验证 在前面的文章(海康威视-按时间下载录像文件_海康威视 sdk 下载录像 大小0-CSDN博客)中,通…

吊打Unity的角色动画重定向专业版工具FPS手臂武器动画动物动画角色动作微调烘焙20240620

今天发现一款关注已久的Unity插件上架商店了,可以将动画从一个通用/人形角色重新定位到另一个通用角色。 吊打Unity的角色动画重定向专业版工具FPS手臂武器动画动物动画角色动作微调烘焙202406201103 Unity 中任何通用角色的终极解决方案。它没有 Humanoid 系统的限…

分析师:是什么导致山寨币在本轮周期表现不佳?

在加密货币领域,山寨币的过度分散化问题逐渐凸显,成为本轮周期内其表现疲软的核心因素。经过深入研究,我发现这种分散化对加密货币市场的整体健康造成了严重威胁。然而,令人遗憾的是,目前看来,我们尚未找到…

ECharts 雷达图案例001-自定义节点动画

ECharts 雷达图案例001-自定义节点动画 引言 在数据可视化的领域中,ECharts 提供了一种强大的工具来展示多维数据。本文将介绍如何使用 ECharts 创建一个自定义节点样式的雷达图,让数据展示更加生动和个性化。 效果预览 通过自定义节点样式&#xff…

数据结构_二叉树

目录 一、树型结构 二、二叉树 2.1 概念 2.2 特殊的二叉树 2.3 二叉树的性质 2.4 二叉树的存储 2.5 遍历二叉树 2.6 操作二叉树 总结 一、树型结构 树是一种非线性的数据结构,它是由 n(n>0) 个有限结点组成一个具有层次关系的集合,一棵 n 个…

CatBoost算法详解

CatBoost算法详解 CatBoost(Categorical Boosting)是由Yandex开发的一种基于梯度提升决策树(GBDT)的机器学习算法,特别擅长处理包含类别特征的数据集。它不仅在精度和速度上表现出色,还对类别特征有天然的…

工业园安全生产新保障:广东地区加强可燃气体报警器校准检测

广东,作为我国经济的重要引擎,拥有众多工业园区。 这些工业园区中,涉及化工、制药、机械制造等多个领域,每天都会产生和使用大量的可燃气体。因此,可燃气体报警器的安装与校准检测,对于保障工业园区的安全…