STM32-定时器系列(一)基本定时器

2023-11-03

    相信学过51单片机的小伙伴们使用过定时刷新数码管吧,那也一定想过,我们在STM32中也想要实现定时刷新数码管,这该怎么实现呢?下面小编就带大家走进STM32的定时器模块吧!

一、什么是定时器

    定时器是一种计时的工具,它具有延时、频率测量、PWM输出、电机控制及编码接口等功能。
    STM32F103微控制器内部集成了多个可编程定时器,可以分为基本定时器(TIM6和TIM7)、通用定时器(TIM2~TIM5)和高级定时器(TIM1、TIM8)3种类型。从功能上看,基本定时器的功能是通用定时器的子集,而通用定时器的功能又是高级定时器的一个子集。

二、基本定时器

1、相关概念

    在STM32F103中,基本定时器TIM6、TIM7各自都包含一个16位自动装载计数器,能够通过各自的可编程预分频器驱动,这两个定时器相互独立,不共享任何资源。

2、主要功能

  • (1)16位自动重载累加计数器
  • (2)16位可编程(可实时修改)预分频器
  • (3)触发DAC同步电路
  • (4)能够咱更新事件(计数器溢出)时产生DMA/中断请求

3、相关寄存器

■ TIM6 和TIM7 控制寄存器 1(TIMx_CR1)
■ TIM6 和TIM7 控制寄存器 2(TIMx_CR2)
■ TIM6 和TIM7 DMA/中断使能寄存器(TIMx_DIER)
■ TIM6 和TIM7 状态寄存器(TIMx_SR)
■ TIM6 和TIM7 事件产生寄存器(TIMx_EGR)
■ TIM6 和TIM7 计数器(TIMx_CNT)
■ TIM6 和TIM7 预分频器(TIMx_PSC)
■ TIM6 和TIM7 自动重装载寄存器(TIMx_ARR)

三、函数解析

1、清除中断标志位TIM_ClearFlag函数

在这里插入图片描述

2、定时器使能失能设置TIM_Cmd函数

在这里插入图片描述

3、定时器初始化TIM_TimeBaseInit函数

在这里插入图片描述

定时器时基单元配置信息结构体TIM_TimeBaseInitTypeDef

typedef struct
{
  uint16_t TIM_Prescaler;        
  uint16_t TIM_CounterMode;       
  uint16_t TIM_Period;           
  uint16_t TIM_ClockDivision;     
  uint8_t TIM_RepetitionCounter; //仅高级定时器TIM1和TIM8有效
} TIM_TimeBaseInitTypeDef;
  • TIM_Period:
        设置在下一个更新事件装入活动的自动重装载寄存器周期的值。它的取值必须在 0x0000 和0xFFFF 之间。
  • TIM_Prescaler:
        设置用来作为 TIMx 时钟频率除数的预分频值。它的取值必须在 0x0000 和 0xFFFF 之间。
  • TIM_ClockDivision:
        配置时钟分割,具体值见下表:
    在这里插入图片描述
  • TIM_CounterMode :
        选择时钟模式,具体选项见下表:
    在这里插入图片描述

四、示例

    小明突发奇想,打算利用STM32F103ZET6开发板做出一个实时时钟出来,其中利用定时器计时并且利用定时器来刷新数码管。

1、基本定时器6(TIM6)配置函数

/*
	* @brif intialization of time(定时器初始化)
	* @para none
	* @reval none
*/
void time6_init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	//打开Time6的APB1时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
	
	/*  定时器的初始化以及设置 */
	//设置自动装载周期的值 寄存器的值为周期的值-1
	TIM_TimeBaseStructure.TIM_Period = 360-1;
	//设置预分频系数 预分频寄存器的值为分频系数-1
	TIM_TimeBaseStructure.TIM_Prescaler = 200-1;
	//设置时钟分割 TDTS =  Tck_tim
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	//时钟设置为向上计数模式
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM6,&TIM_TimeBaseStructure);
	
	//清楚TIMx的中断待处理位 即TIMx的中断源
	TIM_ClearFlag(TIM6,TIM_FLAG_Update);
	
	/* 设置参数并打开中断*/
	TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);
	//设置使能或者失能外设
	TIM_Cmd(TIM6,ENABLE);
	
	/* 设置NVIC参数 即优先级、打开中断 */
	NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;//指定终端通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//配置抢占式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//配置响应式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//设置成使能中断
	NVIC_Init(&NVIC_InitStructure);
}

