1、STM32Timer简介

STM32中一共有11个定时器,其中2个高级控制定时器,4个普通定时器和2个基本定时器,以及2个看门狗定时器和1个系统嘀嗒定时器。

其中系统嘀嗒定时器是前文中所描述的SysTick,看门狗定时器以后再详细研究。今天主要是研究剩下的8个定时器。

定时器

计数器分辨率

计数器类型

预分频系数

产生DMA请求

捕获/比较通道

互补输出

TIM1

TIM8

16位

向上,向下,向上/向下

1-65536之间的任意数

可以

4

TIM2

TIM3

TIM4

TIM5

16位

向上,向下,向上/向下

1-65536之间的任意数

可以

4

没有

TIM6

TIM7

16位

向上

1-65536之间的任意数

可以

0

没有

2、普通定时器TIM2-TIM5

       其中TIM1和TIM8是能够产生3对PWM互补输出的高级定时器,常用于三相电机的驱动,时钟由APB2的输出产生。TIM2-TIM5是普通定时器,TIM6和TIM7是基本定时器,其时钟由APB1输出产生。今天就从最简单的开始学习起,也就是TIM2-TIM5普通定时器的定时功能。

2.1    时钟来源

计数器时钟可以由下列时钟源提供:

内部时钟(CK_INT)

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

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

内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。

由于今天的学习是最基本的定时功能,所以采用内部时钟。TIM2-TIM5的时钟不是直接来自于APB1,而是来自于输入为APB1的一个倍频器。

这个倍频器的作用是:

当APB1的预分频系数为1时,这个倍频器不起作用,定时器的时钟频率等于APB1的频率;

当APB1的预分频系数为其他数值时(即预分频系数为2、4、8或16),这个倍频器起作用,定时器的时钟频率等于APB1的频率的2倍。

通过倍频器给定时器时钟的好处是:

APB1不但要给TIM2-TIM5提供时钟,还要为其他的外设提供时钟;

设置这个倍频器可以保证在其他外设使用较低时钟频率时,TIM2-TIM5仍然可以得到较高的时钟频率。

2.2    计数器模式

TIM2-TIM5可以由向上计数、向下计数、向上向下双向计数。

向上计数模式中,计数器从0计数到自动加载值(TIMx_ARR计数器内容),然后重新从0开始计数并且产生一个计数器溢出事件。在向下模式中,计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。而中央对齐模式(向上/向下计数)是计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。

2.3    编程步骤
  1. 配置系统时钟;
  2. 配置NVIC;
  3. 配置GPIO;
  4. 配置TIMER;

其中,前3项在前面的笔记中已经给出,在此就不再赘述了。第4项配置TIMER有如下配置:

  1. 利用TIM_DeInit()函数将Timer设置为默认缺省值;
  2. TIM_InternalClockConfig()选择TIMx来设置内部时钟源;
  3. TIM_Perscaler来设置预分频系数;
  4. TIM_ClockDivision来设置时钟分割;
  5. TIM_CounterMode来设置计数器模式;
  6. TIM_Period来设置自动装入的值
  7. TIM_ARRPerloadConfig()来设置是否使用预装载缓冲器
  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)使用的采样频率之间的分频比例。TIM_ClockDivision的参数如下表:

TIM_ClockDivision

描述

二进制值

TIM_CKD_DIV1

tDTS = Tck_tim

0x00

TIM_CKD_DIV2

tDTS = 2 * Tck_tim

0x01

TIM_CKD_DIV4

tDTS = 4 * Tck_tim

0x10

数字滤波器(ETR,TIx)是为了将ETR进来的分频后的信号滤波,保证通过信号频率不超过某个限定。

步骤 7 中需要禁止使用预装载缓冲器。当预装载缓冲器被禁止时,写入自动装入的值(TIMx_ARR)的数值会直接传送到对应的影子寄存器;如果使能预加载寄存器,则写入ARR的数值会在更新事件时,才会从预加载寄存器传送到对应的影子寄存器。

ARM中,有的逻辑寄存器在物理上对应2个寄存器,一个是程序员可以写入或读出的寄存器,称为preload register(预装载寄存器),另一个是程序员看不见的、但在操作中真正起作用的寄存器,称为shadow register(影子寄存器);设计preload register和shadow register的好处是,所有真正需要起作用的寄存器(shadow register)可以在同一个时间(发生更新事件时)被更新为所对应的preload register的内容,这样可以保证多个通道的操作能够准确地同步。如果没有shadow register,或者preload register和shadow register是直通的,即软件更新preload register时,同时更新了shadow register,因为软件不可能在一个相同的时刻同时更新多个寄存器,结果造成多个通道的时序不能同步,如果再加上其它因素(例如中断),多个通道的时序关系有可能是不可预知的。

3、程序源代码

本例实现的是通过TIM2的定时功能,使得LED灯按照1s的时间间隔来闪烁

#include "stm32f10x_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);
} 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); //设置高速AHB时钟(APB2)为HCLK时钟
RCC_PCLK2Config(RCC_HCLK_Div1); //设置低速AHB时钟(APB1)为HCLK的2分频
RCC_PCLK1Config(RCC_HCLK_Div2); //设置FLASH代码延时
FLASH_SetLatency(FLASH_Latency_2); //使能预取指缓存
FLASH_PrefetchBufferCmd(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_GetSYSCLKSource() != 0x08);
} //允许TIM2的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //允许GPIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
} void TIMER_cfg()
{
TIM_TimeBaseInitTypeDef TIM_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_CounterMode = TIM_CounterMode_Up; //设置计数溢出大小,每计2000个数就产生一个更新事件
TIM_TimeBaseStructure.TIM_Period = 2000 - 1; //将配置应用到TIM2中
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); //清除溢出中断标志
TIM_ClearFlag(TIM2, TIM_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; //抢占式中断优先级设置为0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //响应式中断优先级设置为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //使能中断
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_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); } 在stm32f10x_it.c中,我们找到函数TIM2_IRQHandler(),并向其中添加代码 void TIM2_IRQHandler(void) { u8 ReadValue; //检测是否发生溢出更新事件
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);
}
}
}

