高级控制定时器(TIM1 和 TIM8)由一个 16 位的自动装载计数器、一个可编程的重复计数器和一个可编程
预分频计数器组成。
高级控制定时器可以用于测量输入信号的脉冲宽度(输入捕获)、产生输出波形(输出比较、PWM、嵌入死
区时间的互补 PWM 等)以及对输入信号进行计数。
结合定时器预分频器和 RCC 时钟控制预分频器,可以实现脉冲宽度和波形周期从几个微秒到几个毫秒的调
节。
高级控制定时器(TIM1 和 TIM8)和通用定时器(TIMx)不共享任何资源,完全独立,可以实现异步或同 步操作,具体描述参看 11.3.20 节。
TIM1 和 TIM8 定时器的功能包括:
16 位向上、向下、向上/下自动装载计数器
16 位可编程预分频器,计数器时钟频率的分频系数为 1~65535 之间的任意数值
多达 4 个独立通道:
输入捕获
输出比较
PWM 生成(边缘或中间对齐模式) 单脉冲模式输出
死区时间可编程的互补输出
外部信号结合内置同步电路对多个定时器进行统一控制
允许在指定数目的计数器周期之后更新定时器寄存器的重复计数器
刹车输入信号可以将定时器输出信号置于复位状态或者一个已知状态
支持 IOM、CSS、PVD、HardFault、比较器输出进行 PWM 刹车
支持捕获 IO 信号或比较器输出信号
如下事件发生时产生中断/DMA:
更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
输入捕获
输出比较
刹车信号输入
高级定时器由预分频器、计数器、自动装载寄存器以及重复计数器组成。计数器可以向上计数、向下计数
或者向上向下双向计数。预分频器分频后的时钟输入计数器。
在时基单元工作时,软件仍可以随时对计数器、自动装载寄存器和预分频器寄存器进行读写。
时基单元包含:预分频器寄存器 (TIMx_PSC)
计数器寄存器(TIMx_CNT)
自动装载寄存器 (TIMx_AR)
重复次数寄存器 (TIMx_REPCNT)
自动装载寄存器具有预先装载功能,读写自动重装载寄存器将访问预装载寄存器。根据在 TIMx_CTRL1 寄
存器中的自动装载预装载使能位(ARPEN)的设置,预装载寄存器的内容被立即或在每次的更新事件 UEV
时传送到影子寄存器。以下条件产生更新事件:
当计数器达到溢出条件(向下计数时的下溢条件)并当 TIMx_CTRL1 寄存器中的 UPDIS 位等于 0 时,
产生更新事件。
软件产生。
预分频器的时钟输出 CK_CNT 驱动计数器,仅当设置了计数器 TIMx_CTRL1 寄存器中的计数器使能位
(CNTEN)时,CK_CNT 才有效。(更多有关使能计数器的细节,请参见控制器的从模式描述)。
注意,在设置了 TIMx_CTRL 寄存器的 CNTEN 位的一个时钟周期后,计数器开始计数
#include
#include "errorno.h"
#include "n32g4fr.h"
#include "bsp_tim.h"
#include "n32g4fr_rcc.h"
static bsp_tim3_cb_t bsp_tim3_cb = NULL;
bsp_tim_cfg bsp_tim3_cfg = {
.num = 3,
.timx = TIM3,
.rcc = RCC_APB1_PERIPH_TIM3,
.irqn = TIM3_IRQn};
/**
* @brief 初始化堆栈指针
* @param timx:定时器结构体 Period:周期 Prescaler:预分频
* @retval 0--成功 -1--失败
*/
int32_t bsp_tim_init(bsp_tim_cfg timx, uint16_t Period, uint16_t Prescaler)
{
TIM_TimeBaseInitType timInitStruct;
NVIC_InitType NVIC_InitStructure;
if (timx.num < 1 || timx.num > 8)
{
return RETVAL(E_FAIL);
}
if (timx.num == 1 || timx.num == 8)
{
RCC_EnableAPB2PeriphClk(timx.rcc, ENABLE);
}
else
{
RCC_EnableAPB1PeriphClk(timx.rcc, ENABLE);
}
timInitStruct.Period = Period;
timInitStruct.Prescaler = Prescaler;
timInitStruct.ClkDiv = 0;
timInitStruct.CntMode = TIM_CNT_MODE_UP;
TIM_InitTimeBase(timx.timx, &timInitStruct);
TIM_ConfigInt(timx.timx, TIM_INT_UPDATE, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = timx.irqn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Enable(timx.timx, ENABLE);
return E_OK;
}
/**
* @brief 控制TIM使能
*/
void bsp_tim_enable(bsp_tim_cfg timx, FunctionalState Cmd)
{
TIM_Enable(timx.timx, Cmd);
}
/**
* @brief 设置TIM3中断回调函数
*/
int32_t bsp_tim3_set_irq_callback(bsp_tim3_cb_t cb)
{
if (bsp_tim3_cb != NULL)
{
return RETVAL(E_FAIL);
}
bsp_tim3_cb = cb;
return E_OK;
}
/**
* @brief TIM3中断处理函数每100us。取TIM2->CNT值,计算脉冲个数
两倍之差。然后将增量脉冲放入最后一个通道的缓冲区,并切换到新通道。
*/
void TIM3_IRQHandler(void)
{
if (TIM_GetIntStatus(TIM3, TIM_INT_UPDATE) != RESET)
{
TIM_ClrIntPendingBit(TIM3, TIM_INT_UPDATE);
(*bsp_tim3_cb)();
}
}
#ifndef _BSP_TIM_H_
#define _BSP_TIM_H_
#include "n32g4fr.h"
typedef void (*bsp_tim3_cb_t)(void);
typedef struct
{
uint8_t num; //定时器编号 范围1-8
TIM_Module *timx; //定时器寄存器结构体,如TIM3
uint32_t rcc; //定时器时钟,如RCC_APB1_PERIPH_TIM3
uint8_t irqn; //中断编号,如TIM3_IRQn
} bsp_tim_cfg;
extern bsp_tim_cfg bsp_tim3_cfg;
int32_t bsp_tim_init(bsp_tim_cfg timx, uint16_t Period, uint16_t Prescaler);
void bsp_tim_enable(bsp_tim_cfg timx, FunctionalState Cmd);
int32_t bsp_tim3_set_irq_callback(bsp_tim3_cb_t cb);
#endif