stm32定时器(基本定时器)操作寄存器版

定时器本质
定时器的本质:计数器
定时器的构成:时钟源+计数器+重载值

1、stm32的定时器
   stm32定时器数量较多、功能比较强;不同的定时器功能有不同。
   stm32的定时器进行类型划分。分为三类:①基本定时器;②通用定时器;③高级定时器
   基本定时器:用于定时器,还可以用于触发DAC(数模转换器)、ADC(模数转换器)工作。
   通用定时器:具备基本定时器所有的功能;捕获输入、比较输出、捕获PWM波、生成PWM波、支持霍尔元件
   高级定时器:具备通用定时器所有的功能:支持死区、刹车功能。

STM32F407的基本定时器有TIM6、TIM7.
STM32F407的通用定时器有TIM2~TIM5,TIM9~TIM14.
STM32F407的高级定时器有TIM1、TIM8.
    
基本定时器定时功能。
2、基本定时器定时功能介绍。
   基本定时器 TIM6 和 TIM7 包含一个 16 位自动重载计数器,该计数器由可编程预分频器驱动。
   此类定时器不仅可用作通用定时器以生成时基(可以作为通用定时器的时钟源), 还可以专门用于驱动数模转换器 (DAC)。实
   际上,此类定时器内部连接到 DAC 并能够通过其触发输出驱动 DAC。
   这些定时器彼此完全独立,不共享任何资源(每个定时器都可以单独工作,不需要其他定时器的资源)。

3、基本定时器的特征
   基本定时器(TIM6 和 TIM7)的特性:
   ● 16 位自动重载递增计数器
   ● 16 位可编程预分频器,用于对计数器时钟频率进行分频(即运行时修改),分频系数介于 1 和 65536 之间
   ● 用于触发 DAC 的同步电路
   ● 发生如下更新事件时会生成中断/DMA 请求:计数器上溢(计数器上溢会产生更新事件,更新事件能够产生中断/DMA请求)。

例:
  假设 168MHz  10000分频
    
  本身在168MHz的情况下1秒钟,只需要记168M个数。
  如果是10000分频,那么就要记:168MHz/10000 = 16800个数  

公式套用:

计数时钟 = 时钟源 / PSC + 1
时钟周期 = 1/计数时钟  
时钟周期 * arr = 得出多少时间才溢出,触发中断


4、基本定时器框架
   工作原理在框图上有体现:

什么时候用自动重载值寄存器带缓冲功能?   什么时候用自动重载值寄存器不带缓冲功能?
   不带缓冲功能:定时器只需要固定一个时间的定时,这个项目中不需要改变这个定时器的定时。
 例如:这个定时器1s中点亮LED灯,1s中熄灭LED灯
   带缓冲功能:定时一个时间后要换时间。  例如:这个定时器500ms中点亮LED灯,100ms中熄灭LED灯
   UG位:可以让计数器清0,自动重载值写入到影子寄存器,清除分频器的值,不会改变分频比。

   配置流程:
   1、选择一个定时时长;确定预分频与重载值。 
   2、确定是否使用缓存功能(UG位操作)
   3、使能定时器
   4、等待时间到

   计算预分频去与自动重载值如何设定?TIM6/7定时器5s钟。

5、基本定时器的相关寄存器

   5.1 TIM6 和 TIM7 控制寄存器 1 (TIMx_CR1)

    

位 7 ARPE:自动重载预装载使能 (Auto-reload preload enable)
        0: TIMx_ARR 寄存器不进行缓冲。
        1: TIMx_ARR 寄存器进行缓冲。
位 3 OPM:单脉冲模式 (One-pulse mode)
        0:计数器在发生更新事件时不会停止计数(循环功能
        1:计数器在发生下一更新事件时停止计数(将 CEN 位清零)(单次功能)。
位 2 URS:更新请求源 (Update request source)
        此位由软件置 1 和清零,用以选择 UEV 事件源。
        0:使能时(UEV使能),所有以下事件都会生成更新中断或 DMA 请求。此类事件包括:
              — 计数器上溢/下溢
              — 将 UG 位置 1
              — 通过从模式控制器生成的更新事件
        1:使能时(UEV使能),只有计数器上溢/下溢会生成更新中断或 DMA 请求。
位 1 UDIS:更新禁止 (Update disable)
        此位由软件置 1 和清零,用以使能/禁止 UEV 事件生成。
        0:使能 UEV。更新 (UEV) 事件可通过以下事件之一生成: 
             — 计数器上溢/下溢
             — 将 UG 位置 1
             — 通过从模式控制器生成的更新事件然后更新影子寄存器的值。
        1:禁止 UEV。不会生成更新事件,各影子寄存器的值(ARR 和 PSC)保持不变。但如果将
          UG 位置 1,或者从从模式控制器接收到硬件复位,则会重新初始化计数器和预分频器。

位 0 CEN:计数器使能 (Counter enable)
        0:禁止计数器
        1:使能计数器
        注意: 只有事先通过软件将 CEN 位置 1,才可以使用门控模式。而触发模式可通过硬件自动将
        CEN 位置 1。
在单脉冲模式下,当发生更新事件时会自动将 CEN 位清零。
5.2  TIM6 和 TIM7 控制寄存器 2 (TIMx_CR2)

这个寄存器与基本定时器功能无关,只有需要使用到TRGO才去关心该位。

5.3TIM6 和 TIM7 DMA/中断使能寄存器 (TIMx_DIER)

位 8 UDE:更新 DMA 请求使能 (Update DMA request enable)
        0:禁止更新 DMA 请求。
        1:使能更新 DMA 请求。
位 0 UIE:更新中断使能 (Update interrupt enable) (模块级使能中断位
        0:禁止更新中断。
        1:使能更新中断。
5.4  TIM6 和 TIM7 状态寄存器 (TIMx_SR)

位 0 UIF:更新中断标志 (Update interrupt flag)
        该位在发生更新事件时通过硬件置 1。但需要通过软件清零。
        0:未发生更新。
        1:更新中断挂起。该位在以下情况下更新寄存器时由硬件置 1:(定时时间到
        — 上溢或下溢并且当 TIMx_CR1 寄存器中 UDIS = 0 时。
        — 当由于 TIMx_CR1 寄存器中 URS = 0 且 UDIS = 0 而通过软件使用 TIMx_EGR 寄存器中

的 UG 位重新初始化 CNT 时。
5.5  TIM6 和 TIM7 事件生成寄存器 (TIMx_EGR)

位 0 UG:更新生成 (Update generation)
        该位可通过软件置 1,并由硬件自动清零。
        0:不执行任何操作。
        1:重新初始化定时器计数器并生成寄存器更新事件。请注意,预分频器计数器也将清零(但预分频比不受影响)。
5.6  TIM6 和 TIM7 计数器 (TIMx_CNT)

位 15:0 CNT[15:0]:计数器值 (Counter value)

5.7  TIM6 和 TIM7 预分频器 (TIMx_PSC)

位 15:0 PSC[15:0]:预分频器值 (Prescaler value)
        计数器时钟频率 CK_CNT 等于 fCK_PSC / (PSC[15:0] + 1)。注意: 该位会自动加1,在设置的时候要减1。

        例如:8400分频  只需写入8399即可。
        PSC 包含在每次发生更新事件时要装载到实际预分频器寄存器的值。
5.8  TIM6 和 TIM7 自动重载寄存器 (TIMx_ARR)

位 15:0 ARR[15:0]:自动重载值 (Auto-reload value)
      ARR 为要装载到实际自动重载寄存器的值。注意:自动重载值写入10000;真实写入的值只能是9999。原因看下图便知。
     有关 ARR 更新和行为的详细信息,请参见第 17.3.1 节:第 484 页的时基单元。
     当自动重载值为空时,计数器不工作。

配置流程:

案例:实现1s LED亮,1s LED灭

6、使用定时器6

1、初始化

      开启时钟、清空计数器的值、设置预分频、设置重载值、设置无缓冲功能、采用循环模式、控制寄存器1、开启中断使能(模块级中断使能、核心级中断使能)、开启计数器使能。

2、编写中断服务函数

     清标志位、灯亮与灯灭。


程序:

timer6.h

#ifndef __TIMER6_H__
#define __TIMER6_H__

#include <stm32f4xx.h>

void timer6_init(u16 arr, u16 psc);


#endif

timer6.c

#include "timer6.h"
#include "led.h"

/*
函数功能:基本定时器初始化
返回值:无
形参:arr:重装载值 psc:预分频值
*/
void timer6_init(u16 arr, u16 psc) 
{
    //开启基本定时器6(TIM6)的时钟
    RCC->APB1ENR |= 1<<4;

    /*清空计数器的值*/
    TIM6->CNT = 0;
    
    TIM6->PSC = psc;  //预分频值 (8400)
    TIM6->ARR = arr;  //重装载值 (1s钟定时)
    
    TIM6->CR1 = 0;      //将控制寄存器1清空
    
    TIM6->CR1 |= 1<<2;    //设置事件更新请求源
    
    /*设置无缓冲功能*/
    TIM6->CR1 &= ~(1<<7);    
    
    /*设置循环模式*/
    TIM6->CR1 &= ~(1<<3);
    
    /*允许更新中断使能*/
    TIM6->DIER |= 1<<0;
    
    /*使能基本定时器中断*/
    NVIC_EnableIRQ(TIM6_DAC_IRQn);
    
    /*开启计数器使能*/
    TIM6->CR1 |= 1<<0;
}

/*
函数功能:基本定时器终端服务函数
返回值:无
形参:无
*/
void TIM6_DAC_IRQHandler(void)
{
    if(TIM6->SR & (1<<0))      //溢出中断
    {
        TIM6->SR &= ~(1<<0);  //清除中断标志位
        //执行相应操作
        LED2 = !LED2;
    }
}

main.c

#include "led.h"
#include "tim6.h"

int main(void)
{
		
	led_init();
	timer6_init(5000-1, 8400-1);	//重装载值:5000-1, 分频8400-1
}
发布了41 篇原创文章 · 获赞 63 · 访问量 57万+

猜你喜欢

转载自blog.csdn.net/qq_36075612/article/details/82937615