> 文章列表 > [单片机框架][bsp层][cx32l003][bsp_tim] Baes TIM 基础定时器配置和使用

[单片机框架][bsp层][cx32l003][bsp_tim] Baes TIM 基础定时器配置和使用

[单片机框架][bsp层][cx32l003][bsp_tim] Baes TIM 基础定时器配置和使用

文章目录

  • 一、基础定时器介绍
  • 二、功能描述
    • (1) Buzzer 功能
  • 三、示例代码(PWM)

一、基础定时器介绍

基础定时器 Base Timer 包含两个定时器 TIM10/11。TIM10/11 功能完全相同。TIM10/11 是同步定时/计数器,可以作为 16/32 位自动重装载功能的定时/计数器,也可以作为16/32 位无重载功能的定时/计数器。TIM10/11 可以对外部脉冲进行计数或者实现系统定时。

[单片机框架][bsp层][cx32l003][bsp_tim] Baes TIM 基础定时器配置和使用

二、功能描述

  1. TIM10/11 每个定时/计数器都有独立的控制启动信号、外部输入时钟和门控信号。
    当 TIM10/11 使用 EXT、GATE 来进行计数功能时,EXT 用于计数器的外部输入时钟信号,GATE 用于有效电平计数使能信号。
  2. 当门控功能使能后,当且仅当外部输入 GATE 电平有效时,计数器才会计数,否则计数器处于保持状态。
  3. 门控使能使用 TIMx_CR.GATE_EN 控制。默认门控功能关闭。
  4. 门控电平选择使用 TIMx_CR.GATE_P 控制。默认高电平为门控有效电平;设置 TIMx_CR.GATE_P 为 1后,门控低电平为有效电平。
  5. 当 TIM10/11 使用 PCLK,GATE 来进行定时功能时,PCLK 用于定时器的内部输入时钟信号,GATE可用于有效电平定时使能信号。
  6. 当门控功使能后,当且仅当外部输入 GATE 电平有效时,定时器才会计数,否则定时器处于定时计数器停止状态。
  7. 门控使能使用 TIMx_CR.GATE_EN 控制。默认门控功能关闭。
  8. 门控电平选择使用 TIMx_CR.GATE_P 控制。默认高电平为门控有效电平;设置为 1 后门控有效电平是低电平。定时功能可以配置预除频。TIMx_CR.TMR_PRE 控制分频比。

(1) Buzzer 功能

  1. 通过定时器的翻转输出功能可以实现驱动 Buzzer 的功能。TIMx_CR.TOG_EN 为 1 时,TOG、TOGN输出反向。
  2. 设置 TIMx_CR.TOG_EN 为 0 可以同时设置端口 TOG、TOGN 输出为 0。
  3. 在计数时钟为4M 情况下 Buzzer 输出不同频率的 Timer 重载模式配置如下(16 位 Max=0xFFFF):

[单片机框架][bsp层][cx32l003][bsp_tim] Baes TIM 基础定时器配置和使用

三、示例代码(PWM)

