STM32学习笔记——利用通用定时器TIM2进行精确延时

发布者:SparklingEyes最新更新时间:2015-08-14 来源: eefocus关键字:STM32  通用定时器  TIM2  精确延时 手机看文章 扫描二维码
随时随地手机看文章
1. 通用定时器概述及性能

1.1 概述

在作者所使用的stm32芯片上,共有TIM1 1个高级定时器以及TIM2、TIM3、TIM4共3个通用定时器。其中各通用定时器均由一个通过可编程预分频器驱动的16位自动装载计数器构成。适用于多种场合,包括测量输入信号的脉冲长度(输入采集)或者产生输出波形(输出比较和PWM)。使用定时器预分频器和RCC时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。定时器是完全独立的,而且没有互相共享任何资源。它们可以一起同步操作。

1.2 性能

通用TIMx定时器特性包括:

 

  • 16 位向上,向下,向上/向下自动装载计数器
  • 16 位可编程预分频器,计数器时钟频率的分频系数为1~65535 之间的任意数值
  • 4个独立通道:

 

─ 输入捕获

─ 输出比较

─ PWM生成(边缘或中间对齐模式)

─ 单脉冲模式输出

 

  • 使用外部信号控制定时器和定时器互连的同步电路
  • 如下事件发生时产生中断/DMA:

 

─ 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)

─ 触发事件(计数器启动,停止,初始化或者由内部/外部触发计数)

─ 输入捕获

─ 输出比较

1.3 部分寄存器

由于通用定时器较为复杂,此处仅介绍如何利用TIM2进行精确延时。下面介绍是TIM中与本篇内容有关的寄存器。

1.3.1控制寄存器1(TIMx_CR1)

 

1.3.2 DMA/中断使能寄存器(TIMx_DIER)

 

 

本篇中只关心其第6位及第0位

 

 

由于需要TIM在更新时产生中断,因此这两位都必须置1。

1.3.3 预分频器(TIMx_PSC)

 

 

该分频器对时钟进行分频,并作为计数器时钟。

时钟来源有4种:

1)内部时钟(CK_INT) 

2)外部时钟模式1:外部输入脚(TIx) 

3)外部时钟模式2:外部触发输入(ETR) 

4)内部触发输入(ITRx):使用A定时器作为B定时器的预分频器(A为B提供时钟)。

具体选择可以通过TIMx_SMCR寄存器相关位来设置。[page]

1.3.4 自动重装载寄存器(TIMx_ARR)

 

 

1.3.5 状态寄存器(TIMx_SR)

 

本篇中主要关心该寄存器第0位

 

 

当产生溢出时,该标记位被置1,执行更新事件后由软件清0。

其他众多关于TIM寄存器可查阅《STM32F10x参考手册》

 

1.4基本计数中断过程

按照自己的理解,使能中断及定时器后,根据时钟来源以及预分频器(TIMx_PSC)所设置的分频数开始计数,当计数达到自动重装载寄存器(TIMx_ARR)中所存储的值时,状态寄存器(TIMx_SR)中对应的标志位(第0位)置1,通过软件检查该位则可以更新事件。

例如:系统中APB1(TIM2被挂在APB下)时钟频率为36MHz,设置TIMx_PSC分频为36000,则作为定时器TIM2的时钟频率为36000000/36000=1000Hz,即1秒内内部开关计数1000次,每次1ms,设置TIMx_ARR重装值为1000,则计数达1000次时,TIMx_SR中第0位标志位被置1,此时为延迟1秒。

 

2 TIM固件库函数

2.1 函数TIM_DeInit

函数名

TIM_DeInit

函数原型

void TIM_DeInit(TIM_TypeDef* TIMx)

功能描述

将外设TIMx寄存器重设为缺省值

输入参数

TIMx:x可以是2、3或4,来选择TIM外设

被调用函数

RCC_APB1PeriphClockCmd().

例:重设TIM2

 

[cpp] view plaincopy
 
  1. TIM_DeInit(TIM2);  

 

 

2.2 函数TIM_TimeBaseInit

函数名

TIM_TimeBaseInit

函数原型

void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)

功能描述

根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

输入参数1

TIMx:x可以是2、3或4,来选择TIM外设

输入参数2

