stm32---基本定时器(TIM6,TIM7)

news/2024/11/29 23:38:06/

        STM32F1的定时器非常多,由两个基本定时器(TIM6,TIM7)、4个通用定时器(TIM2-TIM5)和两个高级定时器(TIM1,TIM8)组成。基本定时器的功能最为简单,类似于51单片机内定时器。通用定时器是在基本定时器的基础上扩展而来,增加了输入捕获与输出比较等功能。高级定时器又是在通用定时器基础上扩展而来,增加了可编程死区互补输出、重复计数器、带刹车(断路)功能,这些功能主要针对工业电机控制方面。但无论是哪个定时器,它们的频率都为72M。

基本定时器只有向上计数方式,且其挂载在APB1总线上,只能由内部时钟供能。基本定时器比较简单,就跟systic差不多。

这个是stm32的中文手册中的介绍。

图介绍:其中自动重装载寄存器(ARR)跟systic中的load寄存器作用一样,其作用主要有三部分:

  1. 设置定时器周期: ARR 决定了基本定时器计数器在溢出(从最大值返回0)之前所需的计数值。换句话说,ARR 值定义了定时器的定时周期。一旦计数器计数达到 ARR 的值,定时器将自动重新加载为0并触发一个更新事件。

  2. 产生定时中断: 当基本定时器的计数器达到 ARR 的值时,会触发一个更新事件,您可以配置定时器中断来捕获这个事件。这允许您在特定的时间间隔内执行代码,以执行定时任务。

  3. 生成PWM信号: 如果您使用基本定时器来生成PWM信号,ARR 将决定PWM信号的周期,即高电平和低电平的时间。

基本定时器通常是16位的,所以 ARR 可以设置的最大值是 65535。预分频器也是16位的,但是在预分频器中数值会自动加1,也就是它的取值范围为1到65536,(因为这个预分频器是作为分母用的,分母不能为0,如:给预分频值设为2-1,那么该定时器的频率为32M)。

自动重装载寄存器下面还有个影子寄存器,这个寄存器是实际起作用的寄存器,这个寄存器我们不能人为的去访问,基本定时器中的控制寄存器(TIMx_CR1)有一位(ARPE)是用来设置自动重装载寄存器是否具有缓冲的,stm32中文手册中的图如下:

当ARPE位设置为0时,该自动重装载寄存器不具备缓冲,它会直接把数值传给影子寄存器,

当ARPE位设置为1时,该自动重装载寄存器具备缓冲,它需要一个更新事件的产生才会把数值传给影子寄存器。

 我们可以写一个基本定时器的简单代码:

void TIM_MyConfig(u16 per,u16 psc)
{TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStruct;/*打开时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);/*初始化定时器*/TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1 ;TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStruct.TIM_Period = per;//自动重装载值TIM_TimeBaseInitStruct.TIM_Prescaler = psc; //分频系数TIM_TimeBaseInit(TIM6, &TIM_TimeBaseInitStruct);TIM_Cmd(TIM6, ENABLE);
}

1、第一步打开时钟,因为TIM2-TIM7都是挂载在APB1总线上的,所以我们需要打开APB1时钟,我们可以设置为TIM6。

2、初始化定时器,这个要注意函数是TIM_TimeBaseInit();,这个与其它(如:GPIO的初始化函数GPIO_Init)不一样,其中:

TIM_ClockDivision是用来设置定时器的时钟分频因子的成员,它用于控制定时器时钟的分频,从而影响定时器的计数速度。

在STM32中,TIM_ClockDivision 的设置有以下选项:

  1. TIM_CKD_DIV1: 不分频。定时器的时钟不经过分频,以外部时钟源的速度进行计数。

  2. TIM_CKD_DIV2: 分频为2。定时器的时钟被分为2,即每2个外部时钟周期计数器增加1。

  3. TIM_CKD_DIV4: 分频为4。定时器的时钟被分为4,即每4个外部时钟周期计数器增加1。

