大家好,欢迎来到IT知识分享网。
时基单元
1、什么是定时器
定时器是一种专门负责定时功能的片上外设,而F1系列的单片机最多由14个定时器(TIM1~TIM14)。而STM32F103C8T6一共只有4个定时器。
如上图所示:STM32F103C8T6有一个高级定时器TIM1,3个通用定时器TIM2~4。而高级定时器TIM1挂载在APB2上面。
2、时基单元的基本结构
如图为定时器的基本结构,而时基单元是定时器结构的一部分,如下图所示。
如图:时基单元的基本结构由预分频器PSC,计数器CNT,自动重装寄存器ARR,重复计数器RCR组成。而RCR只有高级定时器才有,通用定时器没有。
PSC (Prescaler): 对速时钟信号 分频 CNT (Counter) :在时钟脉冲激励下 计数 ARR (Auto Reload Register ):用于设置定时周期 RCR (Repetition Counter Register):用于设置定时的 的次 Update事件 - 当RCR溢 时产生 Update中断 - 由Update事件引发的中断
2.1:脉冲的来源
由晶振而来,具体情况可参考时钟树的相关知识。
由上图所示:如果是APB1产生的频率,那么频率 * 2,如果是APB2产生的频率,那么频率 * 1 STM32F103C8T6的定时器来源的频率max = 72MHz。
2.2:预分频器PSC
预分频器由PSC由计数器,比较器和自动重装器构成。
想要分频率的频率脉冲连接计数器,作为输入信号。当计数器从1开始计数,数值和计数周期通过比较器相较,如果计数值 > 计数周期时,比较器输出一个脉冲,计数值归0,重新开始计数。
如上图所示:计数周期为7,输入脉冲输入了8个脉冲,比较器才输出1个脉冲,实现8分频。
如上图:预分频器为16bit,就是计数器为16bit,则它能分频的最大倍数为:2^16 – 1 +1 = 65536 。
2.3:计数器CNT
例如:如果是2bit的计数器,N也为2bit,那么最大分频倍数为2^2 = 4。
没有脉冲来时:计数器为00
第1个脉冲来:计数器为01
第2个脉冲来:计数器为10
第3个脉冲来:计数器为11
第4个脉冲来:计数器变为00,然后向外输出一个脉冲。
2.4:update事件与预加载

如图:在计数的中途改变N的值时,N的值保存在影子寄存器中,然后等待这一次的计数完成后,影子寄存器在将N的值写入shadow里面。
3、本章常见的标准库函数
与时基单元相关的库函数如下:
1.TIM_DeInit(TIM_TypeDef* TIMx);
•功能:该函数用于将指定的定时器 TIMx 恢复为默认状态。通常在重新配置定时器之前使用,以确保定时器处于初始配置。
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
2.TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
•功能:初始化定时器的时基单元。此函数配置定时器的计数频率、计数模式、预分频器等设置。
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•TIM_TimeBaseInitStruct:指向一个 TIM_TimeBaseInitTypeDef 结构体,该结构体定义了定时器的时间基准设置。
•TIM_TimeBaseInitTypeDef结构体:
TIM_Prescaler:预分频器值。
TIM_CounterMode:计数模式,有以下选项:
TIM_CounterMode_Up 向上计数
TIM_CounterMode_Down 向下计数
TIM_CounterMode_CenterAligned1 中心对齐模式1
TIM_Period:定时器的自动重载值。计数器每当达到该值时会重载。
IM_ClockDivision:时钟分割。用于细化定时器的时钟频率。不常用
TIM_RepetitionCounter:仅适用于高级定时器(如 TIM1、TIM8)。控制定时器的重复计数。
TIM_TimeBaseInitTypeDef TIM_BaseStruct; TIM_BaseStruct.TIM_Prescaler = 72 - 1; // 设置预分频器,外部时钟为72 MHz,预分频器设置为 72 TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up; // 设置为升计数模式 TIM_BaseStruct.TIM_Period = 1000 - 1; // 设置定时器周期为1000 TIM_TimeBaseInit(TIM1, &TIM_BaseStruct); // 初始化 TIM1
3.void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
•功能:将TIM_TimeBaseInitTypeDef结构体中的成员变量初始化为默认值
•参数:
•TIM_TimeBaseInitStruct:这是一个指向TIM_TimeBaseInitTypeDef结构体的指针。TIM_TimeBaseInitTypeDef结构体包含了定时器基本定时参数的定义。
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
4.void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
•功能:该函数用于启用或禁用定时器。
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•NewState:ENABLE/DISABLE
5.void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
•功能:该函数用于配置定时器的中断功能。它通过启用或禁用定时器的特定中断,控制定时器事件发生时是否触发中断.
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•TIM_IT:该参数指定要启用或禁用的定时器中断类型。定时器中断种类通常包括:
TIM_IT_Update: 定时器溢出中断(计数器达到最大值后溢出)。
TIM_IT_CC1: 通道 1 捕获比较中断(捕获到上升沿/下降沿产生中断。CCR == CNT时产生中断)
TIM_IT_CC2: 通道 2 捕获比较中断。
TIM_IT_CC3: 通道 3 捕获比较中断。
TIM_IT_CC4: 通道 4 捕获比较中断。
TIM_IT_Trigger: 触发事件中断。
TIM_IT_Break: 中断断开事件。
•NewState:ENABLE/DISABLE。
6.void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);
•功能:该函数用于设置定时器的预分频器值。
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•Prescaler:预分频值,用来设置定时器计数器的时钟频率。
•TIM_PSCReloadMode:预分频器重新加载模式。该参数指定了预分频器值更新的时机。
TIM_PSCReloadMode_Update: 预分频器在计数器更新事件时重新加载。
TIM_PSCReloadMode_Immediate: 预分频器立即重新加载。
// 设置 TIM2 的预分频器为 1000,并且预分频器值立即重新加载 TIM_PrescalerConfig(TIM2, 1000, TIM_PSCReloadMode_Immediate);
7.void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);
•功能:该函数配置定时器的计数模式,可以选择向上计数、向下计数或中心对齐计数模式。
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•TIM_CounterMode:计数器的计数模式。STM32 提供了三种不同的计数模式:
TIM_CounterMode_Up: 向上计数模式。
TIM_CounterMode_Down: 向下计数模式。
TIM_CounterMode_CenterAligned: 中心对齐计数模式,
8.void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
•功能:该函数用于启用或禁用定时器的 ARR 预加载功能。启用时,ARR 寄存器的值将在下一个计数周期时生效,而不是等待计数器溢出事件。
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•NewState:使能或禁用 ARR(自动重装载寄存器)预加载功能。
ENABLE: 启用 ARR 的预加载功能。
DISABLE: 禁用 ARR 的预加载功能。
9.void TIM_CCPreloadControl(TIM_TypeDef* TIMx, FunctionalState NewState);
•功能:用于启用或禁用定时器的 预装载功能。
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•NewState:指定的定时器(例如:TIM1, TIM2 等)。
ENABLE 启用预装载功能。
DISABLE 禁用预装载功能。
10.void TIM_SelectOnePulseMode(TIM_TypeDef* TIMx, uint16_t TIM_OPMode);
•功能:该函数配置定时器为一次脉冲模式。在一次脉冲模式下,定时器将只触发一个脉冲事件。
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•TIM_OPMode: 一次脉冲模式,决定是否启用一次脉冲模式。可以选择:
TIM_OPMode_Single 启用单次脉冲模式。
TIM_OPMode_Repetitive 启用重复脉冲模式。
11.void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);
•功能:该函数设置定时器的计数器初值。定时器的计数器通常从 0 开始
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•Counter:设置定时器的计数器值。
//将TIM2 的计数器设置为 1000 TIM_SetCounter(TIM2, 1000);
12.void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);
•功能:该函数设置定时器的自动重载值。当计数器值达到该值时,定时器将自动重置并重新开始计数。
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•Autoreload:设置自动重载寄存器的值。
//设置 TIM1 的自动重载值为 5000 TIM_SetAutoreload(TIM1,5000);
13.FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)
•功能:该函数用于检查定时器的某个标志位是否已经被设置。返回值指示该标志位的当前状态
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•TIM_FLAG:指定要检查的标志位。可以是以下常见标志之一:
TIM_FLAG_Update:定时器溢出(更新事件)标志。
TIM_FLAG_CC1:通道1捕获比较标志(捕获到上升沿/下降沿置位。CCR == CNT时置位)
TIM_FLAG_CC2:通道2捕获比较标志。
TIM_FLAG_CC3:通道3捕获比较标志
TIM_FLAG_CC4:通道4捕获比较标志
TIM_FLAG_Trigger:触发事件标志。
TIM_FLAG_Break:断开事件标志。
•返回值:
•SET:表示指定的标志位已被设置。
•RESET:表示指定的标志位未被设置。
14.void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)
•功能:该函数用于清除指定的定时器标志位。通常在处理中断服务时使用
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•TIM_FLAG:指定要清除的标志位。可以是以下常见标志之一:
TIM_FLAG_Update:定时器溢出(更新事件)标志。
TIM_FLAG_CC1:通道1捕获比较标志。
TIM_FLAG_CC2:通道2捕获比较标志。
TIM_FLAG_CC3:通道3捕获比较标志
TIM_FLAG_CC4:通道4捕获比较标志
TIM_FLAG_Trigger:触发事件标志。
TIM_FLAG_Break:断开事件标志。
15.ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT)
•功能:该函数用于检查定时器中断标志位的状态,返回该中断是否已经触发。
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•TIM_IT:指定要检查的标志位。可以是以下常见标志之一:
TIM_IT_Update:定时器溢出中断标志。
TIM_IT_CC1:通道1捕获比较中断标志。
TIM_IT_CC2:通道2捕获比较中断标志。
TIM_IT_CC3:通道3捕获比较中断标志。
TIM_IT_CC4:通道4捕获比较中断标志。
TIM_IT_Trigger:触发事件中断标志。
TIM_IT_Break:断开事件中断标志。
•返回值:
•SET:表示指定的中断标志位已被设置(即中断发生)。
•RESET:表示指定的中断标志位未被设置(即中断未发生)。
16.void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
•功能:该函数用于清除定时器的中断挂起位。它通常在中断服务中使用
•参数:
•TIMx:指定的定时器(例如:TIM1, TIM2 等)。
•TIM_IT:指定要检查的标志位。可以是以下常见标志之一:
TIM_IT_Update:定时器溢出中断标志。
TIM_IT_CC1:通道1捕获比较中断标志。
TIM_IT_CC2:通道2捕获比较中断标志。
TIM_IT_CC3:通道3捕获比较中断标志。
TIM_IT_CC4:通道4捕获比较中断标志。
TIM_IT_Trigger:触发事件中断标志。
TIM_IT_Break:断开事件中断标志。
4、通过定时器中断来设置延迟函数
#include "stm32f10x.h" // Device header void Time_Init(void); void LED_Init(void); void Delay_us(uint64_t us); void Delay_ms(uint32_t ms); static uint32_t count = 0; int main(void) {
Time_Init(); LED_Init(); while(1) {
GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET); Delay_ms(1000); GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET); Delay_us(); } } void LED_Init(void) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOC, &GPIO_InitStruct); } /* 定时器的初始化 */ void Time_Init(void) {
//1. 使能挂载定时器TIM3的总线时钟 RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3,ENABLE);//复位 RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3,DISABLE);//复位 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能时钟 //2. 使能ARR寄存器的预加载特性 TIM_ARRPreloadConfig(TIM3,ENABLE);//打开预加载特性 //3. 初始化时基单元,这些都是配置影子寄存器中 TIM_TimeBaseInitTypeDef TIMInitStruct; TIMInitStruct.TIM_Prescaler = 71;//配置预分频器PSC TIMInitStruct.TIM_Period = 999;//配置自动重装寄存器ARR TIMInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//配置计数器为向上计数模式 TIM_TimeBaseInit(TIM3,&TIMInitStruct); //4. 收到启动Update事件,必须手动启动,因为配置好了的定时器参数在影子寄存器中 TIM_GenerateEvent(TIM3,TIM_EventSource_Update); //5. 使能Updata中断 TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//打开Updata触发的中断源 //6. 配置NVIC NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitTypeDef NVICInitStruct; NVICInitStruct.NVIC_IRQChannel = TIM3_IRQn; NVICInitStruct.NVIC_IRQChannelPreemptionPriority = 0; NVICInitStruct.NVIC_IRQChannelSubPriority = 0; NVICInitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVICInitStruct); //7. 使能定时器TIM3 TIM_Cmd(TIM3,ENABLE); } /* 定时器的中断函数,由上面的定时器初始化得,PSC = 71,则分频72倍,72MHz/72 = 1MHz 1MHz代表1s/ = 0.000001s = 1us,所以没间隔1us计数一次。 自动重装器为999,则代表每隔1000 * 1us = 1ms触发一个Update事件,然后产生一个中断。 */ void TIM3_IRQHandler(void) {
//判断中断标准位,是谁产生的中断源 if(TIM_GetFlagStatus(TIM3,TIM_FLAG_Update) == SET)//如果是Update产生的中断源 {
TIM_ClearFlag(TIM3,TIM_FLAG_Update);//清除中断标准位 count++;//代表每隔1ms,count加1。 } } /* 定义一个ms的延迟函数 */ void Delay_ms(uint32_t ms) {
uint64_t time = count + ms; while(count < time); } /* 定义一个us的延迟函数 */ void Delay_us(uint64_t us) {
uint64_t time = count * 1000 + TIM_GetCounter(TIM3) + us;//TIM_GetCounter(TIM3)获取计数器计数的值 while(count * 1000 + TIM_GetCounter(TIM3) < time); }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/117738.html