TIMTimeBase_InitStruct:指向结构TIM_TimeBaseInitTypeDef的指针,包含了TIMx时间基数单位的配置信息

参阅Section:TIM_TimeBaseInitTypeDef查阅更多该参数允许取值范围.

 

TIM_TimeBaseInitTypeDef structure

TIM_TimeBaseInitTypeDef定义于文件“stm32f10x_tim.h”: 

[cpp] view plaincopy
 
  1. typedef struct   
  2. {   
  3.     u16 TIM_Period;   
  4.     u16 TIM_Prescaler;   
  5.     u8 TIM_ClockDivision;   
  6.     u16 TIM_CounterMode;   
  7. } TIM_TimeBaseInitTypeDef;   

 

TIM_Period 

TIM_Period设置了在下一个更新事件装入活动的自动重装载寄存器周期的值。它的取值必须在0x0000和0xFFFF之间。

TIM_Prescaler 

TIM_Prescaler设置了用来作为TIMx时钟频率除数的预分频值。它的取值必须在0x0000和0xFFFF之间。

TIM_ClockDivision 

TIM_ClockDivision设置了时钟分割。该参数取值见下表。

TIM_ClockDivision

描述

TIM_CKD_DIV1

TDTS = Tck_tim

TIM_CKD_DIV2

TDTS =2 Tck_tim

TIM_CKD_DIV4

TDTS =4 Tck_tim

 

TIM_CounterMode 

TIM_CounterMode选择了计数器模式。该参数取值见下表。

TIM_CounterMode

描述

TIM_CounterMode_Up

TIM向上计数模式

TIM_CounterMode_Down

TIM向下计数模式

TIM_CounterMode_CenterAligned1

TIM中央对齐模式1计数模式

TIM_CounterMode_CenterAligned2

TIM中央对齐模式2计数模式

TIM_CounterMode_CenterAligned3

TIM中央对齐模式3计数模式    

 

例: 

[cpp] view plaincopy
 
  1. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;   
  2. TIM_TimeBaseStructure.TIM_Period = 0xFFFF;   
  3. TIM_TimeBaseStructure.TIM_Prescaler = 0xF;   
  4. TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;   
  5. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
  6. TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);  

 

2.3 函数TIM_ClearFlag

函数名

TIM_ClearFlag

函数原型

void TIM_ClearFlag(TIM_TypeDef* TIMx, u32 TIM_FLAG)

功能描述

清除TIMx的待处理标志位

输入参数1

TIMx:x可以是2,3或者4,来选择TIM外设

输入参数2

TIM_FLAG:待清除的TIM标志位

参阅Section:TIM_FLAG查阅更多该参数允许取值范围

 

TIM_FLAG值

TIM_FLAG

描述

TIME_FLAG_Update

TIM更新标志位

……

……

 

例:

 

[cpp] view plaincopy
 
  1. TIM_ClearFlag(TIM2,TIME_FLAG_Update);  

 

 

2.4 函数TIM_ITConfig

函数名

TIM_ITConfig

函数原型

void TIM_ITConfig(TIM_TypeDef* TIMx, u16 TIM_IT, FunctionalState 

NewState)

功能描述

使能或者失能指定的TIM中断

输入参数1

TIMx:x可以是2,3或者4,来选择TIM外设

输入参数2

TIM_IT:待使能或者失能的TIM中断源

参阅Section:TIM_IT 查阅更多该参数允许取值范围

输入参数3

NewState:TIMx中断的新状态

这个参数可以取:ENABLE或者DISABLE

[page]

TIM_IT值

TIM_FLAG

描述

TIME_FLAG_Update

TIM中断源

……

……

 

例:

 

[cpp] view plaincopy
 
  1. TIM_ITConfig(TIM2,TIME_FLAG_Update,ENABLE);  

 

 

2.5 函数TIM_Cmd

函数名

TIM_Cmd

函数原型

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)

功能描述

使能或者失能TIMx外设

输入参数1

TIMx:x可以是2,3或者4,来选择TIM外设

输入参数2

NewState:TIMx中断的新状态

这个参数可以取:ENABLE或者DISABLE

 

例:

 

[cpp] view plaincopy
 
  1. TIM_Cmd(TIM2,ENABLE);  

 

3 例程程序

