STM32F103单片机学习—— 通用定时器
本篇重点记录的是STM32F1的通用定时器。
STM32F103ZE有8个定时器,其中2个高级定时器(TIM1、TIM8),4个通用定时器(TIM2、TIM3、TIM4、TIM5),2个基本定时器(TIM6、TIM7)。下表是对这8个定时器的详细描述。
定时器种类 | 位数 | 计数器模式 | 产生DMA请求 | 捕获/比较通道 | 互补输出 | 特殊应用场景 |
---|---|---|---|---|---|---|
高级定时器 (TIM1,TIM8) |
16 | 向上、向下、向上/下 | 可以 | 4 | 有 | 带死区控制盒紧急刹车, 可应用于PWM电机控制 |
通用定时器 (TIM2~TIM5) |
16 | 向上、向下、向上/下 | 可以 | 4 | 无 | 通用。定时计数,PWM输出, 输入捕获,输出比较 |
基本定时器 (TIM6,TIM7) |
16 | 向上、向下、向上/下 | 可以 | 0 | 无 | 主要应用于驱动DAC |
上表中可看出STM32F103ZE定时器都是16位的,捕获/比较通道有4个,计数模式包括3种(向上计数、向下计数、中央对齐(向上/向下)计数)。
在此对计数模式做一个解释
①向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。
②向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。
③中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。
1、通用计时器概述
通用计数器TIMx(TIM2~TIM5)定时器的特点包括:
- 位于低速的APB1总线上(APB1)
- 16 位向上、向下、向上/向下(中心对齐)计数模式,自动装载计数器(TIMx_CNT)。
- 16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数 为 1~65535 之间的任意数值。
- 4 个独立通道(TIMx_CH1~4),这些通道可以用来作为:
① 输入捕获
② 输出比较
③ PWM 生成(边缘或中间对齐模式)
④ 单脉冲模式输出 - 可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。
- 产生中断/DMA(6个独立的IRQ/DMA请求生成器),该中断产生的事件如下:
① 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
② 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
③ 输入捕获
④ 输出比较
⑤ 支持针对定位的增量(正交)编码器和霍尔传感器电路
⑥ 触发输入作为外部时钟或者按周期的电流管理 - STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。
- 使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源。
通用计时器框图如下:
从图中我们可以看到通用计时器由时钟、时基单元、输入电路、输出电路构成,下面将会对这四块分别做介绍。
2、通用计数器 时钟的选择
上图总结为计数器的时钟有8种选择:
内部RCC提供的时钟:TIMxCLK(CK_INT)
CK_INT(内部时钟)值的计算:
从下图可知如果是APB1的分频系数是1,则通用定时器的时钟=APB1的时钟;否则(APB1的分频系数不是1)通用寄存器的时钟=APB1时钟*2;
如:默认使用SystemInit函数的情况下,SYSCLK=72M,AHB时钟=72M,APB1时钟=36M,APB1的分频系数=AHB时钟APB1时钟=2APB1的分频系数=AHB时钟APB1时钟=2 ,所以通用定时器时钟CK_INT=2*36M=72M。内部触发器输入口1~4(ITR1、ITR2、ITR3、ITR4),用一个定时器作为另一定时器的分频
- 外部捕捉比较引脚,引脚1(TI1FP1或TI1F_ED)、引脚2(TI2FP2)
- 外部引脚:ETR(使能/禁止位、可编程设定极性、4位外部触发过滤器、外部触发分频器[分频器关闭、二分频、四分频、八分频])
计数器时钟可以由下列时钟源提供(该内容意思同上):
内部时钟(CK_INT)
外部时钟模式1:外部输入脚(TIx)
外部时钟模式2:外部触发输入(ETR)
内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。
3、时基单元
从上图中我们可看到定时器的构成:
1)计数寄存器(TIMx_CNT)
该寄存器计数模式为3种,向上计数、向下计数和对齐计数
2)预分频器寄存器(TIMx_PSC)
可将时钟频率按1到65536之间的任意值进行分频,可在运行时改变其设置值
3)自动装载寄存器(TIMx_ARR)
如果TIMx_CR1寄存器中的ARPE位为0,ARR寄存器的内容将直接写入影子寄存器;如果ARPE为1,ARR寄存器的内容将再每次的更新事件UEV发生时,传送到影子寄存器;
如果TIMx_CR1中的UDIS位为0,当计数器产生溢出条件时,产生更新事件;
4)控制寄存器1(TIMx_CR1)
5)DMA中断使能寄存器(TIMx_DIER)
6)定时器中断实现步骤
时基单元为我们提供了定时的功能,我们利用该功能实现如下示例程序的编写:
通过定时器中断配置,实现每500ms中断一次,通过定时中断实现LED灯闪烁。
① 使能定时器时钟。
RCC_APB1PeriphClockCmd();
② 初始化定时器,配置ARR,PSC(即配置自动装载寄存器TIMx_ARR和预分频寄存器值TIMx_PSC)
TIM_TimeBaseInit(TIM_TypeDef* TIMx, IM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
ARR、PSC如何确定
1)我们知道计数器ARR溢出后会产生更新中断,我们以中心对齐模式的时序图来说明,如下图:
![]()
上图中CK_INT前面已说过,其频率由APB1来决定,若使用默认时钟SystemInit初始化的话,CK_INT=72MHz。
CK_CNT如何确定,我们看下图
![]()
CK_INT=APB1或APB1∗2CK_INT=APB1或APB1∗2
上述公式为何计数器ARR和时钟分频PSC都要加1,因为这两个值是配置在寄存器中的,其实从0开始计数,故要加1。
根据上面导出的Tout的公式,结合本小节开头的需求,中断时间设置为500ms,我们可使用默认的系统频率,则Fck_psc=CK_INT=72MHz,则
设PSC=7199,则ARR=4999,该需求的ARR,PSC我们将会以此值去配置。
③ 开启定时器中断,配置NVIC。
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
NVIC_Init();
④ 使能定时器。
TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
⑤ 编写中断服务函数。
TIMx_IRQHandler();
7)程序编写
//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
//定时器TIM3初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx
}
//定时器3中断服务程序
void TIM3_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志
LED1=!LED1;
}
}
//LED1闪烁的周期为500ms,LED0闪烁的周期为200ms,看到的现象为LED1闪烁慢,LED0闪烁快
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
LED_Init(); //LED端口初始化
TIM3_Int_Init(4999,7199);//10Khz的计数频率,计数到5000为500ms
while(1)
{
LED0=!LED0;
delay_ms(200);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
STM32通用定时器在此篇仅记录了 定时器基本的概念和时基单元的功能编程,由于篇幅的限制,通用定时器的输入和输出的功能将再下篇介绍。
STM32F103单片机学习—— 通用定时器的更多相关文章
- STM32学习笔记(五)——通用定时器计数延时
STM32定时器概述 STM32F40x系列总共最多有14个定时器,定时器分为三类:基本定时器.通用定时器和高级定时器.它们的都是通过计数来达到定时的目的,和51的定时器差不多,基本原理都是一样的,就 ...
- STM32通用定时器(转载)
STM32的定时器功能很强大,学习起来也很费劲儿. 其实手册讲的还是挺全面的,只是无奈TIMER的功能太复杂,所以显得手册很难懂,我就是通过这样看手册:while(!SUCCESS){看手册-}才搞明 ...
- STM32F103的11个定时器详解(转)
源:STM32F103的11个定时器详解 STM32F103系列的单片机一共有11个定时器,其中:2个高级定时器4个普通定时器2个基本定时器2个看门狗定时器1个系统嘀嗒定时器 出去看门狗定时器和系统滴 ...
- STM32 通用定时器好文章收藏
https://blog.csdn.net/fengshuiyue/article/details/79150724 单片机入门学习十三 STM32单片机学习十 通用定时器 里面写的挺不错,图文并茂, ...
- STM32定时器学习---基本定时器
STM32F1系列的产品,除了互联网产品外,工作8个,3种定时器,其中一种就是基本定时器.那么STM32单片机的基本定时器如何操作以及编程呢? 下面我们就来详细的了解一下 STM32F1系列的产品,除 ...
- (五)转载:通用定时器PWM输出
1. TIMER输出PWM基本概念 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有 ...
- stm32通用定时器详解
在stm32的开发中我们经常会用到定时器,因此在学习stm32的过程中定时器是必须要学的,而定时主要又分为三大类分别为: 高级控制定时器(TIM1与TIM8) 通用定时器(TIM2~TIM5) 基本定 ...
- STM32(7)——通用定时器PWM输出
1.TIMER输出PWM基本概念 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种 ...
- STM32——通用定时器基本定时功能
STM32——————通用定时器基本定时功能 1. ...
随机推荐
- sql语句insert into where 错误解析
sql语句中,insert into 代表得是插入一条新得数据,全新得数据,所以你这样得写法是错误得,比如: "insert into klkl_Service_shop(name_real ...
- php面试专题---MySQL分表
php面试专题---MySQL分表 一.总结 一句话总结: 分库分表要数据达到一定的量级才用,这样才有效率,不然利不一定大于弊,可能会增加一次I/O消耗 1.分库分表的使用量级是多少? 单表行数超过 ...
- MySQL5.6多实例安装
MySQL-5.6.36.tar.gz多实例安装 查看官方安装说明 more INSTALL-SOURCE 安装cmake及相关依赖包 yum install -y cmake gcc [root@v ...
- java sftp判断目录是否存在
java sftp判断目录是否存在 public boolean isExistDir(String path,ChannelSftp sftp){ boolean isExist=false; tr ...
- redis主从与集群搭建
redis搭建主从 条件:yum安装(3.2.1)与编译安装(5.0.0)都可以 环境:我这里在同一台主机上搭建,当然也可以两台. 1) 复制redis.conf的主配置文件并命令为slave.con ...
- 在windows上使用xdmcp登陆centos,红帽linux
使用xdmcp协议可以方便的在远端登陆linux服务器,进行一些界面的操作. 修改服务器端配置. vi /etc/gdm/custom.conf 找到下面两个标签 [security] AllowRe ...
- win10 文件管理器频繁卡死
参考: https://www.xitmi.com/1589.html
- Spring MVC浅析
讲到MVC,想必大家都很熟悉,就是将数据模型.视图.控制器进行分离,做到分工明确,在Spring的帮助下,Spring MVC 更是做到了充分的解耦,因为大部分的资源都由Spring进行管理,为Spr ...
- 应用安全 - Web安全 - 文件包含攻防
LFI - 无限制本地文件包含 通过目录遍历漏洞可以获取到系统中其他文件的内容 常见的敏感信息路径 Windows系统 c:\boot.ini // 查看系统版本 c:\windows\system3 ...
- php跨域的几种方式
PHP实现跨域的几种形式 1.JSONP(JSON with padding)原理 利用html里面script标签可以加载其他域下的js这一特性,使用script src的形式来获取其他域下的数据, ...