嵌入式学习 | STM32 裸板驱动开发(Day03)超详细复习笔记(SysTick 系统定时器|位带 BitBand 操作|流水灯实战)
前言
本篇为 STM32 裸机开发第三天学习复盘,重点讲解两种延时方案对比、Cortex-M3 内核自带 SysTick 系统定时器完整原理与固件库 / 寄存器两种操作方式,同时详解 STM32 独有的 BitBand 位带机制,最后结合 SysTick 硬件延时 + 位带操作完成流水灯综合实战,区分标准库调用与底层寄存器手写两种开发思路,知识点附带原理推导、手册页码、寄存器地址、优缺点总结,适合零基础嵌入式入门复习。
一、两种延时方案对比
1. 软件空循环延时(for 循环空跑)
实现代码示例
uint32_t i;
for (i = 0; i < 10000000; i++);
存在两大核心缺陷
- 延时精度粗糙 循环次数没有统一标准,芯片主频、编译器优化等级都会改变实际延时时长,无精确计时标准,项目中不推荐使用。
- CPU 资源占用率 100% 空循环期间 CPU 持续不断执行自增判断,无法并行处理其他任务,阻塞式延时,多任务场景完全不适用。
2. 硬件延时:SysTick 系统定时器(推荐)
SysTick 是 Cortex-M3 内核内置专用 24 位递减定时器,独立于片上外设时钟,专门用于系统毫秒 / 秒级延时、操作系统心跳时钟,是 STM32 裸机开发标准硬件延时方案。
2.1 定时核心原理
(1)核心公式
定时时长定时器计数值定时器工作频率
(2)原理举例
- 定时器工作频率 = 1Hz:每 1 秒计数器减 1
- 配置计数值 = 10:完整递减一轮耗时 = 10 ÷ 1 = 10s
(3)SysTick 时钟来源(时钟树)
参考手册:《stm32f103RB.pdf》 P20 时钟树章节 本实验配置 SysTick 分频后工作频率为 9MHz
2.2 定时完成判断机制
- SysTick 计数器递减至 0 时,硬件自动置位标志位,同时触发内核异常中断;
- 内核自动跳转至预设的异常服务函数执行逻辑;
- 中断服务函数入口由 ARM 内核统一规定,在工程启动文件中绑定。
2.3 中断函数绑定关系(CMSIS 标准)
启动文件:startup_stm32f10x_md.s 文件内中断向量表预先定义 SysTick_Handler 函数地址,SysTick 定时溢出触发中断时,CPU 自动跳转该函数执行用户逻辑。
2.4 标准固件库配置 SysTick(库函数方式)
固件库提供两个核心 API 完成定时器初始化,分别位于不同库文件:
- 配置 SysTick 时钟分频
misc.c
// 选择HCLK八分频作为SysTick时钟源,得到9MHz工作频率
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
- 配置重装载计数值
core_cm3.h
// 装载9000000个计数脉冲,单次最大定时1s
SysTick_Config(9000000);
2.5 固件库操作 SysTick 固有弊端
- 单次最大定时限制 SysTick 为 24 位寄存器,最大计数值 = 224−1,配合 9MHz 时钟计算,单次最长定时约 1 秒; 若业务需要超过 1 秒延时,无法单次配置完成。
解决方案:多次分段定时叠加,循环多次调用 1s 定时实现长延时。
- 缺少关闭定时器的标准库函数 固件库仅提供初始化配置 API,无单独关闭 SysTick 的封装函数;如需启停控制,只能操作底层寄存器。
2.6 底层寄存器手动操作 SysTick(自由度更高)
若不依赖标准库,可直接操作内核 SysTick 三个专用寄存器,灵活配置时钟、计数值、启停、溢出判断。
| 寄存器名称 | 寄存器简称 | 内存地址 | 寄存器位数 | 核心功能 |
|---|---|---|---|---|
| SysTick 控制及状态寄存器 | CSR | 0xE000_E010 | 控制位 + 状态标志 | 定时器使能、中断开关、溢出标志读取 |
| SysTick 重装载数值寄存器 | RVR | 0xE000_E014 | 24 位 | 设置计数器初始装载值 |
| SysTick 当前数值寄存器 | CVR | 0xE000_E018 | 24 位 | 实时读取当前剩余计数值 |
关键寄存器位详解(CSR 寄存器 0xE000_E010)
- Bit0:定时器使能位
- 1:开启 SysTick 定时器,计数器开始递减
- 0:关闭 SysTick 定时器,计数器停止
- Bit16:定时溢出标志位(只读)
- 1:计数器递减至 0,定时时间到达
- 0:计数未完成,定时未结束
RVR 重装载寄存器说明
仅低 24 位有效,计数器递减到 0 时,硬件自动将 RVR 数值重新装载到 CVR,循环计数。
CVR 当前值寄存器说明
实时保存当前剩余计数值,软件可读取,写入任意值会自动清空寄存器。
二、BitBand 位带操作机制
2.1 传统 IO 位操作对比
- 51 单片机:支持直接位赋值,例如
PC2 = 1;,操作简洁直观; - 原生 STM32 寄存器操作:无直接位赋值语法,控制 PC2 引脚需要计算地址偏移、位掩码,写法繁琐:
*(volatile unsigned int *)(GPIOC_ODR_ADDR) |= (0x1 << 2);
BitBand 位带机制就是为了让 STM32 实现类似 51 单片机的直接位赋值语法,简化 IO 引脚操作。
2.2 位带核心工作原理
Cortex-M3 内核将内存分为位带区与位带别名区两块映射空间:
- 位带区:存储实际硬件寄存器 / SRAM 数据,每 1bit 真实硬件位;
- 位带别名区:32 位映射内存,位带区 1bit 对应 别名区 1 个 32 位完整字;
- 操作逻辑:修改别名区对应 32 位字的最低位,硬件自动同步修改位带区对应单 bit,实现单 bit 独立读写。
2.3 Cortex-M3 支持的位带映射范围
- 片上 SRAM 低 1MB 空间 → 对应位带别名区 32MB;
- 片上外设 低 1MB 空间 → 对应位带别名区 32MB;
2.4 GPIO 外设位带归属
查阅《stm32f103RB.pdf》内存映射章节可得:GPIOA/GPIOB/GPIOC/GPIOD 全部位于片上外设低 1MB 位带区,可以直接使用 BitBand 操作控制引脚电平。
三、综合实战需求:位带操作流水灯 + SysTick 硬件延时
3.1 功能技术点拆解
- GPIO 引脚电平控制:采用 BitBand 位带操作,直接引脚赋值,简化代码;
- 延时函数:底层操作 SysTick 寄存器实现硬件精准延时,摒弃粗糙 for 循环;
- 外设驱动:GPIO 端口输出控制 LED,循环切换引脚电平实现流水灯效果。
3.2 代码整体设计思路
- 封装 SysTick 底层寄存器延时函数,支持 ms/s 级精准延时;
- 封装 BitBand 引脚操作宏定义,实现
PA0 = 1;类简洁语法; - 主函数循环依次拉高 / 拉低不同 LED 引脚,配合 SysTick 延时切换灯光。
四、知识点总结梳理
- 延时方案
- 软件 for 循环:简单但精度差、占用 CPU,仅临时调试使用;
- SysTick 硬件定时器:内核自带、计时精准,分标准库封装操作、底层寄存器操作两种写法,存在单次最大 1s 定时限制;
- SysTick 寄存器 CSR 控制状态寄存器、RVR 重装载寄存器、CVR 当前值寄存器,三个寄存器配合完成定时启停、数值配置、溢出判断;
- BitBand 位带 Cortex-M3 专属内存映射机制,外设区 GPIO 可使用位带简化单引脚操作,实现类似 51 单片机直接位赋值;
- 实战组合 BitBand 快速控制 GPIO 引脚 + SysTick 硬件精准延时,是裸机 LED、蜂鸣器等输出外设最常用开发组合。
补充拓展(原文缺失内容补全)
拓展 1:SysTick 超过 1 秒延时实现思路
标准库单次最大装载值仅支持 1s 定时,长延时实现逻辑:
void Delay_s(uint32_t sec)
{
uint32_t i;
for(i = 0; i < sec; i++)
{
SysTick_Config(9000000); // 单次1s
while( !(SysTick->CTRL & (1 << 16)) ); // 等待溢出标志
SysTick->CTRL &= ~(1 << 0); // 关闭定时器
}
}
拓展 2:BitBand 通用计算宏(工程常用)
// 外设位带基地址
#define PERIPH_BITBAND_BASE 0x40000000
#define PERIPH_ALIAS_BASE 0x42000000
// 位带操作宏:addr=寄存器地址,bit=操作位号
#define BITBAND(addr, bit) *((volatile unsigned int *)(PERIPH_ALIAS_BASE + ((addr - PERIPH_BITBAND_BASE) << 5) + (bit << 2)))
使用示例:控制 PC2 输出高电平 BITBAND(GPIOC->ODR, 2) = 1;
拓展 3:标准库 SysTick 与寄存器操作优缺点对比
| 方式 | 优点 | 缺点 |
|---|---|---|
| 标准库函数 | 代码简洁、无需记忆寄存器地址、兼容性强 | 功能受限,无关闭接口、单次定时上限 1s |
| 底层寄存器操作 | 完全自由控制定时器、可随时启停、无功能限制 | 需要记忆寄存器地址与每一位功能,代码量更大 |
更多推荐



所有评论(0)