本例程主要使用TIM2进行精准延时并亮灭LED灯,其中NVIC部分暂做了解,后面再继续深入。另外,需要注意3.0以后版本的固件库相比2.0版有所更改,如删除旧版NVIC部分函数,或移动至misc.c文件中,通道名TIM2_IRQChannel更改为TIM2_IRQn等。完整构架:

 

 

完整代码:

[cpp] view plaincopy
 
  1. #include "stm32f10x.h"  
  2.     void delay1ms(u32 nTimer);  
  3.     void GPIO_Configuration(void);  
  4.     void TIM2_IRQHandler(void);  
  5.     void Timer2_Configuration(void);  
  6.     void NVIC_Configuration(void);  
[cpp] view plaincopy
 
  1. int main(void)  
  2. {  
  3. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能GPIOC时钟  
  4. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能TIM2时钟  
  5. GPIO_Configuration();  
  6. NVIC_Configuration();//配置中断  
  7. Timer2_Configuration();//配置定时器  
  8.   while(1)  
  9.   {  
  10.     GPIO_ResetBits(GPIOC,GPIO_Pin_7|GPIO_Pin_6);  
  11.     GPIO_SetBits(GPIOC,GPIO_Pin_9|GPIO_Pin_8);  
  12.     delay1ms(1000);  
  13.     GPIO_ResetBits(GPIOC,GPIO_Pin_9|GPIO_Pin_8);  
  14.     GPIO_SetBits(GPIOC,GPIO_Pin_7|GPIO_Pin_6);  
  15.     delay1ms(1000);  
  16.     GPIO_Write(GPIOC,0x0140);  
  17.     delay1ms(2000);  
  18.     GPIO_Write(GPIOC,0x0280);  
  19.     delay1ms(2000);  
  20.    }  
  21. }  
  22.    
  23. void GPIO_Configuration(void)  
  24. {  
  25.   GPIO_InitTypeDef GPIO_InitStructure;  
  26.   GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;  
  27.   GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;  
  28.   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;  
  29.   GPIO_Init(GPIOC,&GPIO_InitStructure);  
  30. }  
  31.    
  32. void Timer2_Configuration(void)  
  33. {  
  34.   TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  
  35.   TIM_DeInit(TIM2);//使用缺省值初始化TIM外设寄存器  
  36.   TIM_TimeBaseStructure.TIM_Period=1;//自动重装载寄存器值为1  
  37.   TIM_TimeBaseStructure.TIM_Prescaler=(36000-1);//时钟预分频数为36000  
  38.   TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;//采样分频倍数1,未明该语句作用。  
  39.   TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//上升模式  
  40.   TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);  
  41.   TIM_ClearFlag(TIM2,TIM_FLAG_Update);//清除更新标志位  
  42.   TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断  
  43.   TIM_Cmd(TIM2,ENABLE);//使能TIM2定时器  
  44. }  
  45.    
  46. void NVIC_Configuration(void)  
  47. {  
  48. NVIC_InitTypeDef NVIC_InitStructure;  
  49. NVIC_SetPriorityGrouping(NVIC_PriorityGroup_0);  
  50. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //3.0版以后的函数库将各通道TIM2_IRQChanel改名TIM2_IRQn  
  51. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
  52. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;   
  53. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  54. NVIC_Init(&NVIC_InitStructure);//NVIC_Init函数被包含在misc.c文件中。  
  55. }  
  56.    
  57. volatile u32 gTimer;  
  58. void TIM2_IRQHandler(void)  
  59. {  
  60.   if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)//检查溢出信号  
  61.   {  
  62.     TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除溢出标志  
  63.     gTimer--;  
  64.   }  
  65. }  
  66.    
  67. void delay1ms(u32 nTimer)  
  68. {  
  69.  gTimer=nTimer;  
  70.  while(gTimer);  
  71. }  

 

 

完成编译并烧录后,开发板上四个LED灯先相邻两两亮灭,亮灭时间延迟1秒,然后交替两两亮灭,亮灭时间延迟2秒。

 

参考文献

[1] Sharkdo.STM32用定时器精确延时的方法  [EB/OL].http://www.cnblogs.com/sharkdo/archive/2011/03/23/1993036.html,2011-03-23/2012-10-14

