【STM32】TIM---基本定时器

Author:AXYZdong 自动化专业 工科男
有一点思考,有一点想法,有一点理性!
定个小小目标,努力成为习惯!在最美的年华遇见更好的自己!
CSDN@AXYZdong,CSDN首发,AXYZdong原创
唯一博客更新的地址为: 👉 AXYZdong的博客 👈

在这里插入图片描述


  • 开发板:stm32f407VET6
  • 开发环境:keil5 MDK

插播一条反爬虫信息,读者可以忽略:


在这里插入图片描述

一、TIM 简介

定时器最基本功能:定时

  • 定时发送 USART 数据
  • 定时采集 AD 数据等

定时器与 GPIO 结合

  • 测量输入信号脉冲宽度
  • 产生输出波形 等

在这里插入图片描述

▲ 各个定时器的特性


二、基本定时器

基本定时器 :TIM6TIM7 ,基本功能完全一样,但所占资源彼此完全独立。

在这里插入图片描述

▲ 基本定时器的功能框图


  • 基本定时器时钟只能来自内部时钟
  • 基本定时器的内部时钟(CK_INT)频率为 84MHz
  • 基 本定时器还专门用于 DAC 转换触发
  • 只要设置 CK_PSCTIMx_ARR 这两个寄存器的值就可以控制事件生成的时间

三、定时器周期计算

T o u t = ( A R R + 1 ) ⋅ ( P S C + 1 ) T I M x C L K Tout = \frac{(ARR + 1)\cdot(PSC + 1)}{TIMxCLK} Tout=TIMxCLK(ARR+1)(PSC+1)

  • T o u t Tout Tout:溢出时间,即定时多长时间
  • T I M x C L K TIMxCLK TIMxCLK:定时器时钟频率
//定时器时钟源 TIMxCLK = 2 * PCLK1 25     
//        PCLK1 = HCLK / 4 26     
//        => TIMxCLK=HCLK/2=SystemCoreClock/2=84MHz 
  • A R R ARR ARR:定时器周期,初始化结构体时用 TIM_Period 表示
  uint32_t TIM_Period;            /*!< Specifies the period value to be loaded into the active
                                       Auto-Reload Register at the next update event.
                                       This parameter must be a number between 0x0000 and 0xFFFF.  */ 

  • P S C PSC PSC:预分频大小,初始化结构体时用 TIM_Prescaler 表示
  uint16_t TIM_Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.
                                       This parameter can be a number between 0x0000 and 0xFFFF */

比如我们需要一个 1s 周期的定时器,具体这两个寄存器值该如何设置。

假设,我们先设置 TIMx_ARR寄存器值为 9999 ,即当 TIMx_CNT 从 0 开始计算,刚好等于 9999 时生成事件,总共计数 10000 次,那么如果此时时钟源周期 为 100us 即可得到刚好 1s 的定时周期。

接下来问题就是设置 TIMx_PSC 寄存器值使得 CK_CNT 输出为 100us 周期 (10000Hz) 的时钟。预分频器的输入时钟 CK_PSC 为 84MHz,所以设置预分频器值为 (8400-1) 即可满 足。

四、初始化结构体

typedef struct
{
  //预分频器
  uint16_t TIM_Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.
                                       This parameter can be a number between 0x0000 and 0xFFFF */
  //计数模式
  uint16_t TIM_CounterMode;       /*!< Specifies the counter mode.
                                       This parameter can be a value of @ref TIM_Counter_Mode */
  //定时器周期
  uint32_t TIM_Period;            /*!< Specifies the period value to be loaded into the active
                                       Auto-Reload Register at the next update event.
                                       This parameter must be a number between 0x0000 and 0xFFFF.  */ 
  //时钟分频
  uint16_t TIM_ClockDivision;     /*!< Specifies the clock division.
                                      This parameter can be a value of @ref TIM_Clock_Division_CKD */
  //重复计算器
  uint8_t TIM_RepetitionCounter;  /*!< Specifies the repetition counter value. Each time the RCR downcounter
                                       reaches zero, an update event is generated and counting restarts
                                       from the RCR value (N).
                                       This means in PWM mode that (N+1) corresponds to:
                                          - the number of PWM periods in edge-aligned mode
                                          - the number of half PWM period in center-aligned mode
                                       This parameter must be a number between 0x00 and 0xFF. 
                                       @note This parameter is valid only for TIM1 and TIM8. */
} TIM_TimeBaseInitTypeDef; 


五、基本定时器实验

基本定时器循环定时 1s ,并使能定时器中断,每隔 1s 在定时器中断服务函数使 LED 状态翻转。

编程思路

  • 初始化 LED
  • 开启定时器时钟
  • 设置定时器周期和预分频器
  • 启动定时器中断,开启定时器
  • 中断服务函数翻转 LED

time.h

// =============================================
# @Time    : 2020-10-22
# @Author  : AXYZdong
# @CSDN    : https://blog.csdn.net/qq_43328313
# @FileName: time.h
# @Software: keil5 MDK
// =============================================

#ifndef _TIME_H
#define _TIME_H

#include "stm32f4xx.h"