2、基本定时器7(TIM7配置函数)

/*
	* @brif intialization of time(定时器初始化)
	* @para none
	* @reval none
*/
void time7_init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	//打开Time6的APB1时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE);
	
	/*  定时器的初始化以及设置 */
	//设置自动装载周期的值 寄存器的值为周期的值-1
	TIM_TimeBaseStructure.TIM_Period = 36000-1;
	//设置预分频系数 预分频寄存器的值为分频系数-1
	TIM_TimeBaseStructure.TIM_Prescaler = 2000-1;
	//设置时钟分割 TDTS =  Tck_tim
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	//时钟设置为向上计数模式
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM7,&TIM_TimeBaseStructure);
	
	//清楚TIMx的中断待处理位 即TIMx的中断源
	TIM_ClearFlag(TIM7,TIM_FLAG_Update);
	
	/* 设置参数并打开中断*/
	TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE);
	//设置使能或者失能外设
	TIM_Cmd(TIM7,ENABLE);
	
	/* 设置NVIC参数 即优先级、打开中断 */
	NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;//指定终端通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//配置抢占式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//配置响应式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//设置成使能中断
	NVIC_Init(&NVIC_InitStructure);
}


3、基本定时器6中断处理函数

void TIM6_IRQHandler(void)
{ 
	TIM_ClearFlag(TIM6,TIM_IT_Update);//清楚中断标志位
	refresh_segs();//刷新数码管
}

4、基本定时器7中断处理函数

void TIM7_IRQHandler(void)
{ 
	TIM_ClearFlag(TIM7,TIM_IT_Update);
	if(++second==60){//时钟的秒加1并且判断是否需要分钟加1
		second=0;
		if(++minute==60){//时钟的分加1并且判断是否需要时钟加1
			minute=0;
			if(++hour==24) hour=0;//时钟的时加1并且判断24小时是否过完
		}
	}	
}

5、主函数

int main(void)
{
	time6_init();
	time7_init();
	seg_GPIO_Init();
	while(1){
		segbuff[0] = hour/10;
		segbuff[1] = hour%10+12;
		segbuff[2] = minute/10;
		segbuff[3] = minute%10+12;
		segbuff[4] = second/10;
		segbuff[5] = second%10;
	}
}

五、附

1、基本定时器配置6、基本定时器7的配置

    基本定时器6与基本定时器7在同一个函数中进行配置

/*
	* @brif intialization of time(定时器初始化)
	* @para none
	* @reval none
*/
void time6_init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	//打开Time6的APB1时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
	//打开Time7的APB1时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE);
	
	/*  定时器的初始化以及设置 */
	//设置自动装载周期的值 寄存器的值为周期的值-1
	TIM_TimeBaseStructure.TIM_Period = 360-1;
	//设置预分频系数 预分频寄存器的值为分频系数-1
	TIM_TimeBaseStructure.TIM_Prescaler = 200-1;
	//设置时钟分割 TDTS =  Tck_tim
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	//时钟设置为向上计数模式
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM6,&TIM_TimeBaseStructure);
	
	//清楚TIMx的中断待处理位 即TIMx的中断源
	TIM_ClearFlag(TIM6,TIM_FLAG_Update);
	/* 设置参数并打开中断*/
	TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);
	//设置使能或者失能外设
	TIM_Cmd(TIM6,ENABLE);
	
	/*  定时器的初始化以及设置 */
	//设置自动装载周期的值 寄存器的值为周期的值-1
	TIM_TimeBaseStructure.TIM_Period = 36000-1;
	//设置预分频系数 预分频寄存器的值为分频系数-1
	TIM_TimeBaseStructure.TIM_Prescaler = 2000-1;
	//设置时钟分割 TDTS =  Tck_tim
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	//时钟设置为向上计数模式
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM7,&TIM_TimeBaseStructure);
		
	//清楚TIMx的中断待处理位 即TIMx的中断源
	TIM_ClearFlag(TIM7,TIM_FLAG_Update);
	/* 设置参数并打开中断*/
	TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE);
	//设置使能或者失能外设
	TIM_Cmd(TIM7,ENABLE);
	
	/* 设置NVIC参数 即优先级、打开中断 */
	NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;//指定终端通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//配置抢占式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//配置响应式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//设置成使能中断
	NVIC_Init(&NVIC_InitStructure);

	/* 设置NVIC参数 即优先级、打开中断 */
	NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;//指定终端通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//配置抢占式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//配置响应式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//设置成使能中断
	NVIC_Init(&NVIC_InitStructure);
}