但是我们基本定时器使用到的是内部时钟源所以用不到 TIM_ClockDivision,可以设置为TIM_CKD_DIV1或者不配置这个成员,这个我们只在通用定时器或者高级定时器才用得到

TIM_CounterMode是用来设置计数模式的成员,基本定时器只有一种向上计数模式,所以这一位设置为TIM_CounterMode_Up就可以了。

TIM_Period是用来设置自动重装载值的成员(也就是设置计数次数),也就是自动重装载寄存器中的值,当计数器的计数值达到该值时会产生一个更新事件,这个值我们可以通过传参来设置。

TIM_Prescaler 是用来设置分频系数的值(也就是设置多久计数一次),该值也可以通过传参来设置。

在main函数中我们可以这样写:

void HardWare_Init(void)
{TIM_MyConfig(5000-1,7200-1);//0.5秒计数产生一次更新事件
}int main(void)
{u8 flag = 0;HardWare_Init();while(1){if(TIM_GetFlagStatus(TIM6,TIM_FLAG_Update) == SET){flag = !flag;}if(flag){PAin(8) = 0;}else{PAin(8) = 1;}TIM_ClearFlag(TIM6,TIM_FLAG_Update);}
}

可以通过设置基本定时器来让LED灯按时闪烁,其中也用到了位带操作(PAin(8))。因为我们需要判断的是定时器是否发生更新事件,当定时器发生更新事件时说明完成了一个计数周期,所以我们用到的函数是 TIM_GetFlagStatus(TIM6,TIM_FLAG_Update)。


http://www.ppmy.cn/news/1107406.html

相关文章

如何快速理解JavaScript的递归

前言: 递归是一种在编程中经常使用的概念,它可以帮助我们解决一些需要重复执行相似操作的问题。在JavaScript中,递归是一种函数调用自身的技术。在本文中,我们将探讨递归的原理、使用场景以及一些注意事项。 原理 首先&#xf…

712. 两个字符串的最小ASCII删除和 -- 动规

712. 两个字符串的最小ASCII删除和 class MinimumDeleteSum:"""712. 两个字符串的最小ASCII删除和https://leetcode.cn/problems/minimum-ascii-delete-sum-for-two-strings/"""def solution(self, s1: str, s2: str) -> int:""&qu…

stu01-IDEA怎么创建一个HTML项目

1.打开idea,依次点击file→new→project 2.点击Java,选择你的jdk,没有下载的点击“Download JDK”/已经下载有JDK但在这里没显示的→点击“Add JDK”,选择你安装的JDK的路径,然后next 3.next 4.起好名字,我…

Rabbitmq基本概念-01

MQ介绍 1、什么是MQ?为什么要用MQ? MQ:MessageQueue,消息队列。 队列,是一种FIFO 先进先出的数据结构。消 息由生产者发送到MQ进行排队,然后按原来的顺序交由消息的消费者进行处理。 QQ和微信就是典型的MQ…

Redis 初识与入门

1. 什么是Redis Redis 是一种基于内存的数据库,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于缓存,消息队列、分布式锁等场景。 Redis 提供了多种数据类型来支持不同的业务场景,比如 String(字符串)、…

docker安装xxl-job连接数据库时显示无法连接问题

背景: 在项目中需要定时任务调度,需要在docker容器中安装xxl-job 遇到的问题 部署成功后,可以访问xxl-job登录界面,点登录没反应,但过一段时间就弹出数据库拒绝连接,说MyBatis连接用户失败 原因&#xf…

udev自动创建设备节点的机制

流程框图如下 自动创建 1 内核检测到设备插入后,会发送一个uevent事件到内核中,并提供有关硬件设备的信息。 2 udevd守护程序收到uevent事件后,创建一个设备类,(向上提交目录信息),会在内核中…

「提效脚本 redis」 使用Lua批量删除key

在redis里面可以使用keys aa* 进行匹配所有的key,却没办法直接删除所有匹配的key。 所以可以使用lua脚本进行增强。 以删除 suggest* 开头的key为例。 eval "local keys redis.call(keys, suggest*) for _, key in ipairs(keys) do redis.call(del, key) …