/********************************************************************************
* @file    bsp_tim.c
* @author  jianqiang.xue
* @version V1.1.0
* @date    2023-02-26
* @brief   本文件不再初始化GPIO,由APP_IO完成引脚初始化和复用。
********************************************************************************/
/* Public Includes ------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>#include "RTE_Components.h"
#include CMSIS_device_header#include "bsp_gpio.h"
#include "bsp_tim.h"
#include "cx32l003_hal_basetim.h"
/* Private Includes ----------------------------------------------------------*/
#include "ls_gpio.h"
#include "ls_syscfg.h"/* Private Define ------------------------------------------------------------*/
/* Private Typedef -----------------------------------------------------------*/#if LS_TIM10_EN
BASETIM_HandleTypeDef *g_tim10_handle = NULL;
static uint8_t g_tim10_pwm_update_cnt = 0;
static bsp_base_tim_cfg_t *g_tim10_cfg = NULL;
#endif
/* Public function prototypes -----------------------------------------------*/#if LS_TIM10_EN
#include "ls_gpio.h"
#include "ls_syscfg.h"
/*** @brief  TIM10初始化* @param  *cfg: 基础定时器配置* @retval 0--成功*/
uint8_t bsp_tim10_init(bsp_base_tim_cfg_t *cfg) {if (g_tim10_handle) return 0; // 已经初始化过if (cfg == NULL) return 3; // 配置为空g_tim10_handle = malloc(sizeof(BASETIM_HandleTypeDef)); // 申请空间if (!g_tim10_handle) return 1; // TIM结构体无法申请空间memset(g_tim10_handle, 0, sizeof(BASETIM_HandleTypeDef));// 结构体赋值g_tim10_handle->Instance          = TIM10;g_tim10_handle->Init.CntTimSel    = BASETIM_TIMER_SELECT;          // CKD 时钟分频因子(Clock division)g_tim10_handle->Init.MaxCntLevel  = BASETIM_MAXCNTLEVEL_16BIT;     // TimerSize=0:max count value=0xFFFF;g_tim10_handle->Init.AutoReload   = BASETIM_AUTORELOAD_ENABLE; // 模式2自动重装载计数器/定时器g_tim10_handle->Init.OneShot      = BASETIM_REPEAT_MODE; // 重复模式g_tim10_handle->Init.Period       = BASETIM_MAXCNTVALUE_16BIT - HAL_RCC_GetPCLKFreq()/cfg->period;  // 重装载值 cfg->periodg_tim10_handle->Init.Prescaler    = cfg->prescaler;   // 预分频 cfg->prescalerg_tim10_cfg = cfg;__HAL_RCC_BASETIM_CLK_ENABLE();HAL_BASETIM_Base_Init(g_tim10_handle);HAL_NVIC_EnableIRQ(TIM10_IRQn);return 0;
}void bsp_tim10_set_pwm(uint8_t io, uint8_t val) {if (g_tim10_cfg == NULL) return;HAL_BASETIM_Base_Stop_IT(g_tim10_handle);if (g_tim10_cfg->io != io) {g_tim10_cfg->io = io;}if (g_tim10_cfg->cnt != val) {g_tim10_cfg->cnt = val;}if (io != 0xff) {HAL_BASETIM_Base_Start_IT(g_tim10_handle);}
}void TIM10_IRQHandler(void) {/* TIM Update event */if (__HAL_BASETIM_GET_FLAG(g_tim10_handle) != RESET) {if (__HAL_BASETIM_GET_IT_SOURCE(g_tim10_handle) != RESET) {__HAL_BASETIM_CLEAR_IT(g_tim10_handle);if (g_tim10_cfg == NULL) return;if (g_tim10_cfg->io == 0xFF) {HAL_BASETIM_Base_Stop_IT(g_tim10_handle);return;}if (g_tim10_pwm_update_cnt++ < g_tim10_cfg->cnt) {bsp_gpio_set_pin(g_io_cfg[g_tim10_cfg->io].port, g_io_cfg[g_tim10_cfg->io].pin, BSP_GPIO_PIN_SET);} else if (g_tim10_pwm_update_cnt < g_tim10_cfg->period - g_tim10_cfg->cnt) {bsp_gpio_set_pin(g_io_cfg[g_tim10_cfg->io].port, g_io_cfg[g_tim10_cfg->io].pin, BSP_GPIO_PIN_RESET);} else {g_tim10_pwm_update_cnt = 0;}}}
}#endif
/********************************************************************************
* @file    bsp_tim.c
* @author  jianqiang.xue
* @version V1.1.0
* @date    2023-02-26
* @brief   本文件不再初始化GPIO,由APP_IO完成引脚初始化和复用。
********************************************************************************/#ifndef __BSP_TIM_H
#define __BSP_TIM_H/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include "ls_syscfg.h"
/* Private Define ------------------------------------------------------------*/typedef struct {uint16_t prescaler;  // 预分频器的值(Prescaler value) 计数器的时钟频率(CK_CNT)等于 fCK_PSC/(PSC[15:0]+1)。uint16_t freq; // 单位hz,freq对应的period: 750--15  1000--20 1500--30  2000--40  3000--60  6000--120uint16_t period;     // 周期     作为PWM时,决定了PWM的分辨率uint8_t level_logic; // 有效电平   0--低电平  1--高电平uint8_t io;  // IO_IDuint16_t cnt; // 计数器的值(Counter value)--CNT
} bsp_base_tim_cfg_t; // 模拟PWM
/* Private Typedef -----------------------------------------------------------*//* Public Function Prototypes ------------------------------------------------*/
#if LS_TIM10_EN
uint8_t bsp_tim10_init(bsp_base_tim_cfg_t *cfg);
void bsp_tim10_set_pwm(uint8_t io, uint8_t val);
#endif
#endif
#if LS_TIM10_EN
bsp_base_tim_cfg_t g_tim10_cfg = {.prescaler = LS_TIM10_PRESCALER,.freq = LS_TIM10_FREQ,.period = LS_TIM10_PERIOD,.level_logic = LS_TIM10_LEVEL_LOGIC};
#endif
bsp_tim10_init(&g_tim10_cfg);// 将LED0亮度设置50%
bsp_tim10_set_pwm(LED0, g_tim10_cfg.period/2);