精华内容
下载资源
问答
  • stm32通用定时器中断

    千次阅读 2019-04-03 22:27:45
    通用定时器主要由以下几个部分组成: ...定时器中断流程如下: (1)选择时钟源,需要操作从模式控制寄存器TIMx_SMCR的低3位,默认为000,预分频器直接由内部时钟驱动。 (2)设置预分频寄存器TIMx_PSC ...

    通用定时器主要由以下几个部分组成:
    图1

    (1)时基单元
    主要包括:计数器寄存器、预分频寄存器和自动装载寄存器
    (2)时钟发生器:产生时钟源
    (3)输入捕获通道
    (4)输出通道
    其中定时器中断只涉及了(1)(2)两个部分:
    图2

    定时器中断流程如下:
    (1)选择时钟源,需要操作从模式控制寄存器TIMx_SMCR的低3位,默认为000,预分频器直接由内部时钟驱动。
    图3

    (2)设置预分频寄存器TIMx_PSC
    图4
    默认调用SystemInit函数情况下:
    SYSCLK=72M
    AHB时钟=72M
    APB1时钟=36M
    所以APB1的分频系数=AHB/APB1时钟=2
    所以,通用定时器时钟CK_INT=2*36M=72M
    当设置CK_PSC+1为1,则CK_CNT和CK_INT一致,如图2波形图所示。

    (3)设置控制寄存器TIMx_CR1、重装载寄存器TIMx_ARR以及中断使能寄存器TIMx_DIER等,选择计数模式,计数周期等。以向上计数模式为例,当计数寄存器计数到达设定值时,就会产生溢出,就会有更新事件和更新中断标志,如果使能中断,就会执行中断程序。

    溢出时间计算:Tout(溢出时间)=(ARR+1)(PSC+1)/Tclk
    (ARR+1)计数次数*((PSC+1)/Tclk)单次计数时间
    当采用系统初始化时,APB1时钟为36M,倍频后通用定时器时钟72M,即Tclk为72M,设置PSC为7199,则得到cnk的计数频率为72M/7200=10K,单次计数时间为0.1ms,再设置ARR为4999,则溢出时间为500ms,也就是每500ms产生一次溢出。

    结合代码具体实现通用定时器中断:(以默认内部时钟和通用定时器3为例)
    (1)使能定时器时钟

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    

    (2)初始化定时器,配置ARR,PSC

    TIM_TimeBaseInitTypeDef tis;
    tis.TIM_Period=arr;//设置在下一个更新事件装入活动的自动重装载寄存器周期的值 
     tis.TIM_Prescaler=psc;//设置用来作为TIMx时钟频率除数的预分频值
     tis.TIM_ClockDivision=TIM_CKD_DIV1; //设置时钟分割
     tis.TIM_CounterMode=TIM_CounterMode_Up;  //TIM向上计数模式
     TIM_TimeBaseInit(TIM3,&tis);//根据指定的参数初始化TIMx的时间基数单位
    

    (3)开启定时器中断,并配置NVIC,一般在主函数进行中断分组
    中断分组

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    

    配置中断

     NVIC_InitTypeDef nvics;
     TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,使能更新中断
     nvics.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
     nvics.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
     nvics.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
     nvics.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
     NVIC_Init(&nvics);  //初始化NVIC寄存器
    

    (4)使能定时器

    TIM_Cmd(TIM3, ENABLE);  //使能TIMx 
    

    (5)编写中断服务函数

    void TIM3_IRQHandler(void)   //TIM3中断
    {
     if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
      {
      TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志 
      xxxx//执行的动作
      }
    }
    
    展开全文
  • 定时器中断

    2016-01-28 15:15:00
    2、定时器定时,可达到精确延时。本文分析s3c2440的定时器使用方法。  系统时钟  首先,应先了解s3c2440的时钟系统。MCU的主时钟源主要是外部晶振或外部时钟,目前用的最多的是外部晶振。MINI2440开发板使用一个...

      在程序中,需要延时的时候,通常状况下有两种方法:1、循环语句实现,这种方法简单易用,但是无法得到一个精确的延时时间;2、定时器定时,可达到精确延时。本文分析s3c2440的定时器使用方法。

      系统时钟

      首先,应先了解s3c2440的时钟系统。MCU的主时钟源主要是外部晶振或外部时钟,目前用的最多的是外部晶振。MINI2440开发板使用一个12MHz的外部晶振,如果CPU只工作在12MHz频率下,开发板的使用效率非常低,所有依赖系统时钟工作的硬件,其工作效率也非常低,如果想提高CPU的工作效率,则需要对输入时钟进行一系列处理,其流程如下:

      晶振频率通过PLL(锁相环)进行倍频处理。s3c2440有两个PLL,分别是UPLL和MPLL。UPLL专用于USB模块,提供48MHz,MPLL提供FCLK、HCLK和PCLK。FCLK是主频时钟,用于ARM920T内核;HCLK用于AHB总线设备,如内存控制、中断控制、LCD控制、DMA以及USB主模块;PCLK用于APB总线设备,如外围设备的看门狗,IIS,I2C,PWM,MMC接口,ADC,UART,GPIO,RTC以及SPI。

      s3c2440支持FCLK、HCLK和PCLK之间的分频比例选择,该比例由CLKDIVN寄存器中的HDIVN和PDIVN来决定。因此,我们只需确定FCLK,即可通过设定HDIVN和PDIVN来确定HCLK和PCLK。

      FCLK与输入时钟Fin之间的倍数关系(即晶振频率通过PLL倍频)是通过MPLLCON寄存器(如图1所示)来设置的,MPLLCON寄存器中包含3个参数:MDIV、PDIV、SDIV,公式如下: 

      MPLL(FCLK) = (2*m*Fin) / (p*2^s)

        其中:m = MDIV + 8  , p = PDIV + 2  ,s = SDIV

    图1 MPLLCON寄存器

       总结一下,时钟产生流程为:外部时钟源→通过寄存器MPLLCON得到FCLK→再通过寄存器CLKDIVN得到HCLK和PCLK。

      定时器

      s3c2440有5个16-bit的定时器,定时器0、1、2、3具有PWM功能;定时器4只有一个内部定时而没有关联到输出管脚上;同时,定时器0有一个dead-zeno产生器,用于大电流设备。

      定时器的输入时钟频率信号跟预分频器(prescaler)和分频器(divider)相关。如图2所示。

      预分频器:定时器0和1共享一个8-bit预分频器,定时器2、3、4共享另一个8-bit预分频器,预分频器数值由TCFG0配置,取值范围是0~255。

      分频器:同时,每一个定时器都分别有一个时钟分频器,这样就可以产生5个不同的分频信号,分频器数值由TCFG1配置,取值只能是2、4、8、16,或者外部TCLKn。

      图2 定时器输入时钟框图

      具体公式为:  

      定时器输入时钟频率=PCLK ÷ (prescaler+1) ÷ divider

      比如,已知PCLK=50MHz,我们希望某一个定时器的输入时钟频率为25KHz,那么我们就需要配置prescaler=249,divider=8,则递减计数器每减一次1,时间就过去0.04ms(1÷25000×1000)。

      TCONn为定时器控制寄存器,控制定时器的开启与关闭。

      定时计数缓冲寄存器TCNTBn用于存储定时器的初始值,当定时器启动时,TCNTBn里的数值会被加载到递减计数器TCNTn中。

      定时比较缓冲寄存器TCMPBn用于存储定时器的比较值,TCMPBn的数值会被加载到比较寄存器TCMPn里来跟递减计数器进行比较。

      工作原理为:

      (1)将定时器的初始值和比较值装入寄存器TCNTBn和TCMPBn中。

      (2)设置定时器控制寄存器TCON,启动定时器。此时,TCMPBn和TCNTBn中的值会加载到寄存器TCMPn和TCNTn中。

      (3)定时器会减1计数,即TCNTn进行减1计数,当TCMPn=TCNTn时,TOUTn引脚输出取反。

      在通常应用中,TCMPBn的值用于PWM,当递减计数器和比较计数器数值相等时,电平会翻转,从而达到改变占空比的目的。如果仅仅是用于定时中断,那么将TCMPBn设置为0,则当递减计数器达到0时,定时器中断请求通知CPU定时器操作已经完成。当定时器计数器到达零时, 相应的 TCNTBn的值将自动被加载到递减计数器以继续下一次操作。然而,如果定时器停止了,例如,在定时器运行模式期间清除TCONn的定时器使能位, TCNTBn的值将不会被重新加载到计数器中。

      s3c2440的定时器有一个双缓冲功能,保证下次定时器操作时重加载的值改变时无需停止当前的定时器操作。所以新的定时器的值设定,当前的定时器操作也可以成功完成。定时器的值可以写到TCNTBn中,定时器的当前计数值可以从TCNTOn中读到。TCNTBn被读取的值,不表明计数器的当前状态,而是下一次定时器持续期间的重加载值。当TCNTn为0,自动重加载操作会复制TCNTBn到TCNTn中。但是,如果TCNTn为0,而自动重加载的使能位为0,那么TCNTn不会再操作了。

      配置完定时器相关内容,接下来是配置中断,如设置中断模式(IRQ或FIQ),将定时器执行函数对应定时中断入口地址等等,这里不多加赘述。

    转载于:https://www.cnblogs.com/may1016/p/5163774.html

    展开全文
  • 定时器中断实验

    2021-09-11 14:14:00
    通用定时器运行:通用定时器运行: 时钟选择: 计数器时钟可以由下列时钟源提供: 内部时钟(CK_INT) 外部时钟模式1:外部输入脚(TIx) 外部时钟模式2:外部触发输入(ETR) 内部触发输入(ITRx):使用一个定时器...

    一、概述:

    通用定时器运行图:通用定时器运行图:

    file

    时钟选择:

    计数器时钟可以由下列时钟源提供:
    内部时钟(CK_INT)
    外部时钟模式1:外部输入脚(TIx)
    外部时钟模式2:外部触发输入(ETR)
    内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。

    内部时钟选择:

    file

    时钟计算方法:

    file

    除非APB1的分频系数是1,否则通用定时器TIM2-7的时钟等于APB1时钟的2倍。

    默认调用SystemInit函数情况下:
    SYSCLK=72M
    AHB时钟=72M
    APB1时钟=36M
    所以APB1的分频系数=AHB/APB1时钟=2
    所以,通用定时器时钟CK_INT=2*36M=72M

    二、定时器中断实验相关寄存器:

    寄存器:

    • 计数器当前值寄存器CNT

      file

    • 预分频寄存器TIMx_PSC

      file

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

      file

    • 控制寄存器1(TIMx_CR1):(用到位4和位0)

      file

    • DMA中断使能寄存器(TIMx_DIER)

      file

    库函数:

    • 定时器参数初始化:
           void TIM_TimeBaseInit(TIM_TypeDef* TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);COPY
    typedef struct
    {
      uint16_t TIM_Prescaler;       
      uint16_t TIM_CounterMode;    
      uint16_t TIM_Period;  
    
      //高级TIM才使用以下两种     
      uint16_t TIM_ClockDivision; 
      uint8_t TIM_RepetitionCounter;
    } TIM_TimeBaseInitTypeDef;
    COPY
    TIM_TimeBaseStructure.TIM_Period = 4999; 
    TIM_TimeBaseStructure.TIM_Prescaler =7199; 
    TIM_TimeBaseStructure.TIM_ClockDivision =   TIM_CKD_DIV1; 
    TIM_TimeBaseStructure.TIM_CounterMode =   TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);COPY
    • 定时器使能函数:

      void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)COPY
    • 定时器中断使能函数:

      
      void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);COPY
    
    - 状态标志位获取和清除
    ```c
    FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
    void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
    ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
    void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

    三、定时器中断实现步骤:

    1,能定时器时钟。
    RCC_APB1PeriphClockCmd();
    2, 初始化定时器,配置ARR,PSC。
    TIM_TimeBaseInit();
    3,开启定时器中断,配置NVIC。
    void TIM_ITConfig();
    NVIC_Init();
    4, 使能定时器。
    TIM_Cmd();
    5, 编写中断服务函数。
    TIMx_IRQHandler();

    实验程序要求:

    通过定时器中断配置,每500ms中断一次,然后中断服务函数中控制LED实现LED1状态取反(闪烁)。
    Tout(溢出时间)=(ARR+1)(PSC+1)/Tclk
    Tclk=APB1时钟倍频 PCS=预分频系数
    再由所需Tout来计算出ARR系数

    手写代码:

    建立timer.c文件,编译后,编写timer.h:

    #ifndef __TIMER_H
    #define __TIMER_H
    #include "sys.h"
    
    //初始化定时器函数:需配置ARR和PSC,实验将其作为入口参数
    void TIM3_Int_Init(u16 arr,u16 psc);//TIM3
    
    #endif
    COPY

    编写timer.c:

    #include "timer.h"
    #include "led.h"
    
    void TIM3_Int_Init(u16 arr,u16 psc)
    {
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能TIM3时钟
    
        TimeBaseInitTypeDef TimeBaseInitStrue;
        //调用时钟初始化函数(FWLIB的定时器头文件中)
              //定时器TIM3初始化
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值   
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        //第一个参数为TIMx,第二个为结构体指针类型
        TIM_TimeBaseInit(TIM3,&TimeBaseInitStrue);
    
        //使能指定的TIM3中断,允许更新中断
        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); 
    
        NVIC_InitTypeDef NVIC_InitStructure;
            //中断优先级NVIC设置
        NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
        NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
    
        TIM_Cmd(TIM3, ENABLE);  //使能TIMx    
    }
    
    //定时器3中断服务程序
    void TIM3_IRQHandler(void)   //TIM3中断
    {
        if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
            {
            TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志 
            LED1=!LED1;
            }
    }
    COPY

    编写mian.c:

    #include "led.h"
    #include "delay.h"
    #include "key.h"
    #include "sys.h"
    #include "usart.h"
    #include "timer.h"
    
     int main(void)
     {      
    
        delay_init();            //延时函数初始化    
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
        uart_init(115200);   //串口初始化为115200
        LED_Init();              //LED端口初始化
        TIM3_Int_Init(4999,7199);//10Khz的计数频率,计数到5000为500ms  
        while(1)
        {
            LED0=!LED0;
            delay_ms(200);         
        }    
    
    }    
    COPY

    (led灯代码不做提供)

    实验现象:

    LED0以200ms翻转
    LED1以500ms翻转

    本文转载自:定时器中断实验 – 布尔博客

    欢迎关注技术公众号,获取更多硬件学习干货!

     

    我们能为你提供什么?

    技术辅导:C++、Java、嵌入式软件/硬件

    项目辅导:软件/硬件项目、大厂实训项目

    就业辅导:就业全流程辅导、技术创业支持

    对接企业HR:培养输送优质性人才

     

    展开全文
  • 《STM32中文参考手册V10》-第14章通用定时器   STM32的定时器 STM32F103ZET6一共有8个定时器,其中分别为: 高级定时器(TIM1、TIM8);通用定时器(TIM2、TIM3、TIM4、TIM5);基本定时器(TIM6、TIM7)。 ...

    STM32F1xx官方资料:

    《STM32中文参考手册V10》-第14章通用定时器

     

    STM32的定时器

    STM32F103ZET6一共有8个定时器,其中分别为:

    高级定时器(TIM1、TIM8);通用定时器(TIM2、TIM3、TIM4、TIM5);基本定时器(TIM6、TIM7)。

    他们之间的区别情况见下表:

    STM32定时器的区别
    定时器种类位数计数器模式发出DMA请求捕获/比较通道个数互补输出特殊应用场景
    高级定时器16向上、向下、向上/下可以4

    带死区控制盒紧急刹车,可应用于PW

    M电机控制

    通用定时器16向上、向下、向上/下可以4

    通用。定时计数,PWM输出,输入捕获

    ,输出比较

    基本定时器16向上、向下、向上/下可以0主要应用于驱动DAC

     

    STM32的通用定时器

     

    通用定时器功能特点描述

    STM32的通用定时器是由一个可编程预分频器(PSC)驱动的16位自动重装载计数器(CNT)构成,可用于测量输入脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)等。

    STM3 的通用TIMx(TIM2、TIM3、TIM4 和 TIM5)定时器功能特点包括:

    • 位于低速的APB1总线上(注意:高级定时器是在高速的APB2总线上)
    • 16位向上、向下、向上/向下(中心对齐)计数模式,自动装载计数器(TIMx_CNT);
    • 16位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数 为 1~65535 之间的任意数值;
    • 4 个独立通道(TIMx_CH1~4),这些通道可以用来作为:
    1. 输入捕获
    2. 输出比较
    3. PWM生成(边缘或中间对齐模式)
    4. 单脉冲模式输出 
    • 可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。
    • 如下事件发生时产生中断/DMA(6个独立的IRQ/DMA请求生成器): 
    1. 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发) 
    2. 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
    3. 输入捕获 
    4. 输出比较 
    5. 支持针对定位的增量(正交)编码器和霍尔传感器电路 
    6. 触发输入作为外部时钟或者按周期的电流管理

    STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。   

    使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源。

    计数器模式

    通用定时器可以向上计数、向下计数、向上向下双向计数模式。

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

    简单地理解三种计数模式,可以通过下面的图形:

     

    通用定时器工作流程

    对于这个定时器框图,分成四部分来讲:最顶上的一部分(计数时钟的选择)、中间部分(时基单元)、左下部分(输入捕获)、右下部分(PWM输出)。这里主要介绍一下前两个,后两者的内容会在后面的文章中讲解到。

    计数时钟的选择

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

    • 内部时钟(TIMx_CLK) 
    • 外部时钟模式1:外部捕捉比较引脚(TIx)
    • 外部时钟模式2:外部引脚输入(TIMx_ETR)
    • 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。

    内部时钟源

    从图中可以看出:由AHB时钟经过APB1预分频系数转至APB1时钟,再通过某个规定转至TIMxCLK时钟(即内部时钟CK_INT、CK_PSC)。最终经过PSC预分频系数转至CK_CNT。

    那么APB1时钟怎么转至TIMxCLK时钟呢?除非APB1的分频系数是1,否则通用定时器的时钟等于APB1时钟的2倍。

    例如:默认调用SystemInit函数情况下:SYSCLK=72M、AHB时钟=72M、APB1时钟=36M,所以APB1的分频系数=AHB/APB1时钟=2。所以,通用定时器时钟CK_INT=2*36M=72M。最终经过PSC预分频系数转至CK_CNT。

    时基单元

    时基单元包含:计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)、自动装载寄存器(TIMx_ARR)三部分。

    对不同的预分频系数,计数器的时序图为:

    计数模式

    此时,再来结合时钟的时序图和时基单元,分析一下各个计数模式:

    向上计数模式

    向下计数模式

    中央对齐模式

     

    通用定时器相关配置寄存器

    计数器当前值寄存器(TIMx_CNT)

    作用:存放计数器的当前值。

    预分频寄存器(TIMx_PSC)

    作用:对CK_PSC进行预分频。此时需要注意:CK_CNT计算的时候,预分频系数要+1

    自动重装载寄存器(TIMx_ARR)

    作用:包含将要被传送至实际的自动重装载寄存器的数值。

    注意:该寄存器在物理上实际上对应着2个寄存器。一个是我们直接操作的,另一个是我们看不到的,这个看不到的寄存器叫做影子寄存器。实际上真正起作用的是影子寄存器。根据TIMx_CR1位的APRE位的设置,APRE=0时,预装载寄存器的内容就可以随时传送到影子寄存器,此时两者是互通的;APRE=1时,在每一次更新事件时,才将预装在寄存器的内容传送至影子寄存器。

    控制寄存器(TIMx_CR1)

    作用:对计数器的计数方式、使能位等进行设置。

    这里有ARPE位:自动重装载预装载允许位。ARPE=0时,TIMx_ARR寄存器没有缓冲;ARPE=1时,TIMx_ARR寄存器被装入缓冲器。

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

    作用:对DMA/中断使能进行配置。

     

    通用定时器超时时间

    超出(溢出)时间计算:

    Tout=(ARR+1)(PSC+1)/TIMxCLK

    其中:Tout的单位为us,TIMxCLK的单位为MHz。

    这里需要注意的是:PSC预分频系数需要加1,同时自动重加载值也需要加1。

    • 为什么自动重加载值需要加1,因为从ARR到0之间的数字是ARR+1个;
    • 为什么预分频系数需要加1,因为为了避免预分频系数不设置的时候取0的情况,使之从1开始。

    这里需要和之前的预分频进行区分:由于通用定时器的预分频系数为1~65535之间的任意数值,为了从1开始,所以当预分频系数寄存器为0的时候,代表的预分频系数为1。而之前的那些预分频系数都是固定的几个值,比如1、4、8、16、32、64等等,而且可能0x000代表1,0x001代表4,0x010代表8等等。也就是说,一边是随意的定义(要从1开始),另一边是宏定义了某些值(只有特定的一些值)。

    比如,想要设置超出时间为500ms,并配置中断,TIMxCLK按照系统默认初始化来(即72MHz),PSC取7199,由此可以计算出ARR为4999。

    也就是说,在内部时钟TIMxCLK为72MHz,预分频系数为7199的时候,从4999递减至0的事件是500ms。

     

    通用定时器相关配置库函数

    • 1个初始化函数
    void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

    作用:用于对预分频系数、计数方式、自动重装载计数值、时钟分频因子等参数的设置。

    • 2个使能函数
    void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
    void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);

    作用:前者使能定时器,后者使能定时器中断。

    • 4个状态标志位获取函数
    FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
    void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
    ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
    void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

    作用:前两者获取(或清除)状态标志位,后两者为获取(或清除)中断状态标志位。

     

    定时器中断的一般步骤

    实例要求:通过TIM3的中断来控制DS1的亮灭,DS1是直接连接在PE5上的。

    • 使能定时器时钟。调用函数:RCC_APB1PeriphClockCmd();
    • 初始化定时器,配置ARR、PSC。调用函数:TIM_TimeBaseInit();
    • 开启定时器中断,配置NVIC。调用函数:void TIM_ITConfig();NVIC_Init();
    • 使能定时器。调用函数:TIM_Cmd();
    • 编写中断服务函数。调用函数:TIMx_IRQHandler()。

    下面按照这个一般步骤来进行一个简单的定时器中断程序:

    //通用定时器3中断初始化
    //这里时钟选择为APB1的2倍,而APB1为36M
    //arr:自动重装值。
    //psc:时钟预分频数
    //这里使用的是定时器3!
    void TIM3_Int_Init(u16 arr,u16 psc)
    {
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
    	
    	//定时器TIM3初始化
    	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
    	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
    	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
     
    	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
    
    	//中断优先级NVIC设置
    	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
    
    
    	TIM_Cmd(TIM3, ENABLE);  //使能TIMx					 
    }
    //定时器3中断服务程序
    void TIM3_IRQHandler(void)   //TIM3中断
    {
    	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
    		{
    		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志 
    		LED1=!LED1;
    		}
    }
     int main(void)
     {		
     
    	delay_init();	    	 //延时函数初始化	  
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
     	LED_Init();			     //LED端口初始化
    	TIM3_Int_Init(4999,7199);//10Khz的计数频率,计数到5000为500ms  
       	while(1)
    	{
    		LED0=!LED0;
    		delay_ms(200);		   
    	}	 
    
    
    }	 

    定时器中断的程序和串口中断的程序非常类似,可以将两者结合起来进行比对着学习【STM32】串口相关配置寄存器、库函数(UART一般步骤) 

    同时强调一下,在中断处理函数内,需要判断中断来源和及时清除中断标志位。

     

    展开全文
  • 通用定时器中断实验 定时器中断时钟源解析 教你如何看逻辑信号 向上计数模式(时钟分频因子=1) 中央对齐计数模式(时钟分频因子=1,ARR=6) 相关寄存器简介 事件产生寄存器(TIMx_EGR) 状态寄存器(TIMx_SR)...
  • (注:文中的x为数字) 初始化 ...在设定预分频器的值之前,先理解这里的预分频器与时钟系统里的APB1外设的PPRE1不同(由于原子的SYSTEM中时钟初始化函数将PPRE1设为非1,所以外设定时器的时钟就...
  • stm32通用定时器中断实现步骤

    千次阅读 2019-05-09 20:34:05
    1.使能定时器时钟 RCC_APB1PeriphClockCmd();//注意通用定时器挂在哪条总线...3.开启定时器中断,配置NVIC void TIM_ITConfig(); NVIC_Init(); 4.使能定时器 TIM_Cmd(); 5.编写中断服务函数 TIMx_IRQHand...
  • 51定时器中断控制流水灯

    千次阅读 2021-01-01 15:34:11
    2、了解定时器中断的方法。 3、了解定时器初始化设置的方法。 二、实验内容 1、完成读取定时器溢出标志位来控制流水灯 2、完成定时器中断服务函数控制流水灯 三、实验原理 只用一个定时器: 定时器级联: 四、实验...
  • 定时器中断实现步骤及实例笔记

    千次阅读 2019-07-20 18:01:06
    定时器中断实现步骤 使能定时器时钟。 RCC_APB1PeriphClockCmd(); 初始化定时器,配置ARR,PSC。 TIM_TimeBaseInit(); 开启定时器中断,配置NVIC。 void TIM_ITConfig(); NVIC_Init(); 使能定时器。 TIM_Cmd...
  • ZYNQ 定时器中断函数

    2021-04-25 00:42:56
    一,中断底层原理 部分 PL 到 PS 部分的中断,经过中断控制分配器(ICD),同时进入CPU1 和 CPU0。查询下面表格,可以看到 PL 到 PS 部分一共有 20 个中断可以使用。4 个快速中断(PPI),即IRQF2P[19:16];16 个...
  • 定时器中断 /* *硬件平台:韦东山嵌入式Linxu开发板(S3C2440.v3) *软件平台:运行于VMware Workstation 12 Player下UbuntuLTS16.04_x64 系统 *参考资料:S3C2440datasheet,开发版原理,S3C2440A datasheet, */...
  • C6678定时器中断学习180614

    千次阅读 2018-06-14 23:08:00
    话不多说,接触的6678板子,所以先从6678的中断部分开始写起,之前写了一个GPIO的,但是楼主发现脑子短路了,因为没有外部中断GPIO口来触发,所以改成了定时器中断触发,同时也增加了我对于ti的csl库函数的理解 ...
  • ZYNQ入门(三)-定时器中断

    千次阅读 2018-08-13 11:44:21
    zynq_定时器中断 @(study)[大学生活, markdown_study, LaTex_study] [TOC] zynq的中断体系结构框图 中断控制器(GIC) 在zynq中的中断控制比较复杂,主要是因为中断接收端有两个cpu,涉及到cpu的中断协同问题...
  • 描述单片机定时器中断是我们经常都需要用的,下面将以51单片机为例子来说明单片机定时器中断原理。80C51的定时/计数器的结构定时/计数器的实质是加1计数器(16位),由高8位和低8位两个寄存器组成。TMOD是定时/计数器...
  • 13.ARM定时器中断实例

    千次阅读 2019-01-22 16:10:16
    其中核心部分如下所示: 解析: 1).在外部有一个时钟源,CLK 2).每次时钟上,TCNTn减去1(n代表的是哪个计数器),当TCNTn的数值减小到和TCMPn相等时有个标志位进行提示(用于产生PWM信号),当数值减小到0...
  • Zigbee之旅(四):几个重要的CC2430基础实验——定时器中断 一、承上启下  上一篇,我们一起学习了简单的外部中断的实现。有了对中断的实践经验后,我们这一节来讨论一下定时器中断。CC2430共有4个...
  • 时间码发生器通过两条线与MCU相连,一条是地,一条是信号线用于传输数据。信号传输使用差分...1. EXTI Rising/Falling 中断+定时器方式测量100次波形脉冲宽度,通过排序算法找到合适的值确定为定时器周期值Pe...
  • 中断时为了使单片机具有对外部或者内部随机发生的事件处理而设置的,中断功能的存在,很大程度上提高了单片机处理外部或者内部事件的能力。 其实用生活中的例子,就是周六日,你的妈妈出门上班了,你们打开电脑玩起...
  •  通过使用定时器0来实现1秒的定时功能 ,通过对定时器中断处理函数对灯光的状态进行取反来演示.   2.相关寄存器介绍    定时器配置相关寄存器  1)TCFG0 注:(PCLK =101.25MHz) prescaler 0 = 249,...
  • } } 2.2 外部中断 分析 可以看到,外部中断是非常符合上面这个中断流程的 打个比方,我要在床上吹风扇,我自己的电线不够长,我要用我室友的插排。首先我先要和室友请求,室友同意我就插上去了,最后需要室友把总...
  • 定时器系统是单片机内部一个独立硬件部分,与CPU和晶振之间通过内部某些控制线连接并相互作用,CPU一旦启动定时功能,定时器便会在晶振的作用下自动计时,当定时器计数器积满之后就会产生中断,通知CPU接下来做什么...
  • STM32MP157系列教程连载-Cortex-M4开发篇6:STM32MP1微控制器之定时器中断 第 1 章 Cortex-M4 TIM定时器中断 实验目的 熟悉STM32CubeIDE工具软件的使用。 掌握STM32CubeIDE软件的基本设计流程和设计步骤,能够使用...
  • 目录 项目简介 硬件模块 软件工具 ...本项目利用CubMX创建一个32工程,用以实现定时器中断控制LED灯的状态转换的功能,并在Proteus中进行仿真验证。 硬件模块 STM32F103R4 LED 软件工具 ...
  • 一、课程内容,写了一个代码利用定时器中断实现LED小灯0.5S闪烁一次 (一)、S3C2440定时器部分手册分析: 1、 2、 定时器0、1有一个8位分频器,可以有5中不同的分频数,这个数字存储在TCFG0和TCFG1中。 3、 ...
  • 一位萌新为参加robomaster所做的前期准备–stm32基础(三)(定时器中断) 前段时间,由于在调试步兵车的底盘以及云台代码,调pid参数,研读新规则,小组开会,有些忙,没有及时更新,现在抽空更新文档 (嘿嘿) 一...
  • 定时器中断系统小白极客的51单片机笔记(自用)定时器介绍STC89C52定时器资源定时器框图定时器工作模式定时器时钟中断系统中断程序流程STC89C52中断资源定时器中断系统创建一个自定义列表如何创建一个注脚注释也...
  • SOC定时器中断配置

    2020-08-15 09:40:57
    SOC定时器中断配置 1 定时器中断工作原理 定时器原理: Soc每一个核拥有一个32位的私有定时器和一个32位的私有看门狗定时器,两个核还拥有一个共享的64位全局定时器。 私有定时器工作方式是32位自减模式,当...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,969
精华内容 4,787
关键字:

定时器中断的流程图