[2] Cdzlllfe.stm32 通用定时器精确延时程序[EB/OL].

http://blog.sina.com.cn/s/blog_88534dff01010t1a.html,2011-12-17/2012-10-14

[3]福州芯达工作室.《STM32入门系列教程——定时器与蜂鸣器》[EB/OL]. http://ishare.iask.sina.com.cn/f/10918196.html,2010-10-20/2012-10-14.

[4]正点电子.《Stm32不完全手册》[EB/OL]. http://www.amobbs.com/forum.php?mod=viewthread&tid=4517523,2011-01-17/2012-10-15

[5]半壶水,《STM32 菜鸟学习手册-罗嗦版》,http://wenku.baidu.com/view/fc7c7d20ccbff121dd3683da.html, 2012-08-19.

[6] ST.《如何从STM32F10xxx固件库V2.0.3 升级为STM32F10xxx标准外设库V3.0.0》[EB/OL]. http://ishare.iask.sina.com.cn/f/18297257.html?from=like,2011-08-22/2012-09-09.

关键字:STM32  通用定时器  TIM2  精确延时 引用地址:STM32学习笔记——利用通用定时器TIM2进行精确延时

上一篇:STM32学习笔记——使用函数库编程控制GPIO口输出
下一篇:STM32学习笔记——使用SysTick定时器做延时

推荐阅读最新更新时间:2024-03-16 14:28

