STM32 第18讲 基本定时器(简介/计数模式/寄存器/溢出时间计算方法/实验)

2023-11-05

基本定时器简介

STM32F407 有两个基本定时器 TIM6 和 TIM7
主要特性:
16 位自动重载递增计数器,计数值 1 ~ 65535;
16 位可编程预分频器,预分频系数 1~65536,用于对计数器时钟频率进行分频;
还可以触发 DAC 的同步电路,以及生成中断/DMA 请求。
分频 = 设置的分频系数 + 1

基本定时器框图

在这里插入图片描述

  • ①时钟源
    基本定时器时钟挂
    载在 APB1 总线,所以它的时钟来自于 APB1 总线,但是基本定时器时钟不是直接由 APB1 总线直接提供,而是先经过一个倍频器。当 APB1 的预分频器系数为 1 时,这个倍频器系数为 1,即定时器的时钟频率等于 APB1 总线时钟频率;当 APB1 的预分频器系数≥2 分频时,这个倍频器系数就为 2 , 即定时器的时钟频率等于 APB1 总 线时钟频率的两倍 。我们 在sys_stm32_clock_init 时钟设置函数已经设置 APB1 总线时钟频率为 42Mhz,APB1 总线的预分频器分频系数是 2,所以挂载在 APB1 总线的定时器时钟频率为 84Mhz。
  • ②控制器
    控制器除了控制定时器复位、使能、计数等功能之外,还可以用于触发 DAC 转换
  • ③时基单元
    时基单元包括:计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)、自动重载寄存器(TIMx_ARR) 。基本定时器的这三个寄存器都是 16 位有效数字,即可设置值范围是 0~65535。

时基单元中的预分频器 PSC,它有一个输入和一个输出。输入 CK_PSC 来源于控制器部分,实际上就是来自于内部时钟(CK_INT),即 2 倍的 APB1 总线时钟频率(84MHz)。输出 CK_CNT是分频后的时钟,它是计数器实际的计数时钟,通过设置预分频器寄存器(TIMx_PSC)的值可以得到不同频率 CK_CNT。
在这里插入图片描述

  • 预分频器寄存器(TIMx_PSC)可以在运行过程中修改它的数值,新的预分频数值将在下一个更新事件时起作用。因为更新事件发生时,会把 TIMx_PSC 寄存器值更新到其影子寄存器中,这才会起作用。

    影子寄存器:影子寄存器是一个实际起作用的寄存器,不可直接访问。

自动重载寄存器及其影子寄存器的作用和上述同理。不同点在于自动重载寄存器是否具有缓冲作用还受到 ARPE 位的控制,当该位置 0 时,ARR 寄存器不进行缓冲,我们写入新的 ARR值时,该值会马上被写入 ARR 影子寄存器中,从而直接生效;当该位置 1 时,ARR 寄存器进行缓冲,我们写入新的 ARR 值时,该值不会马上被写入 ARR 影子寄存器中,而是要等到更新事件发生才会被写入 ARR 影子寄存器,这时才生效。

产生更新事件的两种情况:

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

计数模式及溢出条件

在这里插入图片描述
通过时序图理解计数模式

递增计数模式

在这里插入图片描述

递减计数模式

在这里插入图片描述

中间对齐计数模式

在这里插入图片描述

相关寄存器

控制寄存器1 (TIMx_CR1)

在这里插入图片描述

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

用于使能更新中断
在这里插入图片描述

状态寄存器(TIMx_SR)

用于判断是否发生了更新中断,由硬件置1,软件清零
在这里插入图片描述

计数器寄存器(TIMx_CNT)

计数器实时数值,可用于设置计数器初始值
在这里插入图片描述

预分频寄存器(TIMx_PSC)

在这里插入图片描述
写入的数值范围是 0 到 65535,分频系数范围:1 到 65536。

自动重装载寄存器(TIMx_ARR)

在这里插入图片描述
计数器的值会和 ARR 寄存器影子寄存器进行比较,当两者相等,定时器就会溢出,从而发生更新事件,如果打开更新中断,还会发生更新中断。

溢出时间计算方法

在这里插入图片描述

实验

