STM32时钟和定时器
时钟源
STM32包含了5个时钟源,分别为HSI、HSE、LSI、LSE、PLL。
- HSI是高速内部时钟、RC振荡器,频率为8MHz;
- HSE是高速外部时钟,即晶振,可接石英/陶瓷谐振器或接外部时钟源,频率范围为4MHz~16MHz;
- LSI为低速内部时钟、RC振荡器,频率40kHz;
- LSE为低速外部时钟,接32.768kHz晶振,作为RTC时钟源;
- PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz;
定时器TIM2~TIM7挂载在APB1分频器上,TIM1和TIM8挂载在APB2分频器上;APB1上面挂载的是低速外设,APB2上挂载高速外设。APB2可以工作在72MHz下,而APB1最大是36MHz。
定时器的产生路线:系统时钟 -> AHB预分频 -> APB2预分频 -> TIM1倍频器 -> 产生TIM1的时钟系统
在system_stm32f10x.c文件下,有默认定义SYSCLK_FREQ_72MHz,同时在SystemInit()函数下调用了SetSysClock(),根据宏定义将时钟设为72MHz。读取SystemCoreClock变量即可获得系统时钟频率。
在默认情况下,系统的各个时钟频率如下:
- SYSCLK:72M
- AHB:72M
- APB1(PCLK1):36M
- APB2(PCLK2):72M
- PLL:72M
计时器的类型
- TIM1和TIM8是高级定时器
- TIM2-TIM5是通用定时器
- TIM6和TIM7是基本的定时器
这8个定时器都是16位的,它们的计数器的类型除了基本定时器TIM6和TIM7其他都支持向上、向下、向上/向下这3种计数模式。
计数器的三种计数模式
- 向上计数模式:从0开始,计到arr预设值,产生溢出事件,返回重新计时
- 向下计数模式:从arr预设值开始,计到0,产生溢出事件,返回重新计时
- 中央对齐模式:从0开始向上计数,计到arr产生溢出事件,然后向下计数,计数到1以后,又产生溢出,然后再从0开始向上计数。(此种技术方法也可叫向上/向下计数)
各定时器的主要功能
基本定时器(TIM6、TIM7)的主要功能:
只有最基本的定时功能,基本定时器TIM6和TIM7各包含一个16位自动装载计数器,由各自的可编程预分频器驱动。主要用于产生DAC触发信号。
通用定时器(TIM2~TIM5)的主要功能:
除了基本的定时器的功能外,还具有测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)
高级定时器(TIM1、TIM8)的主要功能:
高级定时器不但具有基本/通用定时器的所有的功能外,还具有控制交直流电动机所有的功能,比如它可以输出6路互补带死区的信号,刹车功能等等。
详细的定时器设定如下:
- 首先要搞清楚定时器的计数时钟频率,在预分频系数≠1的时候,TIM2~7的时钟频率为APB1的频率的2倍,即72MHz,预分频系数的默认值不是1。
- 定时器的设置主要包括定时器的初始化和中断的初始化。
定时器的时钟不是直接来自APB1或APB2,而是来自输入为APB1或APB2的一个倍频器,当APB1的预分频系数为1时,这个倍频器不起作用,定时器的时钟频率等于APB1的频率;当APB1的预分频系数为其它数值(即预分频系数为2、4、8或16)时,这个倍频器起作用,定时器的时钟频率等于APB1的频率的两倍。
假定AHB=36MHz,因为APB1允许的最大频率为36MHz,所以APB1的预分频系数可以取任意数值;
当预分频系数=1时,APB1=36MHz,TIM2~7的时钟频率=36MHz(倍频器不起作用);
当预分频系数=2时,APB1=36MHz/2=18MHz,在倍频器的作用下,TIM2~7的时钟频率=36MHz;
当预分频系数=4时,APB1=36MHz/4=9MHz,在倍频器的作用下,TIM2~7的时钟频率=18MHz;
当预分频系数=8时,APB1=36MHz/8=4.5MHz,在倍频器的作用下,TIM2~7的时钟频率=9MHz;
当预分频系数=16时,APB1=36MHz/16=2.25MHz,在倍频器的作用下,TIM2~7的时钟频率=4.5MHz;
既然需要TIM2~7的时钟频率=36MHz,为什么不直接取APB1的预分频系数=1呢?这是因为APB1不但要为TIM2~7提供时钟,而且还要为其它外设提供时钟,设置这个倍频器可以在保证其它外设使用较低时钟频率时,TIM2~7仍能得到较高的时钟频率。例如当AHB=72MHz时,APB1的预分频系数必须大于2,因为APB1的最大频率只能为36MHz。如果APB1的预分频系数=2,则因为这个倍频器,TIM2~7仍然能够得到72MHz的时钟频率。能够使用更高的时钟频率,无疑提高了定时器的分辨率,这也正是设计这个倍频器的初衷。
定时器初始化:
首先定义TIM_TimeBaseInitTypeDef类型的结构体,它包含了如下的内容:
typedef struct
{
uint16_t TIM_Prescaler;
uint16_t TIM_CounterMode;
uint16_t TIM_Period;
uint16_t TIM_ClockDivision;
uint8_t TIM_RepetitionCounter;
} TIM_TimeBaseInitTypeDef;
第一项 TIM_Prescaler 是定时器预分频值,时钟源经该预分频器才是定时器时钟,它设定TIMx_PSC 寄存器的值。可设置范围为 0 至 65535,实现 1至 65536 分频。
第二项 TIM_CounterMode 为定时器计数模式,它的内容如下:
#define TIM_CounterMode_Up ((uint16_t)0x0000)
#define TIM_CounterMode_Down ((uint16_t)0x0010)
#define TIM_CounterMode_CenterAligned1 ((uint16_t)0x0020)
#define TIM_CounterMode_CenterAligned2 ((uint16_t)0x0040)
#define TIM_CounterMode_CenterAligned3 ((uint16_t)0x0060)
它可以是向上计数、向下计数以及三种中心对齐模式。基本定时器只能是向上计数,即 TIMx_CNT只能从0开始递增,并且无需初始化。
第三项 TIM_Period 为定时器周期,当计数寄存器的值递增到等于该值时,将相关事件标志位置位。范围为0 至 65535。
第四项 TIM_ClockDivision 为时钟分频,设置定时器时钟 CK_INT 频率与数字滤波器采样时钟频率分频比,基本定时器没有此功能,不用设置。
第五项 TIM_RepetitionCounter 为重复计数器,属于高级控制寄存器专用寄存器位,利用它可以非常容易控制输出 PWM 的个数。一般的定时器不需要设置。
循环定时时间的计算:基本定时器只有内部时钟72MHz,定时器的实际时钟=内部时钟 / ( 定时器预分频值 + 1 ),那么如果 TIM_Prescaler 设置为7200-1,则内部时钟源经过定时器预分频后即可得到 (72MHz / (7200-1)+1)=10kHz的频率。然后 TIM_Period 设置为5000-1(因为计数是从0开始,所以要减1),即可得到定时时间为(5000 * (1 / 10kHz))=0.5s的定时器。
除此之外还要设置中断的类型,一般的定时器为更新中断,即由溢出事件产生的中断,设置的方式为:TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE),其中第一项是定时器代号,第二项为类型,这里设定为更新方式,第三项为使能。
TIM3的初始化函数:
void TIM3_Init(u16 arr,u16 psc)
{
// 定时时间=(arr+1)*(psc+1)/72 单位为us
TIM_TimeBaseInitTypeDef TIM_STR;
NVIC_InitTypeDef NVIC_STR;
// TIM3挂载在APB1上,由于预分频系数默认不是1,所以TIM3的时钟为2*APB1=72M
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
//初始化定时器
TIM_STR.TIM_Period=arr;
TIM_STR.TIM_Prescaler=psc;
// (arr+1)*(psc+1)/TIM时钟=定时器溢出中断触发周期
TIM_STR.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_STR.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&TIM_STR);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
// 初始化中断
// 设定为TIM3中断
NVIC_STR.NVIC_IRQChannel=TIM3_IRQn;
// 先占优先级0级
NVIC_STR.NVIC_IRQChannelPreemptionPriority=0;
// 从优先级3级
NVIC_STR.NVIC_IRQChannelSubPriority=3;
// IRQ通道时能
NVIC_STR.NVIC_IRQChannelCmd=ENABLE;
// 中断初始化
NVIC_Init(&NVIC_STR);
// 使能定时器
TIM_Cmd(TIM3,ENABLE);
}
中断服务函数:
TIM3的中断函数为 TIM3_IRQHandler
中断服务函数内包含了:判断是否发生中断、中断发生后执行的内容、清除标志位三部分。
void TIM3_IRQHandler(void)
{
// 判断是否发生中断
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{
// 清除标志位
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
// 执行中断内容
}
}
完成调用
只要在main函数里调用 TIM3_Init() 函数,并填入适当的参数,即可实现精确的定时中断,例如获得1秒,即(arr+1)*(psc+1)/72000000 = 1,则可分解成arr=9999,psc=7199,配置如下:
TIM3_Init(9999,7199);
STM32时钟和定时器的更多相关文章
- STM32时钟理解
转载自 http://blog.sina.com.cn/s/blog_6ebd49350100q6xw.html STM32时钟理解 一.硬件上的连接问题 如果使用内部RC振荡器而不使用外部晶振,请按 ...
- STM32学习笔记——定时器中断(向原子哥学习)
定时器中断 STM32 的定时器功能十分强大,有 TIME1 和 TIME8 等高级定时器,也有 TIME2~TIME5 等通用定时器,还有 TIME6 和TIME7 等基本定时器.在本章中,我们将利 ...
- Stm32之通用定时器复习
因为毕业设计要用到PWM调光很久都没用到Stm32的定时器,有些内容已经遗忘,为了回顾复习相关内容今天开下通用定时器这一章节的数据手册. 1.时钟 通用定时器一般是TIM2~TIM5,TIM1.TIM ...
- STM32入门系列-STM32时钟系统,STM32时钟树
时钟对于单片机来说是非常重要的,它为单片机工作提供一个稳定的机器周期从而使系统能够正常运行.时钟系统犹如人的心脏,一旦有问题整个系统就崩溃.我们知道STM32属于高级单片机,其内部有很多的外设,但不是 ...
- LibOpenCM3(五) 基础功能: 系统时钟, GPIO, 定时器
目录 LibOpenCM3(一) Linux下命令行开发环境配置 LibOpenCM3(二) 项目模板 Makefile分析 LibOpenCM3(三) .ld文件(连接器脚本)和startup代码说 ...
- stm32时钟配置总结
stm32时钟配置时钟源: 1,HSE(高速外部时钟)即常见的外接8M晶振方案: 2,HSI(高速内部时钟) 即8M内部振荡时钟方案: 3,LSE(低速外部时钟)即常见的32.768Khz晶振方案: ...
- STM32 TIM高级定时器死区时间的计算
STM32 TIM高级定时器的互补PWM支持插入死区时间,本文将介绍如何计算以及配置正确的死区时间. 文章目录 什么是死区时间? 数据手册的参数 如何计算合理的死区时间? STM32中配置死区时间 什 ...
- STM32 TIM1高级定时器RCR重复计数器的理解
STM32 TIM1高级定时器RCR重复计数器的理解 TIMx_RCR重复计数器寄存器,重复计数器只支持高级定时器TIM1和TIM8,下面看标准外设库的TIM结构体的封装: typedef struc ...
- STM32时钟系统的配置寄存器和源码分析
一.时钟系统 概述 时钟是单片机运行的基础,时钟信号推动单片机内各个部分执行相应的指令,时钟系统就是CPU的脉搏,决定cpu速率. STM32有多个时钟来源的选择,为什么 STM32 要有多个时钟源呢 ...
随机推荐
- 修改ubuntu默认源
修改文件 桌面版Ubuntu默认非root账户 可以先在 home/user/下新建一个文件source.list-new 将其写为 deb http://mirrors.aliyun.com/ubu ...
- 阿里云docker部署mysql
看完我的上一个博客之后,对centos系统应该有一定的了解,话不多说,接下来我们来在docker容器中部署mysql. 1.下载mysql镜像,因为本人用的5.7版本,你也可以下载最新版,都是可以的 ...
- docker部署LAMP架构并部署上线wordpress博客系统
第一步:直接在镜像仓库拉取LAMP镜像 [root@ken-node3 ken]# docker pull tutum/lamp 第二步:查看已经获取到的镜像 [root@ken-node3 ken] ...
- nioServerChannel的的状态
转载自https://blog.csdn.net/zxhoo/article/details/17964353 Channel继承层次图分析上面提到的三个状态的时候,会去看Channel继承层次里某些 ...
- Oracle学习(十三)优化专题
一.查询频繁,数据量大 索引 使用时机:表中经常查询的字段可以考虑添加索引. 联合索引:若能确认多个条件会同时使用时,可以将这几个条件作为联合索引. 单列索引:若条件查询时,这几个条件不是同时用到的话 ...
- Mac鼠标灵敏度调节
系统的调节到最大还是无法满足你的时候那么你就该看看我接下来的操作了,请看: 查看 首先打开终端,输入一下命令: defaults read -g com.apple.mouse.scaling 此命令 ...
- pwnable.kr-cmd1-witeup
执行分析程序,知过滤掉了flag.sh.tmp字段,但在linux下可通过通配符匹配文件哦. 哦对,参数输入的命令中,没有环境变量的支持,所有文件和命令必须用绝对路径哦.
- 总结一下,selenium 自动化流程如下
自动化程序调用Selenium 客户端库函数(比如点击按钮元素) 客户端库会发送Selenium 命令 给浏览器的驱动程序 浏览器驱动程序接收到命令后 ,驱动浏览器去执行命令 浏览器执行命令 浏览器驱 ...
- 消息队列之事务消息,RocketMQ 和 Kafka 是如何做的?
每个时代,都不会亏待会学习的人. 大家好,我是 yes. 今天我们来谈一谈消息队列的事务消息,一说起事务相信大家都不陌生,脑海里蹦出来的就是 ACID. 通常我们理解的事务就是为了一些更新操作要么都成 ...
- Python-列表推导式、生成器、字典推导式
列表推导式 [] + for + if 算子.循环.条件, 对相同的数据进行处理, 算子也可以是函数 number = [i for i in range(1, 101) if i % 2 == 0] ...