//宏定义
#define BASIC_TIM             TIM6
#define BASIC_TIM_CLK         RCC_APB1Periph_TIM6

#define BASIC_TIM_IRQn        TIM6_DAC_IRQn
#define BASIC_TIM_IRQHandler  TIM6_DAC_IRQHandler

void TIM_Config(uint16_t ARR , uint16_t PSC);

#endif

time.c

// =============================================
# @Time    : 2020-10-22
# @Author  : AXYZdong
# @CSDN    : https://blog.csdn.net/qq_43328313
# @FileName: time.c
# @Software: keil5 MDK
// =============================================

#include "time.h"
#include "bsp_led.h"

extern void TIM_Config(uint16_t ARR , uint16_t PSC);

void TIM_Config(uint16_t ARR , uint16_t PSC)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); 
    NVIC_InitStructure.NVIC_IRQChannel = BASIC_TIM_IRQn;//定时器中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
	
/*  
*注意:TIM_TimeBaseInitTypeDef 结构体里面有 5 个成员,TIM6 和 TIM7 的寄存器里面只有  
*TIM_Prescaler 和 TIM_Period,所以使用 TIM6 和 TIM7 的时候只需初始化这两个成员即可,  
* 另外三个成员是通用定时器和高级定时器才有.  
*-----------------------------------------------------------------------  
* TIM_Prescaler         都有  
* TIM_CounterMode       TIMx,x[6,7]没有,其他都有(基本定时器)  
* TIM_Period            都有  
* TIM_ClockDivision     TIMx,x[6,7]没有,其他都有(基本定时器) 
* TIM_RepetitionCounter TIMx,x[1,8]才有(高级定时器) 
*----------------------------------------------------------------------- 
*/ 
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;

RCC_APB1PeriphClockCmd(BASIC_TIM_CLK, ENABLE);   //开启 TIMx_CLK 

TIM_TimeBaseInitStruct.TIM_Period = ARR;         //累计 TIM_Period 个后产生一个更新或者中断
TIM_TimeBaseInitStruct.TIM_Prescaler = PSC;      //设定定时器频率

TIM_TimeBaseInit(BASIC_TIM, &TIM_TimeBaseInitStruct);  //初始化定时器 TIMx 

TIM_ITConfig(BASIC_TIM, TIM_IT_Update, ENABLE);        //开启定时器更新中断 
TIM_Cmd(BASIC_TIM, ENABLE);                            //使能定时器  

}

void BASIC_TIM_IRQHandler()
{
  if(TIM_GetITStatus(BASIC_TIM , TIM_IT_Update) == SET)
	{
	  LED0 = ~ LED0;
		TIM_ClearITPendingBit(BASIC_TIM , TIM_IT_Update);
	}
}

main.c

// =============================================
# @Time    : 2020-10-22
# @Author  : AXYZdong
# @CSDN    : https://blog.csdn.net/qq_43328313
# @FileName: main.c
# @Software: keil5 MDK
// =============================================

#include "stm32f4xx.h"
#include "time.h"
#include "bsp_led.h"

int main(void)
{
  LED_GPIO_Config();     //初始化LED
  TIM_Config(9999,8399); //初始化定时器
	while(1)
	{
 
 	}
}

六、总结

  • 宏定义的使用可以便于代码移植
  • LED 状态翻转使用了 位带 操作
  • 软件设置的定时时间和 LED 闪烁时间不太一致,不清楚哪个地方出问题了?有知道的小伙伴可以 👇 下方留言告诉我哦

【参考文献】

[1] 《零死角玩转 STM32—基于野火 F407[霸天虎]开发板 》



「你可能还想看」系列文章:
【STM32】点亮LED
【STM32】GPIO输入—按键检测
【STM32】0.96寸OLED显示屏(7针SPI协议)软件模拟SPI
【STM32】1.44寸TFT液晶屏显示字符、汉字和图片
【STM32】stm32f407 + DS18B20 碰出不一样的火花
【STM32】5分钟了解STM32的串口通信
【STM32】串口通信—用代码与芯片对话
【STM32】串口通信出现乱码(使用官方标准库)
【STM32】EXTI—外部中断/事件控制器
【STM32】PWM 输出 (标准库)

【STM32】CubeMX+HAL 点亮LED
【STM32】CubeMX+HAL 输出PWM

【STM32】ST-LINK下载器下载后需复位,程序才运行的问题

其他相关文章:
【信号与系统】笔记合集,你确定不收藏吗?我已经收藏了
我用50行代码居然「让天猫精灵把客厅灯开了」
流程图在线绘制,快速、便捷、高效!


  本次的分享就到这里


11

好书不厌百回读,熟读自知其中意。将学习成为习惯,用知识改变命运,用博客见证成长,用行动证明努力。
如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!
听说 👉 点赞 👈 的人运气不会太差,每一天都会元气满满呦!^ _ ^ ❤️ ❤️ ❤️
码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了👉关注👈我哦!
更多精彩内容请前往 AXYZdong的博客


如果以上内容有任何错误或者不准确的地方,欢迎在下面 👇 留个言。或者你有更好的想法,欢迎一起交流学习~~~

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=33io4h3lf84k4

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AXYZdong

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值