定时器中断配置步骤

  1. 配置定时器基础工作参数
  2. 定时器基础MSP初始化
  3. 使能更新中断并启动定时器
  4. 设置优先级,使能中断
  5. 编写中断服务函数
  6. 编写中断服务函数

相关HAL库函数介绍

在这里插入图片描述
关键结构体介绍

typedef struct
{
	 TIM_TypeDef *Instance; /* 外设寄存器基地址 */
	 TIM_Base_InitTypeDef Init; /* 定时器初始化结构体*/
	 HAL_TIM_ActiveChannel Channel; /* 定时器通道 */
	 DMA_HandleTypeDef *hdma[7]; /* DMA 管理结构体 */
	 HAL_LockTypeDef Lock; /* 锁定资源 */
	 __IO HAL_TIM_StateTypeDef State; /* 定时器状态 */
	 __IO HAL_TIM_ChannelStateTypeDef ChannelState; /* 定时器通道状态 */
	 __IO HAL_TIM_ChannelStateTypeDef ChannelNState; /* 定时器互补通道状态 */
	 __IO HAL_TIM_DMABurstStateTypeDef DMABurstState; /* DMA 溢出状态 */
}TIM_HandleTypeDef;


/* TIM_Base_InitTypeDef 结构体 */
typedef struct
{
	 uint32_t Prescaler; /* 预分频系数 */ 
	 uint32_t CounterMode; /* 计数模式 */
	 uint32_t Period; /* 自动重载值 ARR */
	 uint32_t ClockDivision; /* 时钟分频因子 */ 
	 uint32_t RepetitionCounter; /* 重复计数器 */
	 uint32_t AutoReloadPreload; /* 自动重载预装载使能 */
} TIM_Base_InitTypeDef;

定时器中断实验

  • 实现功能
    使用TIM6,实现500ms定时器中断,在中断中反转LED1,在main函数中通过延时函数反转LED0。
  • bitm.h
    对基本定时器,中断进行宏定义
#ifndef __BTIM_H
#define __BTIM_H

#include "./SYSTEM/sys/sys.h"


/******************************************************************************************/
/* 基本定时器 定义 */

/* TIMX 中断定义 
 * 默认是针对TIM6/TIM7
 * 注意: 通过修改这4个宏定义,可以支持TIM1~TIM8任意一个定时器.
 */
 
#define BTIM_TIMX_INT                       TIM6
#define BTIM_TIMX_INT_IRQn                  TIM6_DAC_IRQn
#define BTIM_TIMX_INT_IRQHandler            TIM6_DAC_IRQHandler
#define BTIM_TIMX_INT_CLK_ENABLE()          do{ __HAL_RCC_TIM6_CLK_ENABLE(); }while(0)  /* TIM6 时钟使能 */

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

void btim_timx_int_init(uint16_t arr, uint16_t psc);    /* 基本定时器 定时中断初始化函数 */

#endif
  • bitm.c
  1. 基本定时器初始化函数
#include "./BSP/LED/led.h"
#include "./BSP/TIMER/btim.h"


TIM_HandleTypeDef g_timx_handler;         /* 定时器参数句柄 */
/**
* @brief       基本定时器TIMX定时中断初始化函数
* @note
*              基本定时器的时钟来自APB1,当PPRE1 ≥ 2分频的时候
*              基本定时器的时钟为APB1时钟的2倍, 而APB1为42M, 所以定时器时钟 = 84Mhz
*              定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
*              Ft=定时器工作频率,单位:Mhz
*
* @param       arr : 自动重装值。
* @param       psc : 时钟预分频数
* @retval      无
*/
void btim_timx_int_init(uint16_t arr, uint16_t psc)
{
   g_timx_handler.Instance = BTIM_TIMX_INT;                      /* 定时器x */
   g_timx_handler.Init.Prescaler = psc;                          /* 分频 */
   g_timx_handler.Init.CounterMode = TIM_COUNTERMODE_UP;         /* 递增计数模式 */
   g_timx_handler.Init.Period = arr;                             /* 自动装载值 */
   HAL_TIM_Base_Init(&g_timx_handler);
   
   HAL_TIM_Base_Start_IT(&g_timx_handler);                       /* 使能定时器x和定时器更新中断 */
}
  1. 底层驱动代码
**
 * @brief       定时器底层驱动,开启时钟,设置中断优先级
                此函数会被HAL_TIM_Base_Init()函数调用
 * @param       无
 * @retval      无
 */
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == BTIM_TIMX_INT)
    {
        BTIM_TIMX_INT_CLK_ENABLE();                     /* 使能TIMx时钟 */
        HAL_NVIC_SetPriority(BTIM_TIMX_INT_IRQn, 1, 3); /* 抢占1,子优先级3 */
        HAL_NVIC_EnableIRQ(BTIM_TIMX_INT_IRQn);         /* 开启ITMx中断 */
    }
}
  1. TIM中断服务函数
/**
 * @brief       基本定时器TIMX中断服务函数
 * @param       无
 * @retval      无
 */
void BTIM_TIMX_INT_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&g_timx_handler);  /* 定时器回调函数 */
}
  1. 回调函数
/**
 * @brief       回调函数,定时器中断服务函数调用
 * @param       无
 * @retval      无
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == BTIM_TIMX_INT)
    {
        LED1_TOGGLE(); /* LED1反转 */
    }
}
  • main.c
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/TIMER/btim.h"


int main(void)
{    
    HAL_Init();                             /* 初始化HAL库 */
    sys_stm32_clock_init(336, 8, 2, 7);     /* 设置时钟,168Mhz */
    delay_init(168);                        /* 延时初始化 */
    usart_init(115200);                     /* 串口初始化为115200 */
    led_init();                             /* 初始化LED */
    btim_timx_int_init(5000 - 1, 8400 - 1); /* 84 000 000 / 84 00 = 10 000 10Khz的计数频率,计数5K次为500ms */
    
    while(1)
    {
        LED0_TOGGLE();                      /* LED0(红灯) 翻转 */
        delay_ms(200);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32 第18讲 基本定时器(简介/计数模式/寄存器/溢出时间计算方法/实验) 的相关文章

随机推荐

  • (一)pygame.event详细解析

    文章目录 pygame event详细解析 函数表 函数详解 pygame event pump pygame event get pygame event poll pygame event wait pygame event peek
  • Elasticsearch学习笔记(一) DSL语句

    1 index 1 1 查询所有index GET cat indices v 1 2 新增index 新增一个名为pigg的index PUT pigg 1 3 删除index 删除pigg这个index 产线千万别这么做 删了就完了 D
  • 【react从入门到精通】深入理解React生命周期

    文章目录 人工智能福利文章 前言 React技能树 React的生命周期是什么 React v16 0前的生命周期 组件初始化 initialization 阶段 组件挂载 Mounting 阶段 组件更新 update 阶段 组件销毁阶段
  • 2.4.8 Profile虚拟IO设备

    最后更新2021 07 21 虚拟IO设备由HMC发出配置信息 由Hypervisor创建 虚拟IO设备并非真实存在 只是一些Hypervisor的参数 所以通常你可以根据需要 任意增删虚拟IO设备 但是创建虚拟IO设备依然有一些规则需要遵
  • Vue3.0——vite项目搭建

    2021 10 26 因为技术不断更新 故有些命令行不是最新的 随着后期补丁的更新 部分错误后期可能不存在了 建议大家参照时间节点看本片文章 1 搭建vite项目 npm init vitejs app 2 npm init vitejs
  • 用rsync命令和scp命令实现本机带进度条提示拷贝

    rsync命令 rsync av progress mnt yidong2 full20100526 tar gz mnt yidong1 以上命令 可以实现本机带进度条提示拷贝 可以实现不同机器带进度条提示拷贝 可以拷贝多个文件 scp命
  • 在Ubuntu20.04安装单节点ClickHouse22.8.4并解决DB::NetException: Connection refused NETWORK_ERROR导致无法远程访问的问题

    在Ubuntu20 04安装单节点ClickHouse22 8 4并解决DB NetException Connection refused 192 168 88 22 9000 NETWORK ERROR 导致无法远程访问的问题 前言 参
  • git将项目的其他分支合并到自己的分支

    步骤1 查看本地的所有分支 如果有即将合并的分支 则跳到 步骤3 git checkout 他人的分支名 git branch 步骤2 查看所有分支 确定即将合并的分支名 git branch a 步骤3 检出即将合并的分支到你的本地 gi
  • js中的class类

    js中的class类 函数声明和类声明之间的一个重要区别是函数声明会提升 类声明不会 需要先进行声明 再去访问 否则会报错 var father new Father 我是爸爸 class Father constructor name t
  • 跑路了,去东北国企干软件测试一个月的感触

    前言 不知不觉入职新公司快一个月了 突然心血来潮想跟大家唠唠 在新公司上班的感受 有好有坏 喜忧参半吧 工作环境 我新入职的公司是哈尔滨的一家国企下的二级子公司 新成立的研发公司 目前还处于蓬勃发展的阶段 业务水准也算的上是不错了 目前人数
  • 笔记本计算机硬盘如何分盘,笔记本电脑怎样分盘_笔记本电脑如何自己分盘-win7之家...

    在购买笔记本电脑之后 很多用户没有考虑清楚就随便将磁盘分盘 之后发现磁盘不够用 所以就想要重新分盘 不过许多小伙伴可能还不知道笔记本电脑怎样分盘吧 方法并不难 我们可以进入到计算机的管理中进行操作 这就给大家讲述一下笔记本电脑自己分盘的详细
  • 秦朝的军功制度

    作者 李四郎 链接 https www zhihu com question 35082355 answer 126247488 来源 知乎 著作权归作者所有 商业转载请联系作者获得授权 非商业转载请注明出处 二十级爵位可以按实际地位和待遇
  • 计算机视觉(十一):目标检测算法:R-CNN、Fast R-CNN、Faster R-CNN

    1 引言 在计算机视觉的发展中 我们的任务也越来越复杂 对于一张图像 我们不仅要实现对于目标的分类问题 还要准确的定位目标所在图片的位置 这个就是目标检测技术 在基于深度学习的目标检测技术中 就不得不提到最著名的三个算法了 R CNN Fa
  • 解决XML中符号解析问题

    当在xml中使用大于号 gt 小于号 lt 等字符时 会影响xml的解析 1 使用转义字符 lt lt 小于号 gt gt 大于号 amp 和 apos 单引号 quot 双引号 2 使用 被这个标记所包含的内容将表示为纯文本 比如表示文本
  • LeetCode 第7天 动态规划 (子序列问题 二)编辑距离 python

    以下题目来来源 力扣 LeetCode 链接 https leetcode cn problems uncrossed lines 著作权归领扣网络所有 商业转载请联系官方授权 非商业转载请注明出处 1035 不相交的线 在两条独立的水平线
  • redis主从同步 主机down

    redis主机设置了密码 将master和slave的密码配置相同 然后将slave的配置文件中的masterauth属性进行填写 将master的密码写上去即可使用命令slaveof或者在配置文件中 replicaof对master进行指
  • 一步一步教你Pycharm的配置Python环境

    1 点开你的pycharm 创建一个python文件 很多人学习python 不知道从何学起 很多人学习python 掌握了基本语法过后 不知道在哪里寻找案例上手 很多已经做案例的人 却不知道如何去学习更加高深的知识 那么针对这三类人 我给
  • LSTM与Bi-LSTM的时间序列预测(负荷预测)——附代码

    目录 摘要 1 电力负荷预测 2 滑动窗输入结构的构建 3 LSTM 4 Bi LSTM 5 程序运行结果 6 本文Matlab代码实现 摘要 本文使用LSTM和Bi LSTM 以电力负荷预测为例对比了两者的预测性能 其中将电力负荷构造为滑
  • Ubuntu下系统CPU/内存/GPU/硬盘监控查看指令

    1 实时监控CPU及内存的 Htop监控 安装 sudo apt get install htop 启动htop htop Ubuntu默认监控器 Win A打开所有APP 搜索System Monitor System Monitor如下
  • STM32 第18讲 基本定时器(简介/计数模式/寄存器/溢出时间计算方法/实验)

    文章目录 基本定时器简介 基本定时器框图 计数模式及溢出条件 递增计数模式 递减计数模式 中间对齐计数模式 相关寄存器 控制寄存器1 TIMx CR1 DMA 中断使能寄存器 TIMx DIER 状态寄存器 TIMx SR 计数器寄存器 T