如何学习用裸机汇编实现STM32F103C8T6的PC13引脚LED闪烁?
裸机汇编实现STM32F103C8T6 PC13 LED闪烁:从手册查阅到代码实现
先帮你把几个核心困惑捋清楚,再一步步教你怎么从官方文档挖信息,最后给你可运行的汇编代码——完全不用怕那些所谓的“魔法地址”,本质都是有章可循的硬件寄存器操作。
为什么必须配置外设时钟?
Arduino框架把所有底层脏活都替你做了,包括默认开启常用外设的时钟,但STM32的硬件设计逻辑是所有外设默认关闭时钟,目的是最大限度省电。你要操作GPIOC,必须先给它“通电”(打开时钟),否则所有对GPIOC寄存器的操作都是无效的。这不是多余步骤,是嵌入式硬件的基本设计规则。
所谓“魔法地址/数字”到底是什么?
这些就是STM32内存映射里的硬件寄存器地址和配置值,一点都不“魔法”——只是你还没学会从官方手册里找它们而已。比如:
- GPIOC的所有寄存器都映射到固定内存区间(从
0x40011000开始) - 控制GPIOC时钟的寄存器是RCC_APB2ENR,地址
0x40021018,其中第4位对应GPIOC的时钟使能,写(1 << 4)就能打开它
怎么从官方手册里找需要的信息?
你提到的RM0008(STM32F1参考手册)和PM0056(Cortex-M3编程手册)是核心,不用全看,按需求查对应章节:
1. 确定外设时钟配置:查RCC章节
打开RM0008,翻到第6章 复位和时钟控制(RCC):
- 找到「APB2外设时钟使能寄存器(RCC_APB2ENR)」,看位定义:第4位
IOPCEN就是GPIOC的时钟使能位,置1开启时钟。 - 记下寄存器地址:
0x40021018(手册会给每个寄存器的偏移地址,加上RCC基地址0x40021000就能算出)
2. 配置GPIO引脚:查GPIO章节
翻到RM0008的第9章 通用和复用功能I/O(GPIO和AFIO):
- PC13属于GPIOC的高8位引脚(引脚8-15对应CRH寄存器,0-7对应CRL),所以要配置
GPIOC_CRH寄存器(地址0x40011004,GPIOC基地址0x40011000加偏移0x04) - 每个引脚占4位,PC13对应第20-23位(计算方式:
(13-8)*4 = 20)。要配置成通用推挽输出,4位配置值是0x02(二进制0010:CNF位设为00表示推挽输出,MODE位设为10表示2MHz输出速度) - 控制引脚电平的是
GPIOC_ODR寄存器(地址0x4001100C),第13位对应PC13:置1是高电平(LED灭,因为STM32F1的PC13 LED是低电平点亮),置0是低电平(LED亮)
3. 汇编编程基础:查Cortex-M3编程手册
打开PM0056,看第8章 汇编语言编程,了解ARM Cortex-M3的汇编指令(比如LDR/STR访问内存,MOV/ORR操作寄存器,B跳转实现循环等),以及复位向量表的要求(必须先定义堆栈指针,再定义复位入口)
裸机汇编实现LED闪烁的代码示例
下面是基于ARM汇编的代码,直接可以烧录到STM32F103C8T6运行:
; 定义寄存器地址 RCC_APB2ENR EQU 0x40021018 GPIOC_CRH EQU 0x40011004 GPIOC_ODR EQU 0x4001100C ; 复位向量表 AREA RESET, DATA, READONLY EXPORT __Vectors __Vectors DCD 0x20001000 ; 堆栈指针(STM32F103C8T6有20KB RAM,栈顶设为0x20001000) DCD Reset_Handler ; 复位入口 ALIGN ; 复位处理函数 AREA CODE, READONLY Reset_Handler ; 1. 开启GPIOC时钟 LDR R0, =RCC_APB2ENR LDR R1, [R0] ORR R1, R1, #(1<<4) ; 置位IOPCEN位 STR R1, [R0] ; 2. 配置PC13为通用推挽输出(2MHz) LDR R0, =GPIOC_CRH LDR R1, [R0] BIC R1, R1, #0xF000000 ; 清除PC13对应的4位(第20-23位) ORR R1, R1, #0x2000000 ; 设置PC13为推挽输出,2MHz STR R1, [R0] ; 3. 循环翻转LED电平 Loop ; 点亮LED:PC13置0 LDR R0, =GPIOC_ODR LDR R1, [R0] BIC R1, R1, #(1<<13) STR R1, [R0] BL Delay ; 延时 ; 熄灭LED:PC13置1 LDR R0, =GPIOC_ODR LDR R1, [R0] ORR R1, R1, #(1<<13) STR R1, [R0] BL Delay ; 延时 B Loop ; 循环 ; 简单延时函数 Delay LDR R2, =0x3FFFFF Delay_Loop SUBS R2, R2, #1 BNE Delay_Loop BX LR END
总结学习路径
- 先从数据手册确认引脚对应关系(比如PC13属于哪个GPIO端口)
- 从参考手册的RCC章节找外设时钟使能方法
- 从参考手册的GPIO章节找引脚配置和电平控制的寄存器
- 从编程手册学习汇编指令和Cortex-M3的编程模型
- 动手写代码,逐步验证每一步(比如先只配置时钟和GPIO,看LED是否能点亮,再加循环翻转)
内容的提问来源于stack exchange,提问作者nalzok