STM32(5)——通用定时器基本定时器的更多相关文章

  1. STM32 HAL库学习系列第4篇 定时器TIM----- 开始定时器与PWM输出配置

    基本流程: 1.配置定时器 2.开启定时器 3.动态改变pwm输出,改变值  HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); 函数总结: __HAL_TIM ...

  2. STM32之通用定时器

    广大的互联网的大家早上中午晚上..又好..没错了..我又来了..写博客不是定时的..为什么我要提写博客不是定时的呢??聪明的人又猜到我要说什么了吧.有前途.其实我还是第一次听到定时器有通用和高级之分的 ...

  3. [stm32] STM32的通用定时器TIMx系统了解

    通用定时器(TIMx) 一.TIMx简介 二.TIMx主要功能 三.TIMx功能描述 3.1 时基单元 3.2 计数器模式 3.3 时钟选择 3.4 捕获/比较通道 3.5 输入捕获模式 3.6 PW ...

  4. stm32之通用定时器TIM

    STM32系列的CPU,有多达8个定时器: 1.其中TMI1和TIM8是能够产生三对PWM互补输出的高级定时器,常用于三相电机的驱动:它们的时钟有APB2的输出产生: 2.其它6个为普通定时器,时钟由 ...

  5. Stm32之通用定时器复习

    因为毕业设计要用到PWM调光很久都没用到Stm32的定时器,有些内容已经遗忘,为了回顾复习相关内容今天开下通用定时器这一章节的数据手册. 1.时钟 通用定时器一般是TIM2~TIM5,TIM1.TIM ...

  6. 一文打尽PWM协议、PPM协议、PCM协议、SBUS协议、XBUS协议、DSM协议 | STM32的通用定时器TIM3实现PPM信号输出

    PWM.PPM.PCM.SBUS.XBUS.DSM都是接收机与其他设备通信的协议. 请注意这里不要将遥控器和接收机之间的协议混淆.遥控器和接收机之间会采用某种协议来互相沟通,这些协议往往各个厂牌各自有 ...

  7. STM32之系统滴答定时器

    一.SysTick(系统滴答定时器)概述 操作系统需要一个滴答定时器周期性产生中断,以产生系统运行的节拍.在中断服务程序里,基于优先级调度的操作系统会根据进程优先级切换任务,基于时间片轮转系统会根据时 ...

  8. STM32定时器配置(TIM1-TIM8)高级定时器+普通定时器,定时计数模式下总结

    文章结构: ——> 一.定时器基本介绍 ——> 二.普通定时器详细介绍TIM2-TIM5 ——> 三.定时器代码实例 一.定时器基本介绍  之前有用过野火的学习板上面讲解很详细,所以 ...

  9. STM32定时器配置(TIM1、TIM2、TIM3、TIM4、TIM5、TIM8)高级定时器+普通定时器,定时计数模式下总结

    文章结构: ——> 一.定时器基本介绍 ——> 二.普通定时器详细介绍TIM2-TIM5 ——> 三.定时器代码实例 一.定时器基本介绍  之前有用过野火的学习板上面讲解很详细,所以 ...

随机推荐

  1. javascript中简单提示框

    CSS部分 .help-tip{ width: 340px; border:1px solid #A0A0A0; background-color: #F8F8F8; border-radius: 5 ...

  2. Python实例---FTP小程序

    [更多参考] 点击下载

  3. MVC与WebApi中的异常过滤器

    一.MVC的异常过滤器   1.自定义MVC异常过滤器 创建一个类,继承HandleErrorAttribute即可,如果不需要作为特性使用直接实现IExceptionFilter接口即可, 注意,该 ...

  4. 如何恢复在Windows 10中被永久删除的照片?

    照片被误删除了需要恢复?这里推荐一款软件:winutilities.使用WinUtilities文件恢复向导允许您通过简单的点击恢复已删除的照片或从Windows 10回收站中恢复被删除的照片. 恢复 ...

  5. java多态-优化上个实例

    开闭原则:对修改是封闭的,对扩展是开放的,不要违反开闭原则. 可以使用多态解决这个问题.父类的引用变量可以引用子类是对象. 写的越是抽象,越是稳定 public class printerDemo { ...

  6. chrome浏览器Network面板请求Timing分析

    Timing显示资源在整个请求生命周期过程中各部分话费的时间. Queueing 排队的时间花费.可能由于该请求被渲染引擎认为是优先级比较低的资源(图片).服务器不可用.超过浏览器并发请求的最大连接数 ...

  7. Yahoo!团队经验:网站性能优化的34条黄金法则

    英文原文:http://developer.yahoo.com/performance/rules.html 1.尽量减少HTTP请求次数 (1)合并文件就是通过把所有的脚本放到一个文件中来减少HTT ...

  8. 远程执行newLISP代码

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/sheismylife/article/details/26393899 newLISP提供了一个简单 ...

  9. [USACO08JAN]Telephone Lines

    嘟嘟嘟 题意概括一下,就是在无向图上求一条1到n的路径,使路径上第k + 1大的边权尽量小. 考虑dp,令dp[i][j] 表示走到节点 i,路线上有 j 条电话线免费时,路径上最贵的电缆花费最小是多 ...

  10. ethereumjs/ethereumjs-blockchain-2-test

    https://github.com/ethereumjs/ethereumjs-blockchain/tree/master/test 'use strict' const test = requi ...