STM32学习笔记:基础例子
本例子代码参考了STM32库开发实战指南中的代码,由于使用的板子是尚学STM32F103ZET6,为了配合板上已有资源,也参考了其配套代码。为了便于书写文本,我尽量将代码都写到了一个文件中,这种方式是不推荐的,在做具体工程时最好代码分类管理,使工程逻辑清晰。 现在对板上一些资源说明:板上有两个LED灯,引脚为PE5、PE6,均为ResetBits时点亮。有三个按钮,依次为黄色复位,红色PE4(按下接GND)、红色PA0(按下接3.3V,WAKE UP按钮)。ISP口为靠近电源开关的USB,也是USART1口。USART2口为PA3(Rx)、PA2(Tx)。IPD为高电平中断(按键一边接高电平),IPU为低电平中断。 接下来
[单片机]
<font color='red'>STM32</font>学习笔记:基础例子
浅谈STM32的端口输出方式
STM32有两个寄存器可以控制IO输出, 一个是ODR寄存器, 只使用了低16位. 向此寄存器写数据, 就可以控制某个引脚的输出电平. BSRR寄存器是端口位设置/清除寄存器. 此寄存器和ODR寄存器有类似的功能, 都可以来用设置GPIO端口输出.此寄存器分为高16位和低16位, 向高16位的某位写1清除对应ODR寄存器位(输出0), 写0无影响. 向低16位某位写1置位对应ODR寄存器位(输出1), 写0无影响. 可见两个寄存器均可以控制IO输出, 从上文可知写BSRR实际上是可以影响ODR寄存器的值的, 那么使用这两个寄存器控制输出有什么区别呢? 在ST的手册中有这样的说明(RM0090 266页): Each I/O por
[单片机]
STM32的IO外部中断EXTI的使用
一、前言 在之前针对 STM32 的G PI O相关API函数及配置使用进行了详细的介绍,GPIO作为输入引脚时,调用相关读 信号 引脚函数接口就可以在程序的循环中,轮询的对输入信号进行读取 检测 操作,除了轮询的方式访问输入引脚,还可以通过另外一种叫做外部中断的方式来对引脚的输入信号进行检测,本篇首先介绍下EX TI 的结构,接着介绍外部中断的相关概念,对STM32的IO外部中断EXTI有个初步的了解,在此基础上重点围绕IO外部中断EXTI的使用展开分析。 图1 外部中断设计 二、EXTI结构 EXTI(Ex te rnal interrupt/event controller)—外部中断/事件 控制器 ,管理了控制器的
[单片机]
<font color='red'>STM32</font>的IO外部中断EXTI的使用
基于STM32设计的智能家居控制系统(华为云IOT)
1. 功能介绍 随着 物联网 技术的快速发展, 智能家居 控制系统 成为了人们追求便捷、舒适和安全生活的重要组成部分。为了满足用户对 智能 家居的需求,设计了一款基于华为云物联网平台的智能家居控制系统, 硬件 采用了 STM32 和 ESP8266 的组合,实现了设备的上云连接。 传统的家居控制系统存在一些不足,比如需要人工操作、无法实现远程控制等。而我们的智能家居控制系统,通过与华为云物联网平台的连接,可以实现远程控制各种电器开关,并且可以远程收集家里煤气、天然气、烟雾、光照度、温度湿度等信息,为用户提供更加智能化和便捷的家居体验。 智能家居控制系统具有以下主要特点和功能: 远程控制:通过与华为云物联网平台的连接,用户可以
[单片机]
基于<font color='red'>STM32</font>设计的智能家居控制系统(华为云IOT)
stm32串口占用时间、消耗CPU及最大中断时间的深度分析,探寻一种更有效的串口发送方式
1、stm32串口发送占用的时间 答:做嵌入式以来,一直自认为在两个MCU之间的串口通信很占用时间,让我感觉很是不爽。经过一番查找资料后发现并没有我想象的那么糟糕。 串口发送数据: 发送数据在软件层面来看是按照字节来发送的。USARTx- DR = (Data & (uint16_t)0x01FF);CPU只需要把一个字节的数据填充到DR寄存器中就可以了,然后具体的发送过程是由硬件来完成,单字节的发送过程中不消耗CPU。但是为什么我们使用串口来发送连续的数据时为什么还是感觉到这么慢,而且连续发送的过程中CPU不能去做其他任务呢?究其原因是因为我们为保证数据发送的完整性在发送过程中加入了while(USART_GetFlagSt
[单片机]
<font color='red'>stm32</font>串口占用时间、消耗CPU及最大中断时间的深度分析,探寻一种更有效的串口发送方式
stm32指令集合不区分大小写
单片机中接收到奥串口的指令一般为字符串,如果使用strncmp比较是否为我们的指令集中的指令,则不能区分大小写,这里可以使用strcasecmp( )函数和strncasecmp( )函数,来对接收到的字符串指令进行接收比较,并且可以不区分大小写,包含头文件include“stdio.h” 下面对strcasecmp( )函数和strncasecmp( )函数的原型以及应用进行介绍: strcasecmp( )函数说明: strcasecmp()用来比较参数s1和s2字符串,比较时会自动忽略大小写的差异。 返回值 若参数s1和s2字符串相同则返回0。s1长度大于s2长度则返回大于0 的值,s1 长度若小于s2 长度则返回小
[单片机]
STM32系统时钟树分析
下面是一个STM32芯片的时钟树图 1、LSI是低速内部时钟,RC振荡器,频率为32kHz左右。供独立看门狗和自动唤醒单元使用。 2、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。这个主要是RTC的时钟源。 3、HSE是高速外部时钟,课接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~26MHz。我们开发板接的是8M的晶振。HSE也可以直接作为系统时钟或者PLL输入。 4、HSI是高速内部时钟,RC振荡器,频率为16MHz。可以直接作为系统时钟或者用作PLL输入。 5、PLL为锁相环倍频输出。STM32F4有两个PLL: (1)主PLL由HSE或者HSI提供时钟信号,并具有两个不同的输出时钟。 第一个
[单片机]
<font color='red'>STM32</font>系统时钟树分析
STM32速成笔记(3)—按键检测
一、按键 检测 原理 按键检测原理比较简单,按键按下和不按下,其连接引脚的电平是不一样的,按键检测正是通过检测按键引脚的电平变化来实现的。比如按键未按下时引脚电平为高电平,按键按下后为低电平。我们在检测按键时只需要检测按键引脚是否变为低电平来确定按键是否按下。 二、 硬件 连接 按键的硬件连接决定了我们在配置按键IO时IO的状态。以我们使用的普中核心板为例,上面有三个按键 普中核心板按键硬件电路图 其中K1一端接VCC,另一端接单片机。K2和K3一端接地,另一端接单片机。硬件电路不同,导致他们在进行按键检测时IO的配置不同。 针对K1这种按键电路,按键按下时, 单片机 的引脚接到VCC,因此在未按下的情况下该引脚的默认电平
[单片机]
<font color='red'>STM32</font>速成笔记(3)—按键检测
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved