打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033

LiSun

打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

9 定时器(TIMER)

9.1 通用定时器(TMR2到TMR5)
9.1.1 TMRx简介
通用定时器是一个通过可编程预分频器驱动的 16 位自动装载计数器构成。它适用于多种场合,包括测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM) 。
使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。

每个定时器都是完全独立的,没有互相共享任何资源。它们可以一起同步操作,参见 9.2.3.15 节。

9.1.2 TMRx主要功能
通用 TMRx(TMR2、TMR3、TMR4 和 TMR5)定时器功能包括:

  • 16位向上、向下、向上/向下自动装载计数器
    注意: TMR2 和 TMR5 可选 32 位,详见 9.2.4.1 节 TMRx_CTRL1 寄存器
  • 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65536之间的任意数值
  • 4个独立通道:
    ①输入捕获
    ②输出比较
    ③PWM生成(边缘或中间对齐模式)
    ④单脉冲模式输出
  • 使用外部信号控制定时器和定时器互连的同步电路
  • 如下事件发生时产生中断/DMA:
    ① 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触
    发)
    ②触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
    ③输入捕获
    ④输出比较
  • 支持针对定位的增量(正交)编码器和霍尔传感器电路
  • 触发输入作为外部时钟或者按周期的电流管理
    在这里插入图片描述
    9.1.3 TMRx功能描述
    9.1.3.1 时基单元
    可编程通用定时器的主要部分是一个 16 位计数器和与其相关的自动装载寄存器。这个计数器可以向上计数、向下计数或者向上向下双向计数。此计数器时钟由预分频器分频得到。
    计数器、自动装载寄存器和预分频器寄存器可以由软件读写,在计数器运行时仍可以读写。
    时基单元包含:
  • 计数器寄存器(TMRx_CNT)
  • 预分频器寄存器(TMRx_DIV)
  • 自动装载寄存器(TMRx_AR)

自动装载寄存器是预先装载的, 写或读自动重装载寄存器将访问预装载寄存器。 根据在 TMRx_CTRL1寄存器中的自动装载预装载使能位 (ARPEN) 的设置, 预装载寄存器的内容被立即或在每次的更新事件 UEV 时传送到影子寄存器。 当计数器达到溢出条件 (向下计数时的下溢条件) 并当 TMRx_CTRL1寄存器中的 UEVDIS 位等于’0’时,产生更新事件。更新事件也可以由软件产生。随后会详细描述每一种配置下更新事件的产生。

计数器由预分频器的时钟输出 CK_CNT 驱动,仅当设置了计数器 TMRx_CTRL1 寄存器中的计数器使能位(CNTEN)时,CK_CNT 才有效。 (有关计数器使能的细节,请参见控制器的从模式描述) 。

注意: 真正的计数器使能信号 CNT_EN 是在 CNTEN 的一个时钟周期后被设置。

/********************************************************************************
* @file    bsp_tim.c
* @author  jianqiang.xue
* @version V1.0.0
* @date    2022-02-14
* @brief   NULL
********************************************************************************/
/* Includes ----------------------------------------------------------*/
#include <stdio.h>
#include <string.h>

#include "RTE_Components.h"
#include CMSIS_device_header

#include "bsp_gpio.h"
#include "bsp_tim.h"

/* Private Includes ----------------------------------------------------------*/
#include "business_gpio.h"
#include "business_function.h"

/* Private Define ------------------------------------------------------------*/
/* Private Typedef -----------------------------------------------------------*/
#if BS_TIM1_EN
TMR_TimerBaseInitType tim1_handle_t =
{
    .TMR_Period            = BS_TIM1_PERIOD,                     // 重装载值
    .TMR_DIV               = BS_TIM1_PRESCALER,                  // 预分频
    .TMR_ClockDivision     = 0,                                  // CKD 时钟分频因子(Clock division)
    .TMR_CounterMode       = TMR_CounterDIR_Up,                  // 边沿对齐模式 计数器向上计数
    .TMR_RepetitionCounter = 0,                                  // TIM1_RCR 重复计数器的值
};

TMR_OCInitType tim1_oc_init_handle_t =
{
    .TMR_OCMode         = TMR_OCMode_PWM1,        // PWM模式1 TIM1_CCMR1
    .TMR_Pulse          = BS_TIM1_PERIOD,         // CCR 捕获/比较通道
    .TMR_OutputState    = TMR_OutputState_Enable, // 输出模式
    .TMR_OCPolarity     = TMR_OCPolarity_High     // 高电平有效
};
#endif


void bsp_tim_pwm_init(void)
{
#if BS_TIM1_EN
    /* TMR1 clocks enable */
    RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_TMR1, ENABLE);
    /* Set TIMx instance */
    TMR_TimeBaseInit(TMR1, &tim1_handle_t);

#if BS_PWM0_EN
    /* Enable the Clock */
    bsp_gpio_set_clk(GPIO_APBx, BS_TIM1_CH1_GPIO_CLK, true);
    bsp_gpio_init_tim(BS_TIM1_CH1_GPIO_PORT, BS_TIM1_CH1_PIN, 0);
    TMR_OC1Init(TMR1, &tim1_oc_init_handle_t);
    TMR_OC1PreloadConfig(TMR1, TMR_OCPreload_Enable);  //CH1预装载使能
#endif

#if BS_PWM1_EN
    /* Enable the Clock */
    bsp_gpio_set_clk(GPIO_APBx, BS_TIM1_CH2_GPIO_CLK, true);
    bsp_gpio_init_tim(BS_TIM1_CH2_GPIO_PORT, BS_TIM1_CH2_PIN, 0);
    TMR_OC2Init(TMR1, &tim1_oc_init_handle_t);
    TMR_OC2PreloadConfig(TMR1, TMR_OCPreload_Enable);  //CH2预装载使能
#endif

#if BS_PWM2_EN
    /* Enable the Clock */
    bsp_gpio_set_clk(GPIO_APBx, BS_TIM1_CH3_GPIO_CLK, true);
    bsp_gpio_init_tim(BS_TIM1_CH3_GPIO_PORT, BS_TIM1_CH3_PIN, 0);
    TMR_OC3Init(TMR1, &tim1_oc_init_handle_t);
    TMR_OC3PreloadConfig(TMR1, TMR_OCPreload_Enable);  //CH3预装载使能
#endif

#if BS_PWM3_EN
    /* Enable the Clock */
    bsp_gpio_set_clk(GPIO_APBx, BS_TIM1_CH4_GPIO_CLK, true);
    bsp_gpio_init_tim(BS_TIM1_CH4_GPIO_PORT, BS_TIM1_CH4_PIN, 0);
    TMR_OC4Init(TMR1, &tim1_oc_init_handle_t);
    TMR_OC4PreloadConfig(TMR1, TMR_OCPreload_Enable);  //CH4预装载使能
#endif

    /* TMR1 Main Output Enable
    普通定时器在完成以上设置了之后, 就可以输出 PWM 了,
    但是高级定时器,我们还需要使能刹车和死区寄存器( TIM1_BDTR)的 MOE 位,以使能整个 OCx(即 PWM)输出。
    */
    TMR_CtrlPWMOutputs(TMR1, ENABLE);
    //使能TIMx在ARR上的预装载寄存器
    TMR_ARPreloadConfig(TMR1, ENABLE);
    /* TMR1 counter enable */
    TMR_Cmd(TMR1, ENABLE);
#endif
}

void bsp_tim_pwm_deinit(void)
{
#if BS_TIM1_EN
#if BS_PWM0_EN
    bsp_gpio_deinit(BS_TIM1_CH1_GPIO_PORT, BS_TIM1_CH1_PIN);
#endif
#if BS_PWM1_EN
    bsp_gpio_deinit(BS_TIM1_CH2_GPIO_PORT, BS_TIM1_CH2_PIN);
#endif
#if BS_PWM2_EN
    bsp_gpio_deinit(BS_TIM1_CH3_GPIO_PORT, BS_TIM1_CH3_PIN);
#endif
#if BS_PWM3_EN
    bsp_gpio_deinit(BS_TIM1_CH4_GPIO_PORT, BS_TIM1_CH4_PIN);
#endif
    TMR_Reset(TMR1);
    RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_TMR1, DISABLE);
#endif
}

void bsp_tim_set_period(bsp_tim_t tim_id, uint16_t period)
{
    if (tim_id == BSP_TIM_0)
    {
    }
    else if (tim_id == BSP_TIM_1)
    {
        TMR_SetAutoreload(TMR1, period);
    }
}


/********************************************************************************
* @file    bsp_tim.h
* @author  jianqiang.xue
* @version V1.0.0
* @date    2021-04-19
* @brief   NULL
********************************************************************************/

#ifndef __BSP_TIM_H
#define __BSP_TIM_H

#include <stdint.h>

/* Includes ------------------------------------------------------------------*/
typedef enum
{
    BSP_TIM_0 = 0,
    BSP_TIM_1
} bsp_tim_t;

/* Public Function Prototypes ------------------------------------------------*/

void bsp_tim_pwm_init(void);
void bsp_tim_pwm_deinit(void);
void bsp_tim_set_period(bsp_tim_t tim_id, uint16_t period);
#endif

posted on 2022-08-13 11:00  xuejianqiang  阅读(104)  评论(0编辑  收藏  举报
打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033