ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

YIE002开发探索04-定时器

2021-07-26 22:01:06  阅读:268  来源: 互联网

标签:TIM3 定时器 YIE002 04 中断 TIM 时钟 Prescaler


(请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365)

YIE002开发探索之定时器



定时器的最基本的功能是用来周期性的定时,当然,它还用来实现如下功能:
1) 输入捕获。脉冲计数,在上升沿或下降沿检测,已经PWM的输入检测;
2) 输出比较。脉冲输出和步进电机的控制;
3) PWM生成。电压输出控制、直流减速电机控制等;
4) 编码器接口、霍尔传感器接口等。

当然,根据所用芯片不同,定时器还能提供更多的功能,比如与DMA的配合等。本篇准备用定时器产生的时间中断,周期性地控制LED灯的亮灭,以期对定时器的编程有基本的理解。

1 STM32的定时器

YIE002-STM32所用的芯片为STM32F103C8T6,属于STM32F1系列,在此系列,STM32提供了大量的定时器:2个基本定时器(TIM6、TIM7)、4个通用定时器(TIM2、TIM3、TIM4、TIM5)、2个高级控制定时器(TIM1和TIM8),以及4个特定功能定时器(SysTick、IWDG、WWDG、RTC),共有12个。另外,超大容量系列的产品中,又增加了5个通用寄存器TIM9~TIM14。

从功能上来说,高级控制通用器的功能是通用定时器的超集、通用定时器的功能是基本定时器的超集。比较通用定时器和高级控制定时器,可知它们的功能非常接近,高级控制定时器只是针对电动机的控制增加了一些功能。

因此,本篇准备使用通用定时器TIM3,构建演示程序。

1.1 定时器的时钟

TIM1和TIM8是高级控制定时器,时钟由APB2输出产生;TIM2至于TIM5是通用定时器,TIM6和TIM7是基本定时器,时钟由APB1输出产生。

从前几篇中可以知道,F103C8T6的系统时钟为72MHZ。如图1所示的时钟树,给出了定时器的时钟频率。
时钟树
图1 定时器的时钟树

图1是以STM32F103C8T6为例绘制的。APB1为36MHZ,APB2为72MHZ。在我们的配置中,APB1 Prescaler是2分频;APB2 Prescaler是1分频。从图中可以看出,不论是通过挂在APB1下、还是挂在APB2下的时钟,其时钟都是72MHZ。

也即TIMxCLK均为72MHZ,与系统时钟等同。

1.2 定时器的中断时间(TIM3)

STM32F1的通用定时器(本例中使用的TIM3)是通过可编程预分频器(PSC)驱动的16位自动装载计数器(CNT)构成,其基本的配置过程包括:
1) TIM3时钟使能;
2) 初始化定时器参数,设置自动重装值、分配系数、计数方式等;
3) 允许TIM3更新中断;
4) 设置TIM3的中断优先级;
5) 使能TIM3;
6) 编写中断服务函数。

使用CubeMX编程,上述6个步骤的前5个都是通过图形配置、自动生成代码的,只有中断服务函数需要编写。

编写代码之前,我们需要考虑定时器以多长的时间定时中断。计算中断时间,与TIMx_PSC寄存器(预分频寄存器)和TIMx_ARR寄存器(自动重装载寄存器)有关。具体的细节可以查看《STM32参考手册》,我们主要关注CubeLibrary中如何操作。在stm32f1xx_hal_tim.h中定义了定时器初始化的数据结构:

/** @defgroup TIM_Exported_Types TIM Exported Types
  * @{
  */

/**
  * @brief  TIM Time base Configuration Structure definition
  */
typedef struct
{
  uint32_t Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.
                                   This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */

  uint32_t CounterMode;       /*!< Specifies the counter mode.
                                   This parameter can be a value of @ref TIM_Counter_Mode */

  uint32_t Period;            /*!< Specifies the period value to be loaded into the active
                                   Auto-Reload Register at the next update event.
                                   This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF.  */

  uint32_t ClockDivision;     /*!< Specifies the clock division.
                                   This parameter can be a value of @ref TIM_ClockDivision */

  uint32_t RepetitionCounter;  /*!< Specifies the repetition counter value. Each time the RCR downcounter
                                    reaches zero, an update event is generated and counting restarts
                                    from the RCR value (N).
                                    This means in PWM mode that (N+1) corresponds to:
                                        - the number of PWM periods in edge-aligned mode
                                        - the number of half PWM period in center-aligned mode
                                     GP timers: this parameter must be a number between Min_Data = 0x00 and
                                     Max_Data = 0xFF.
                                     Advanced timers: this parameter must be a number between Min_Data = 0x0000 and
                                     Max_Data = 0xFFFF. */

  uint32_t AutoReloadPreload;  /*!< Specifies the auto-reload preload.
                                   This parameter can be a value of @ref TIM_AutoReloadPreload */
} TIM_Base_InitTypeDef;

数据结构TIM_Base_InitTypeDef的成员变量Prescaler对应预分频寄存器、成员变量Period对应自动重装载寄存器。注意,这两个值可设置的值为[0,65535],注意不要越界。

假设TimClk为定时器时钟频率(单位:MHZ),TimOut为中断时间(也即溢出时间,单位:秒),则计算公式为:

TimOut = ((Prescaler + 1) * (Period + 1)) /TimClk;

TIM3的时钟频率TimClk为72MHZ,如果需要1秒的中断时间,则可以设置

Prescaler=7200-1; 
Period=10000-1;

计算可得TimOut = 1 秒。

常用的几个溢出时间:

Period =9999  Prescaler =7199   1000ms
Period =4999  Prescaler =7199   500ms
Period =2499  Prescaler =7199   250ms
Period =1999  Prescaler =7199   200ms
Period =999   Prescaler =7199   100ms

有了这些基本概念,就可以进入编程步骤了。

2 YIE002-STM32的定时器编程

如之前一样,分为图形配置然后自动生成代码,以及手动编写代码。

2.1 Cube MX的图形配置

本篇的例子,是在03ExtIO上修改的。原来的配置没有修改,主要添加定时器TIM3的配置。如图2所示。
配置TIM3
图2 配置TIM3

在Pinout & Configuration菜单下,选择Timers中的TIM3,将其“Internal Clock”的选项勾选上。同时设置Prescaler值为7200-1,Counter Period值设置为10000-1。

然后设置TIM3中断的优先级,可在System Core的NVIC中设置,如图3所示。

设置TIM3中断优先级
图3 设置TIM3中断优先级

之前设置的外部中断的优先级,可以不必修改,保留即可。

完成设置后,生成代码。

2.2 编写TIM3中断服务函数

定时的中断服务处理函数,在startup_stm32f103xb.s中可以看到。

 EXPORT  TIM1_BRK_IRQHandler        
 EXPORT  TIM1_UP_IRQHandler         
 EXPORT  TIM1_TRG_COM_IRQHandler    
 EXPORT  TIM1_CC_IRQHandler         
 EXPORT  TIM2_IRQHandler            
 EXPORT  TIM3_IRQHandler            
 EXPORT  TIM4_IRQHandler   

我们需要处理的中断函数是TIM3_IRQHandler。跟踪此函数,可以知道,Cube Library提供了回调函数HAL_TIM_PeriodElapsedCallback()供用户处理定时器中断。

因此需要处理的工作包括两项:

一是在初始化函数MX_TIM3_Init()中,添加对TIM3的中断使能函数,代码如下:

/* USER CODE BEGIN TIM3_Init 2 */
	//robin add 20210725
	if(HAL_TIM_Base_Start_IT(&htim3)!=HAL_OK)
	{
		Error_Handler();
	}
 /* USER CODE END TIM3_Init 2 */     

二是添加对回调函数HAL_TIM_PeriodElapsedCallback()的实现,代码如下(添加在USER CODE BEGIN 4中):

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim ==(&htim3))    
        HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_12);
}

编译下载,就可以看到实际效果了。所实现的代码,将以1秒为周期,驱动灯LED1亮灭。


标签:TIM3,定时器,YIE002,04,中断,TIM,时钟,Prescaler
来源: https://blog.csdn.net/luobing4365/article/details/119119080

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有