STM32 HAL库开发学习5. 系统滴答定时器

STM32 HAL库开发学习5. 系统滴答定时器

  • 一、滴答定时器概述
    • [1. 概述](#1. 概述)
    • [2. 时钟源](#2. 时钟源)
    • [3. 寄存器](#3. 寄存器)
      • [(1)控制与状态寄存器 STK_CTRL](#(1)控制与状态寄存器 STK_CTRL)
      • [(2)重载寄存器 STK_LOAD](#(2)重载寄存器 STK_LOAD)
      • [(3)当前值寄存器 STK_VAL](#(3)当前值寄存器 STK_VAL)
  • 二、HAL库滴答定时器初始化
  • 三、SysTick实现微秒级延时
    • [1. 使用 STM32CubeMX创建工程](#1. 使用 STM32CubeMX创建工程)
    • [2. 代码实现](#2. 代码实现)

一、滴答定时器概述

1. 概述

滴答定时器是Cortext-M内核的一个简单定时器。

滴答定时器是一个24位的递减计数器,主要用于为嵌入式系统提供基本的定时功能,也为实时操作系统RTOS提供系统节拍。

2. 时钟源

滴答定时器有两个可选的时钟源,一个是处理器内核时钟: HCLK,另一个是外部参考时钟。

当定时器启动后,它会从设定的初始值开始递减计数。每经过一个时钟周期,计数器值减1.当计数器减到0,会产生一个中断请求,并且可以根据设置重新加截初始值。

3. 寄存器

(1)控制与状态寄存器 STK_CTRL

该寄存器用于控制滴答定时器的主要功能。其中包含了启动 / 停止定时器的位(ENABLE 位),如果将此位置 1,则启动定时器;若置 0,则停止定时器。

还有用于控制中断使能的位(TICKINT 位),当这个位置 1 时,定时器计数到 0 时会产生中断;置 0 则禁止中断。

另外,有一个位用于指示定时器当前是否正在计数(COUNTFLAG 位),可以通过读取这个位来确定定时器是否已经完成了一次计数循环。

(2)重载寄存器 STK_LOAD

这个寄存器用于设置滴答定时器的初始计数值。因为定时器是 24 位的,所以可以设置的最大值为 。通过设置这个寄存器的值,可以确定定时器每次计数循环的时长。例如,根据所选的时钟源频率和想要实现的定时周期,计算出相应的初始值并写入这个寄存器。

(3)当前值寄存器 STK_VAL

可以读取当前定时器计数器的剩余值。不过需要注意的是,在某些情况下读取这个寄存器的值可能会受到限制或者需要特殊的操作顺序。例如,在一些芯片中,可能需要先暂停定时器(通过清除 ENABLE 位)才能准确读取当前值。

二、HAL库滴答定时器初始化

使用 STM32CubeMX 生成的项目里,main函数会调用 HAL_Init();

进入该函数,可以看到如下调用 :

c 复制代码
  /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
  HAL_InitTick(TICK_INT_PRIORITY);

// 宏的值
#define  TICK_INT_PRIORITY            15U    /*!< tick interrupt priority (lowest by default)  */

这里即实现了滴答定时器的初始化。

三、SysTick实现微秒级延时

本实验实现微秒及翻转IO端口。

1. 使用 STM32CubeMX创建工程

GPIO里,配置PA8为输出,

SYS里,配置时间基准源为SysTick,Debug 为Serial Wire。

RCC,时钟源,把 High Speed Clock(HSE) 选择: Crystal/Ceramic Resonator。

然后把时钟配置 HCLK设置为72MHz:

回车,提示窗口选择OK,系统自动把PLL设置好。

打开生成的项目。

2. 代码实现

c 复制代码
/**
 * @brief 微秒级延时
 * @param us
 */
void my_delay_us(uint32_t us) {
    uint32_t ticks_per_us = SystemCoreClock / 1000000;
    uint32_t start_ticks = SysTick->VAL;
    uint32_t delay_ticks = us * ticks_per_us;
    if (delay_ticks > start_ticks) {
        delay_ticks = delay_ticks - start_ticks + SysTick->LOAD;
    } else {
        delay_ticks = delay_ticks + SysTick->LOAD - start_ticks;
    }
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
    while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0) {
        if ((SysTick->LOAD - SysTick->VAL) > delay_ticks) {
            break;
        }
    }
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}

/**
 * @brief 毫秒级延时
 * @param ms
 */
void my_delay_ms(uint32_t ms) {
    while (ms--) {
        my_delay_us(1000);
    }
}

main函数:

c 复制代码
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();
    /* USER CODE BEGIN 2 */

    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1) {
        /* USER CODE END WHILE */
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8);
        my_delay_ms(1);
        /* USER CODE BEGIN 3 */
    }
    /* USER CODE END 3 */
}

在PA8观察输出的波形:

相关推荐
雾岛听风眠几秒前
运放学习笔记
笔记·学习
肥大毛几秒前
C++入门学习---结构体
开发语言·c++·学习
likeshop 好像科技3 分钟前
新手学习AI智能体Agent逻辑设计的指引
人工智能·学习·开源·github
副露のmagic30 分钟前
更弱智的算法学习 day11
学习
czhaii43 分钟前
并口LCD1602用DMA刷屏
单片机·嵌入式硬件·硬件工程
冲,干,闯1 小时前
CH32V307以太网学习
学习
测试小张z1 小时前
软考自学两个月通过系统集成项目管理师的考试
学习·学习方法
硅农深芯1 小时前
MCU的启动流程你了解么?
单片机·嵌入式硬件·硬件工程
‿hhh1 小时前
学习笔记整理(部分)
java·开发语言·笔记·学习·mvc
Ki13812 小时前
我的AI学习小结:从入门到放弃
人工智能·学习