STM32F103ZE基本定时器笔记

前言

STM32F103ZET6中包含2个高级控制定时器、4个普通定时器和2个基本定时器,以及2个看门狗定时器和1个系统嘀嗒定时器。
下表比较了高级控制定时器、普通定时器和基本定时器的功能:
在这里插入图片描述

基本定时器

在这里插入图片描述
从上图我们可以看到,基本定时器主要由下面三个寄存器组成。
计数器寄存器 (TIMx_CNT)
预分频器寄存器 (TIMx_PSC)
自动重载寄存器 (TIMx_ARR)

计数器寄存器 (TIMx_CNT)存储的是当前的计数值。
预分频器 (TIMx_PSC)为多少个SK_PSC脉冲计数一次,如下图预分频器的值为1(预分频寄存器默认为0,为不分频),则为两个脉冲计数一次。即为二分频。如果要1000分频,则预分频器的值为1000-1。
在这里插入图片描述
自动重装寄存器 (TIMx_ARR)存储的是计数器的溢出值,例如下图中计数器递增计数到36计数器溢出,触发一次事件。而实际上为37个脉冲触发一次溢出事件(从0开始计数)。
在这里插入图片描述

实践基本定时器

要确定定时的时间我们必须先确定CK_PSC的频率,TIM6配置中选择内部时钟作为时钟源,查看数据手册或者查看代码可以知道TIM6是挂接到APB1时钟线上。
在这里插入图片描述
在这里插入图片描述

STM32之定时器时间计算

1.根据系统时钟进行计算,假设是72Mhz

2.定时器溢出时间=((arr+1)*(psc+1))/Tclk ;
Tclk:定时器的输入时钟频率(单位MHZ)
Tout:定时器溢出时间(单位为us)
.TIM_Period = arr; eg;9999
.TIM_Prescaler = psc; eg:7199

3.定时器溢出时间= ((9999+1)×(7199+1))/72 = 1000000us = 1000ms=1s
在这里插入图片描述

定时器有如下三种计数模式

递增计数模式:计数器从 0 计数到自动重载值,然后重新从 0 开始计数并生成计数器上溢事件。
递减计数模式:计数器从自动重载值开始递减到 0,然后重新从自动重载值开始计数并生成计数器下溢事件。
中心对齐模式:计数器从 0 开始计数到自动重载值 – 1 ,生成计数器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事件。之后从0 开始重新计数。

在NVIC Settings框勾选开启定时器中断。优先级为默认。或者在NVIC配置中使能TIM3中断。
在这里插入图片描述

在KEIL中的配置

现在以1秒灯闪烁为例

1.开启定时器

在使用定时器时,需要在主函数前添加定时器开启函数
在这里插入图片描述

2.在回调函数内写代码
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	//根据前面的配置可知此程序每一秒被调动一次
    if (htim->Instance == htim7.Instance)//判断是否为定时器7的中断
    {
       HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_5);//翻转PE5
    }
}

/* USER CODE END 4 */
定时器初始化
void MX_TIM7_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  //定时器初始化结构体
  htim7.Instance = TIM7;
  //选择定时器7
  htim7.Init.Prescaler = 7200-1;
  //预分频为7200分频,100微秒向上计数一次==1s/(72M/7200)
  htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
  //向上计数
  htim7.Init.Period = 10000-1;
  //自动重装载值
  htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  //不使能自动重装预加载寄存器
  if (HAL_TIM_Base_Init(&htim7) != HAL_OK)//初始化定时器
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  主模式选择。选择具体模式发送到TRG0上
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  主定时器的从模式使能与失能位
  if (HAL_TIMEx_MasterConfigSynchronization(&htim7, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{

  if(tim_baseHandle->Instance==TIM7)
  {
    __HAL_RCC_TIM7_CLK_ENABLE();
	//开启定时器7的时钟
    HAL_NVIC_SetPriority(TIM7_IRQn, 0, 0);
    //响应优先级0,抢占优先级0.(0为最高优先级)
    HAL_NVIC_EnableIRQ(TIM7_IRQn);
    //开启NVIC控制器中TIM7的中断
  }
}
加载与预加载关系

预加载寄存器是自动重装载寄存器的“影子”,也就是预加载寄存器是自动重装载寄存器的缓冲器。但是自动重装载寄存器不是用户用程序可以直接进行操作的,用户需要借助于预加载寄存器(缓冲区)才能访问它。

其目的是为了保证自动重装载寄存器在合适的时候被修改,不允许其随便被修改,否则可能导致在切换的时候发生事与愿违的结果。

简单来说:没有预加载寄存器,这次修改的值,立马会被执行。而有了预加载寄存器,这次修改值会等到这次执行完后,才去执行。

总结
因为定时器的周期都比较短,我们可以通过预加载寄存器配合自动重装载寄存器,来更好的操作定时器,以达到我们期望的效果。

下面的这个解释挺好的

👀使能预装载的意义在于可以多个通道同时输出时,时序能准确地同步。网上的一段有意义的解释是:设计preload register和shadow register的好处是,所有真正需要起作用的寄存器(shadow register)可以在同一个时间(发生更新事件时)被更新为所对应的preload register的内容,这样可以保证多个通道的操作能够准确地同步。如果没有shadow register,或者preload register和shadow register是直通的,即软件更新preload register时,同时更新了shadow register,因为软件不可能在一个相同的时刻同时更新多个寄存器,结果造成多个通道的时序不能同步,如果再加上其它因素(例如中断),多个通道的时序关系有可能是不可预知的。可见如果只是单通道输出,多通道输出时没时序精准的同步更新要求,不使能也可以的。(来源于网友wang27)
————————————————
版权声明:本文为CSDN博主「飞鸟211」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_46015011/article/details/107108739

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要配置STM32F103系列微控制器的基本定时器,您需要遵循以下步骤: 1. 选择要使用的定时器STM32F103系列有3个基本定时器,分别是TIM2、TIM3和TIM4。根据您的需求选择一个可用的定时器。 2. 启用定时器时钟:在RCC寄存器中使能相应定时器的时钟。例如,如果您选择使用TIM2,您需要将APB1总线上的TIM2时钟使能。 3. 配置定时器的工作模式:选择定时器的计数模式。可以选择定时器模式、输入捕获模式或PWM输出模式。 4. 设置定时器的预分频因子:通过设置PSC寄存器来设置定时器的预分频因子,以确定定时器的时钟频率。 5. 设置定时器的自动重装载寄存器(ARR):通过设置ARR寄存器来确定定时器计数器的周期。这将决定定时器溢出时间。 6. 配置相关的中断(可选):如果需要,您可以配置定时器相关的中断,以便在特定事件发生时触发中断。 7. 启动定时器:在CR1寄存器中设置CEN位,启动定时器。 以下是一个使用TIM2配置基本定时器的示例代码片段: ```c #include "stm32f10x.h" void TIM2_Configuration(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period = 9999; // 设置ARR寄存器的值,决定计数器的周期 TIM_TimeBaseStructure.TIM_Prescaler = 7199; // 设置PSC寄存器的值,决定定时器的时钟频率 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_Cmd(TIM2, ENABLE); // 启动定时器 } ``` 请注意,以上代码仅为示例,您需要根据您的具体需求进行适当的修改。 希望对您有所帮助!如果您还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值