目录
一、定时器资源
🔵超低功耗的 STM32L071xx 器件包括三个通用定时器,一个低功耗定时器,一个基本定时器,两个看门狗定时器和 SysTick 定时器。
- 计数器分辨率:决定计数的范围,16位计数器计数范围为(0-65535)
- 计数器类型:向上计数、向下计数、向上/向下计数
- 预分频系数:1-65536,对输入定时器的时钟进行分频
- 捕捉/比较通道:捕获外部触发信号、PWM 输出、单脉冲输出等
定时器 | 计数器分频率 | 计数器类型 | 预分频系数 | DMA请求产生 | 捕获/比较通道数 | 互补输出 |
---|---|---|---|---|---|---|
TIM2 TIM3 | 16位 | 向上、向下、向上/向下 | 1-65536 | 允许 | 4 | 不能 |
TIM21 TIM22 | 16位 | 向上、向下、向上/向下 | 1-65536 | 不允许 | 2 | 不能 |
TIM6 TIM7 | 16位 | 向上 | 1-65536 | 允许 | 0 | 不能 |
1. 4个可同步的通用定时器(TIM2、TIM3、TIM21、TIM22)
- 其中 TIM3 的通道3(即引脚 PB0),可用于拓展的脉冲模块作输入捕获通道;
2. LPTIM 低功耗定时器(下文介绍);
3. SysTick Timer: 这个定时器专门用于操作系统,但也可以用作标准的计数器。它是基于一个24位的自动重新加载能力和一个可编程的时钟源。当计数器到达0时,它具有可掩蔽的系统中断生成功能。
二、LPTIM
(1)LPTIM 介绍
低功耗计时器有一个独立的时钟,如果它被 LSE、LSL 或外部时钟锁定,它也处于停止模式。它能够从停止模式唤醒设备。
这个低功耗计时器支持以下功能:
- 具有 16 位自动重载寄存器的 16 位上计数器
- 16位比较寄存器
- 可配置的输出: (脉冲、PWM)
- 连续/一次模式
- 软件触发/硬件触发
- 可选择时钟来源:
- 内部时钟来源(LSE、LSI、HSI、APB)
- 外部时钟源通过 LPTIM 输入(即使没有内部时钟源运行,脉冲计数器应用程序也使用)
- 可编程数字故障滤波器
- 编码器模式
(2)STM32CubeMX 软件配置
🔅“工程建立、时钟树配置、Debug 串行线配置、代码生成配置” 在【蓝桥杯——物联网设计与开发】基础模块1- GPIO输出 一文中有讲解,这里不再赘述❗️
1️⃣点击引脚 PC15 → 选择 GPIO_Output 模式(此处默认为推挽输出);
2️⃣点击 "GPIO" → 点击引脚 PC15 → 将 "GPIO output level" 栏修改为 "High",即将 PC15 引脚初始化为高电平;
⚠️此处修改不是必须的,应当根据题意要求进行配置,这里默认为上电熄灭;
3️⃣点击 "Timers" → 选择 "LPTIM1" → 在模式一栏中选择 "Counts internal clock events";
- 此处使能低功耗定时器 LPTIM1,并将模式配置为"计数内部时钟",即 LPTIM1 的时钟源为内部时钟;
4️⃣点击 "Clock Configuration" 栏 → 配置 LPTIMCLK (低功耗定时器时钟源)为 "PCLK1" (外设时钟1);
5️⃣返回 "Pinout & Configuration" 栏,对 LPTIM 参数进行配置;
- 时钟分频配置为32分频,即 LPTIM 时基时钟为1MHz;
- 预装载更新模式配置为 "Update End Of Period",即在周期结束时更新;
6️⃣在 "NVIC Settings" 栏,使能 LPTIM 中断;
7️⃣生成代码即可;
(3)代码编写
🟢️main函数
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define PERIOD 1000
/* USER CODE END PD */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_LPTIM1_Init();
/* USER CODE BEGIN 2 */
/* 启动定时器并设置周期,此处设置为1000,即1ms中断一次 */
HAL_LPTIM_Counter_Start_IT(&hlptim1, PERIOD);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
在 while(1) 死循环之前,调用函数
HAL_LPTIM_Counter_Start_IT(&hlptim1, PERIOD);
以中断的方式启动 LPTIM 开始计数,此处周期设置为1000;
由于 LPTIM 时基时钟为 1MHz,则1000个周期为1ms,即1ms中断一次;
🟠️中断回调函数
/* USER CODE BEGIN 0 */
/* LPTIM 自动重载匹配回调函数 - 1ms进入一次 */
void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim)
{
/* 静态变量定义,用于1s计数 */
static uint16_t cnt_1s = 0;
/* 计数满1000次即1s */
if(++cnt_1s == 1000)
{
/* 变量清零,用于下一次计数 */
cnt_1s = 0;
/* LD5状态翻转,便于观察现象 */
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);
}
}
/* USER CODE END 0 */
⚠️查阅头文件 "stm32l0xx_hal_lptim.h" → 在第618行,查找中断回调函数声明;
声明函数 void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim);
该函数每 1ms 进入一次,在函数内部声明静态变量用于 1s 计数,当时间达到 1s 时,将变量清零,并翻转 LD5 状态,便于现象观察;
(4)实验现象
- LD5 状态每间隔 1s 取反;
三、踩坑日记
🔅使用中断回调函数,一定要在进入死循环之前调用定时器中断方式启动函数,否则中断无法工作;