2、基本定时器的定时时长计算

  • 定时时长T=(自动装载周期的值+1)(预分频系数+1)/72MHz;
      例如,上面用于数码管刷新基本定时器6定时的时长T=360
    200/72000000=1/1000s;用于实时时钟时间刷新的基本定时器7的定时时长T=36000*2000/72000000=1s。

3、其他相关函数

    假如大家想看相关模块的内容请点击链接前往:STM32-刷新数码管

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32-定时器系列(一)基本定时器 的相关文章

  • GCC ARM 汇编预处理器宏

    我正在尝试使用汇编 ARM 宏进行定点乘法 define MULT a b asm volatile SMULL r2 r3 0 1 n t ADD r2 r2 0x8000 n t ADC r3 r3 0 n t MOV 0 r2 ASR
  • 为 ARM 交叉编译 zlib

    我尝试为arm poky linux gnueabi交叉编译zlib 但启动 make 时出现错误 zlib 1 2 11 AR HOST ar CC HOST gcc RANLIB HOST ranlib configure prefix
  • 如何在 Android 设备上运行 VS Code [重复]

    这个问题在这里已经有答案了 我有 Galaxy Tab S6 它具有替代笔记本电脑的很酷的功能 例如连接鼠标和键盘 但不幸的是它运行 Android 操作系统 并且没有很多开发应用程序可用于 Android 所以我想是否有一个选项可以在至少
  • 分析 Cortex-M7 (stm32f7) 上的 memcpy 性能

    简洁版本 从 GNU ARM 工具链中提取的 memcpy 的性能指标在 ARM Cortex M7 上对于不同的副本大小似乎差异很大 即使复制数据的代码始终保持不变 这可能是什么原因造成的 长版 我是使用 GNU Arm 工具链 11 2
  • 移动数组中的元素

    我需要一点帮助 我想将数组中的元素向上移动一个元素 以便新位置 1 包含位置 1 中的旧值 new 2 包含 old 1 依此类推 旧的最后一个值被丢弃 第一个位置的新值是我每秒给出的新值 我使用大小为 10 的数组 uint32 t TE
  • STM32 传输结束时,循环 DMA 外设到存储器的行为如何?

    我想问一下 在以下情况下 STM32 中的 DMA SPI rx 会如何表现 我有一个指定的 例如 96 字节数组 名为 A 用于存储从 SPI 接收到的数据 我打开循环 SPI DMA 它对每个字节进行操作 配置为 96 字节 是否有可能
  • 使用 Android NDK 使用 -fsigned-char 进行构建安全吗?

    为了与其他平台保持一致 我需要使用signed char在我正在处理的一些本机代码中 但默认情况下在Android NDK上char类型是unsigned 我尝试明确使用signed char类型 但它生成太多警告differ in sig
  • 是否可以将 SpaCy 安装到 Raspberry Pi 4 Raspbian Buster

    我一整天都在安装 SpaCy sudo pip install U spacy Looking in indexes https pypi org simple https www piwheels org simple Collectin
  • 了解 U-Boot 内存占用

    我不明白加载 U Boot 时 RAM 中发生了什么 我正在开发 Xilinx Zynq ZC702 评估套件 并尝试使用 U Boot 在其上加载 Linux 内核 于是我使用Xilinx工具Vivado和SDK生成了一个BOOT bin
  • gdb 不会从外部架构读取核心文件

    我正在尝试在 Linux 桌面上读取 ARM 核心文件 但似乎无法找出我的核心文件 有什么方法可以指示 gdb 我的核心文件是什么类型吗 file daemon daemon ELF 32 bit LSB executable ARM ve
  • saber sd 如何在没有 SPL 的情况下直接从 uboot 启动

    sabre sd 基于 imx 6 最大内部 RAM 约为 150Kb 然而 uboot 足够大 可以容纳在这个空间中 在这个场景中事情是如何进行的 https community freescale com docs DOC 95015
  • Qemu flash 启动不起作用

    我有一本相当旧的 2009 年出版 嵌入式 ARM Linux 书 其中使用u boot and qemu 的用法qemu与u boot书中对二进制的解释如下 qemu system arm M connex pflash u boot b
  • 英特尔的最后分支记录功能是英特尔处理器独有的吗?

    最后分支记录是指存储与最近执行的分支相关的源地址和目标地址的寄存器对 MSR 的集合 它们受英特尔酷睿 2 英特尔至强和英特尔凌动处理器系列的支持 http css csail mit edu 6 858 2012 readings ia3
  • ARM NEON 矢量化失败

    我想在 ARM cortex a9 上启用 NEON 矢量化 但在编译时得到以下输出 未矢量化 不支持相关 stmt D 14140 82 D 14143 77 D 14141 81 这是我的循环 void my mul float32 t
  • 上下文切换到安全模式(arm trustzone)的成本是多少

    我试图了解在arm中可信 安全 和非安全模式之间来回切换的成本 从非安全世界转移到安全世界时到底需要发生什么 我知道需要设置 ns 位 基于某些特殊指令 需要刷新和更新页表 刷新和更新处理器缓存 还有什么需要发生的吗 处理器缓存 它们是分段
  • aarch64 Linux 硬浮点或软浮点

    linux系统有arm64 有arm架构armv8 a 如何知道 Debian 运行的是硬浮动还是软浮动 符合 AAPCS64 GNU GCC for armv8仅提供硬浮动aarch64工具链 这与 armv7 a 的 GCC 不同 后者
  • A64 Neon SIMD - 256 位比较

    我想将两个小端 256 位值与 A64 Neon 指令 asm 进行有效比较 平等 为了平等 我已经有了解决方案 bool eq256 const UInt256 lhs const UInt256 rhs bool result 首先 将
  • LDR指令如何将常量加载到寄存器中?

    我刚刚读了一本ARM指令书 看到一条指令我无法解释 It says LDR将 32 位常量加载到r0登记 LDR r0 pc const number 8 pc const number DCD 0xff00ffff 我不明白什么 pc c
  • 在 ARM Cortex-M3 中使用 newlib 的 malloc

    我正在为 ARM Cortex M3 NXP 的 LCP17xx 创建代码 到目前为止我一直在使用静态内存 一切都运行良好 我尝试添加动态内存支持 但是一旦调用 malloc 系统就会卡住 我正在使用 gcc 为 Arm Bare Meta
  • 什么是 .axf 文件?

    我是arm架构的新手 我从事嵌入式软件工作 并试图了解我的项目二进制文件的调试文件夹中存在的 axf文件 发现它是链接器在构建过程中生成的arm可执行格式文件 用于调试崩溃 所以很明显它包含了一些调试信息 但不清楚具体是什么信息 而且deb

