《2022年STM32学习笔记通用定时器基本定时功能.pdf》由会员分享,可在线阅读,更多相关《2022年STM32学习笔记通用定时器基本定时功能.pdf(10页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、STM32 学习笔记( 4):通用定时器基本定时功能1.STM32 的 Timer 简介STM32 中一共有 11 个定时器,其中2 个高级控制定时器,4 个普通定时器和2 个基本定时器,以及2 个看门狗定时器和1 个系统嘀嗒定时器。其中系统嘀嗒定时器是前文中所描述的SysTick,看门狗定时器以后再详细研究。今天主要是研究剩下的8 个定时器。定时器计数器分辨率计数器类型预分频系数产生 DMA请求捕获/比较通道互补输出TIM1TIM816 位向上,向下,向上/向下1-65536之间的任意数可以4有TIM2TIM3TIM4TIM516 位向上,向下,向上/向下1-65536之间的任意数可以4没有
2、TIM6TIM716 位向上1-65536之间的任意数可以0没有其中 TIM1和 TIM8 是能够产生3 对 PWM 互补输出的高级定时器, 常用于三相电机的驱动, 时钟由 APB2 的输出产生。TIM2-TIM5是普通定时器,TIM6 和 TIM7 是基本定时器,其时钟由APB1 输出产生。 由于 STM32 的 TIMER 功能太复杂了,所以只能一点一点的学习。因此今天就从最简单的开始学习起,也就是TIM2-TIM5普通定时器的定时功能。2.普通定时器 TIM2-TIM52.1 时钟来源计数器时钟可以由下列时钟源提供: 内部时钟 (CK_INT) 外部时钟模式1:外部输入脚 (TIx) 精
3、品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 1 页,共 10 页 - - - - - - - - - - 外部时钟模式2:外部触发输入 (ETR) 内部触发输入 (ITRx) :使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1 而作为另一个定时器Timer2 的预分频器。由于今天的学习是最基本的定时功能,所以采用内部时钟。TIM2-TIM5的时钟不是直接来自于APB1,而是来自于输入为APB1的一个倍频器。这个倍频器的作用是:当 APB1 的预分频系数为1 时,这个倍频器不起作
4、用,定时器的时钟频率等于APB1 的频率;当 APB1 的预分频系数为其他数值时(即预分频系数为2、4、8 或 16),这个倍频器起作用, 定时器的时钟频率等于APB1的频率的 2 倍。APB1 的分频在 STM32_SYSTICK 的学习笔记中有详细描述。通过倍频器给定时器时钟的好处是:APB1 不但要给 TIM2-TIM5提供时钟,还要为其他的外设提供时钟;设置这个倍频器可以保证在其他外设使用较低时钟频率时,TIM2-TIM5仍然可以得到较高的时钟频率。2.2 计数器模式TIM2-TIM5可以由向上计数、向下计数、向上向下双向计数。向上计数模式中,计数器从0 计数到自动加载值 (TIMx_
5、ARR计数器内容 ),然后重新从0开始计数并且产生一个计数器溢出事件。在向下模式中,计数器从自动装入的值(TIMx_ARR) 开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。而中央对齐模式(向上/向下计数)是计数器从 0 开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1 并且产生一个计数器溢出事件;然后再从 0 开始重新计数。2.3 编程步骤1. 配置系统时钟;2. 配置 NVIC ;3. 配置 GPIO;4. 配置 TIMER ;其中,前 3 项在前面的笔记中已经给出,在此就不再赘述了。第4 项配置 TIMER 有如下配置:(1) 利用 TIM
6、_DeInit() 函数将 Timer 设置为默认缺省值;精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 2 页,共 10 页 - - - - - - - - - - (2) TIM_InternalClockConfig() 选择 TIMx 来设置内部时钟源;(3) TIM_Perscaler 来设置预分频系数;(4) TIM_ClockDivision 来设置时钟分割;(5) TIM_CounterMode来设置计数器模式;(6) TIM_Period 来设置自动装入的值(7) TIM_ARRPerl
7、oadConfig() 来设置是否使用预装载缓冲器(8) TIM_ITConfig() 来开启 TIMx 的中断其中(3)-(6)步骤中的参数由TIM_TimerBaseInitTypeDef 结构体给出。步骤(3)中的预分频系数用来确定TIMx 所使用的时钟频率,具体计算方法为:CK_INT/(TIM_Perscaler+1) 。CK_INT 是内部时钟源的频率,是根据2.1 中所描述的APB1 的倍频器送出的时钟,TIM_Perscaler 是用户设定的预分频系数,其值范围是从0 65535。步骤( 4)中的时钟分割定义的是在定时器时钟频率(CK_INT) 与数字滤波器 (ETR,TIx)
8、 使用的采样频率之间的分频比例。TIM_ClockDivision的参数如下表:TIM_ClockDivision描述二进制值TIM_CKD_DIV1tDTS = Tck_tim0 x00TIM_CKD_DIV2tDTS = 2 * Tck_tim0 x01TIM_CKD_DIV4tDTS = 4 * Tck_tim0 x10数字滤波器 (ETR,TIx) 是为了将 ETR 进来的分频后的信号滤波,保证通过信号频率不超过某个限定。步骤( 7)中需要禁止使用预装载缓冲器。当预装载缓冲器被禁止时,写入自动装入的值(TIMx_ARR) 的数值会直接传送到对应的影子寄存器;如果使能预加载寄存器,则写入
9、ARR 的数值会在更新事件时,才会从预加载寄存器传送到对应的影子寄存器。ARM 中,有的逻辑寄存器在物理上对应2 个寄存器,一个是程序员可以写入或读出的寄存器,称为preload register(预装载寄存器 ),另一个是程序员看不见的、但在操作中真正起作用的寄存器,称为 shadow register(影子寄存器 );设计 preload register和 shadow register的好处是,所有真正需要起作用的寄存器(shadow register)可以在同一个时间(发生更新事件时 )被更新为所对应的 preload register的内容, 这样可以保证多个通道的操作能够准确地同
10、步。如果没有 shadow register, 或者 preload register和 shadow 精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 3 页,共 10 页 - - - - - - - - - - register 是直通的,即软件更新preload register 时,同时更新了shadow register,因为软件不可能在一个相同的时刻同时更新多个寄存器,结果造成多个通道的时序不能同步,如果再加上其它因素(例如中断 ),多个通道的时序关系有可能是不可预知的。3.程序源代码本例实现的
11、是通过TIM2 的定时功能,使得LED 灯按照 1s 的时间间隔来闪烁#include stm32f10 x_lib.h void RCC_cfg(); void TIMER_cfg(); void NVIC_cfg(); void GPIO_cfg(); int main() RCC_cfg(); NVIC_cfg(); GPIO_cfg(); TIMER_cfg(); /开启定时器 2 TIM_Cmd(TIM2,ENABLE); while(1); 精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 4
12、页,共 10 页 - - - - - - - - - - void RCC_cfg() /定义错误状态变量ErrorStatus HSEStartUpStatus; /将 RCC 寄存器重新设置为默认值RCC_DeInit(); /打开外部高速时钟晶振RCC_HSEConfig(RCC_HSE_ON); /等待外部高速时钟晶振工作HSEStartUpStatus = RCC_WaitForHSEStartUp(); if(HSEStartUpStatus = SUCCESS) /设置 AHB 时钟(HCLK) 为系统时钟RCC_HCLKConfig(RCC_SYSCLK_Div1); /设置高
13、速 AHB 时钟 (APB2) 为 HCLK 时钟RCC_PCLK2Config(RCC_HCLK_Div1); /设置低速 AHB 时钟 (APB1) 为 HCLK 的 2 分频精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 5 页,共 10 页 - - - - - - - - - - RCC_PCLK1Config(RCC_HCLK_Div2); /设置 FLASH 代码延时FLASH_SetLatency(FLASH_Latency_2); /使能预取指缓存FLASH_PrefetchBufferC
14、md(FLASH_PrefetchBuffer_Enable); /设置 PLL 时钟,为 HSE 的 9 倍频 8MHz * 9 = 72MHz RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); /使能 PLL RCC_PLLCmd(ENABLE); /等待 PLL 准备就绪while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) = RESET); /设置 PLL 为系统时钟源RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /判断 PLL 是否是系统时钟while(RCC_
15、GetSYSCLKSource() != 0 x08); /允许 TIM2 的时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); 精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 6 页,共 10 页 - - - - - - - - - - /允许 GPIO 的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); void TIMER_cfg() TIM_TimeBaseInitTypeDef T
16、IM_TimeBaseStructure; /重新将 Timer 设置为缺省值TIM_DeInit(TIM2); /采用内部时钟给TIM2 提供时钟源TIM_InternalClockConfig(TIM2); /预分频系数为36000-1,这样计数器时钟为72MHz/36000 = 2kHz TIM_TimeBaseStructure.TIM_Prescaler = 36000 - 1; /设置时钟分割TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; /设置计数器模式为向上计数模式TIM_TimeBaseStructure.TIM
17、_CounterMode = TIM_CounterMode_Up; /设置计数溢出大小,每计2000 个数就产生一个更新事件TIM_TimeBaseStructure.TIM_Period = 2000 - 1; /将配置应用到TIM2 中精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 7 页,共 10 页 - - - - - - - - - - TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); /清除溢出中断标志TIM_ClearFlag(TIM2, TIM
18、_FLAG_Update); /禁止 ARR 预装载缓冲器TIM_ARRPreloadConfig(TIM2, DISABLE); /开启 TIM2 的中断TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); void NVIC_cfg() NVIC_InitTypeDef NVIC_InitStructure; /选择中断分组1 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /选择 TIM2 的中断通道NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel; /抢占
19、式中断优先级设置为0 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; /响应式中断优先级设置为0 精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 8 页,共 10 页 - - - - - - - - - - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /使能中断NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NV
20、IC_InitStructure); void GPIO_cfg() GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; /选择引脚 5 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; / 输出频率最大50MHz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; / 带上拉电阻输出GPIO_Init(GPIOB,&GPIO_InitStructure); 在 stm32f10 x_it.c
21、中,我们找到函数TIM2_IRQHandler() ,并向其中添加代码void TIM2_IRQHandler(void) u8 ReadValue; /检测是否发生溢出更新事件精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 9 页,共 10 页 - - - - - - - - - - if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) /清除 TIM2 的中断待处理位TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update); /将 PB.5 管脚输出数值写入ReadValue ReadValue = GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5); if(ReadValue = 0) GPIO_SetBits(GPIOB,GPIO_Pin_5); else GPIO_ResetBits(GPIOB,GPIO_Pin_5); 精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 10 页,共 10 页 - - - - - - - - - -
限制150内