时钟源

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. 首先要搞清楚定时器的计数时钟频率,在预分频系数≠1的时候,TIM2~7的时钟频率为APB1的频率的2倍,即72MHz,预分频系数的默认值不是1。
  2. 定时器的设置主要包括定时器的初始化和中断的初始化。

定时器的时钟不是直接来自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时钟和定时器的更多相关文章

  1. STM32时钟理解

    转载自 http://blog.sina.com.cn/s/blog_6ebd49350100q6xw.html STM32时钟理解 一.硬件上的连接问题 如果使用内部RC振荡器而不使用外部晶振,请按 ...

  2. STM32学习笔记——定时器中断(向原子哥学习)

    定时器中断 STM32 的定时器功能十分强大,有 TIME1 和 TIME8 等高级定时器,也有 TIME2~TIME5 等通用定时器,还有 TIME6 和TIME7 等基本定时器.在本章中,我们将利 ...

  3. Stm32之通用定时器复习

    因为毕业设计要用到PWM调光很久都没用到Stm32的定时器,有些内容已经遗忘,为了回顾复习相关内容今天开下通用定时器这一章节的数据手册. 1.时钟 通用定时器一般是TIM2~TIM5,TIM1.TIM ...

  4. STM32入门系列-STM32时钟系统,STM32时钟树

    时钟对于单片机来说是非常重要的,它为单片机工作提供一个稳定的机器周期从而使系统能够正常运行.时钟系统犹如人的心脏,一旦有问题整个系统就崩溃.我们知道STM32属于高级单片机,其内部有很多的外设,但不是 ...

  5. LibOpenCM3(五) 基础功能: 系统时钟, GPIO, 定时器

    目录 LibOpenCM3(一) Linux下命令行开发环境配置 LibOpenCM3(二) 项目模板 Makefile分析 LibOpenCM3(三) .ld文件(连接器脚本)和startup代码说 ...

  6. stm32时钟配置总结

    stm32时钟配置时钟源: 1,HSE(高速外部时钟)即常见的外接8M晶振方案: 2,HSI(高速内部时钟) 即8M内部振荡时钟方案: 3,LSE(低速外部时钟)即常见的32.768Khz晶振方案: ...

  7. STM32 TIM高级定时器死区时间的计算

    STM32 TIM高级定时器的互补PWM支持插入死区时间,本文将介绍如何计算以及配置正确的死区时间. 文章目录 什么是死区时间? 数据手册的参数 如何计算合理的死区时间? STM32中配置死区时间 什 ...

  8. STM32 TIM1高级定时器RCR重复计数器的理解

    STM32 TIM1高级定时器RCR重复计数器的理解 TIMx_RCR重复计数器寄存器,重复计数器只支持高级定时器TIM1和TIM8,下面看标准外设库的TIM结构体的封装: typedef struc ...

  9. STM32时钟系统的配置寄存器和源码分析

    一.时钟系统 概述 时钟是单片机运行的基础,时钟信号推动单片机内各个部分执行相应的指令,时钟系统就是CPU的脉搏,决定cpu速率. STM32有多个时钟来源的选择,为什么 STM32 要有多个时钟源呢 ...

随机推荐

  1. python 3 for嵌套

  2. softmax交叉熵损失函数求导

    来源:https://www.jianshu.com/p/c02a1fbffad6 简单易懂的softmax交叉熵损失函数求导 来写一个softmax求导的推导过程,不仅可以给自己理清思路,还可以造福 ...

  3. hadoop和hbase高可用模式部署

    记录apache版本的hadoop和hbase的安装,并启用高可用模式. 1. 主机环境 我这里使用的操作系统是centos 6.5,安装在vmware上,共三台. 主机名 IP 操作系统 用户名 安 ...

  4. ASP.NET Web API 2系列(四):基于JWT的token身份认证方案

    1.引言 通过前边的系列教程,我们可以掌握WebAPI的初步运用,但是此时的API接口任何人都可以访问,这显然不是我们想要的,这时就需要控制对它的访问,也就是WebAPI的权限验证.验证方式非常多,本 ...

  5. 基于bellman-ford算法使用队列优化的spfa求最短路O(m),最坏O(n*m)

    acwing851-spfa求最短路 #include<iostream> #include<cstring> #include<algorithm> #inclu ...

  6. 趣图:后端工程师做 UI 的活

      扩展阅读 趣图:苦逼的后端工程师 趣图:前端 VS 后端 [趣图]开发人员腹黑的一面

  7. MyBatis学习(一)初识MyBatis

    一.MyBatis简介 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名 ...

  8. 20190531模拟赛总结&反思

    T1: 来源:Codeforces -  Classroom Watch Describe: 给出一个正整数 n,现在问存在多少个 x,使得  x在十进制下的每一位之和加上 x 等于 n. Solut ...

  9. linux_基础调优

    1. 配置授时服务,使用阿里云的授时服务 echo -e "# update time\n*/5 * * * * /usr/sbin/ntpdate time1.aliyun.com &am ...

  10. 简化ETL工作,编写一个Canal胶水层

    前提 这是一篇憋了很久的文章,一直想写,却又一直忘记了写.整篇文章可能会有点流水账,相对详细地介绍怎么写一个小型的"框架".这个精悍的胶水层已经在生产环境服役超过半年,这里尝试把耦 ...