随机推荐

  • 【MATLAB第10期】基于贝叶斯Bayes算法优化LSTM长短期记忆网络的多输入单输出回归预测模型思路框架

    基于贝叶斯Bayes算法优化LSTM长短期记忆网络的多输入单输出回归预测模型思路框架 前言 前面在 MATLAB第8期 讲解了基于贝叶斯Bayes算法优化LSTM长短期记忆网络的时间序列预测模型 即单输入数据时间序列预测 见本人知乎主页 思
  • 部署gitlab,模拟开发流程

    一 安装gitlab 1 需要先安装依赖包 yum install y curl policycoreutils python openssh server postfix 2 gitlab 下载网址 https mirrors tuna
  • 双系统下Ubuntu突然不能连接WiFi解决办法

    注意是突然不能连接 1 在Windows系统下 我的电脑 gt 管理 gt 设备管理 gt 网络适配器里面有个WiFi 2 选中右键属性 然后把那个运行电脑关机时关闭WiFi节省电脑的 去掉即可
  • 安装WSL,Ubuntu,子系统备份与迁移

    1 安装WSL及Ubuntu 在搜索框里打入cmd以管理员方式运行 键入wsl install并按回车 此命令将启用运行 WSL 并安装 Linux 的 Ubuntu 发行版 默认安装 wsl install 如果不想安装Ubuntu发行版
  • 基于Dlib进行人脸特征点检测的Python代码实现

    一 Python代码实现 import sys import os import glob import dlib import numpy as np import cv2 把imread中的路径修改为自己的图片路径 图片格式为jpeg格
  • Linux操作系统之tcp并发编程

    一 tcp并发编程 运行结果 多线程运行代码 运行结果 二 发送缓冲区与接收缓冲区 运行结果 为什么会出现以上的现象呢 因为在服务端与客户端都存在发送缓冲区与接收缓冲区
  • Unity插件 --- LeanTouch的使用

    在unity自带的asset store搜索 Lean touch 然后找到对应的资源 然后全部都导入到项目中 1 开启和关闭 private void OnEnable LeanTouch OnFingerDown HandeFinger
  • 浅读设计模式

    浅读设计模式 1 引言 2 重新认识一下UML 3 设计模式的七大原则 4 设计模式的分类 5 设计模式的具体说明 6 容易混淆的设计模式之间的区别 6 1创建型设计模式 6 2结构型设计模式 6 3行为型设计模式 6 4跨类对比 7 声明
  • 伪元素::after和::before的”前世今生“

    序言 在做前端页面时 需要做一些样式上的改变 使用伪元素很轻易就做到了 之前一直说伪元素还可以清除浮动 然后就想了解一下这东西到底能干什么 如下图 之前碰到的 为元素添加边框样式 小程序中修改radio checkbox的默认样式 都用到了
  • Blender_5_挤出

    这一专栏是我的学习笔记 小白 欢迎评论交流 在此感谢B站辣椒酱的教学视频 挺好玩的 1 挤出选区 选中面之后 快捷按钮栏选择 挤出 拖拽黄色的小圆 也可以在选中面之后 按快捷键E 很方便 下面是正方体 选中顶面之后挤出的效果 2 挤出流形
  • 数字IC设计——跨时钟域篇1(时钟域)

    数字IC设计 跨时钟域篇1 一 时钟域概要 1 CDC介绍 CDC clock domain crossing 检查 跨时钟域的检查 是对电路设计中同步电路设计的检查 非同步时钟没有固定的相位关系 这样Setup Hold不满足而产生了亚稳
  • Rk3399 Android9.0 恢复出厂设置流程

    Reset 流程 1 原生设置中响应 恢复出厂设置 功能 继而发出重置广播 Intent ACTION FACTORY RESET 2 frameWork层 接收到此广播 根据广播所携带的参数执行Android层的Reset设定 3 And
  • kafka简单代码实现

    生产者 package cn smart storm kafka simple import kafka javaapi producer Producer import kafka producer KeyedMessage import
  • 现代c++白皮书(C++17)

    8 C 17 大海迷航 在经过 C 14 这个小版本标准之后 C 17 Smith 2017 原本被看作是一个大版本 C 17 有很多新的特性 但没有一个我认为称得上重大 尽管我们已经有给 C 11 和 C 14 带来成功的工作流程 标准社
  • 使用GDB调试C++程序

    以下是GDB调试的常用流程和一些常用命令 编译源代码 使用C 编译器 如g 将源代码编译为可执行文件 例如 使用以下命令编译名为program cpp的源代码文件 g g program cpp o program 启动GDB调试器 在终端
  • 【异地组网】蒲公英x1保姆级教程

    异地组网 蒲公英x1教程 文章目录 异地组网 蒲公英x1教程 一 组网配置 1 连接线路 2 登录官网 3 配置旁路 二 手机端异地访问 三 windows端异地访问 四 异地访问测试 一 组网配置 1 连接线路 将蒲公英盒子接入对应配置的
  • Angular6笔记(5)

    1 构造函数 构造函数是当类进行实例化时执行的特殊函数 通常会在构造函数中对新对象进行初始化工作 构造函数必须命名为constructor 因为构造函数是在类被实例化时调用的 所以它们可以 有输入参数 但不能有任何返回值 我们要通过调用ne
  • JavaScript将一维数组转化为二维数组

    JavaScript将一维数组转化为二维数组 遇到的问题 后端返回的是一组一维数组 但是需要展示的格式是二维数组 常见的场景举例 后台返回10个长度的数组 需要分成3个一组展示在banner上 例 1 2 3 4 5 6 7 8 9 10
  • 《Contextual Transformer Networks for Visual Recognition》阅读笔记

    传统的Transformer是使用1x1卷积操作来获key query pair 这种key query pair都是独立的 没有考虑上下文 作者提出了一种使用3x3卷积操作来得到融合上下文的key 局部上下文 作为static conte
  • STM32-定时器系列(一)基本定时器

    相信学过51单片机的小伙伴们使用过定时刷新数码管吧 那也一定想过 我们在STM32中也想要实现定时刷新数码管 这该怎么实现呢 下面小编就带大家走进STM32的定时器模块吧 一 什么是定时器 定时器是一种计时的工具 它具有延时 频率测量 PW