准备
Windows + protues
Ubuntu虚拟机:用于编译
绘制原理图选择stm32f103c8元件
stm32f10X参考手册
stm32f103c8t6.h:由st公司提供的寄存器定义头文件,主要是查看寄存器地址
时钟
define PERIPH_BASE ((uint32_t)0x40000000)
define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
define RCC_BASE (AHBPERIPH_BASE + 0x1000)
RCC_APB2ENR 偏移0x18:0x40021018 bit2=1(0b100=4)
GPIOA01属性
define PERIPH_BASE ((uint32_t)0x40000000)
define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
GPIOA_BASE 0x40010800
端口配置低寄存器(GPIOx_CRL) (x=A..E)
偏移地址:0x00
GPIOA_CRL 0x40010800
CNF0[3:2] 00:推挽输出模式
MODE0[1:0] 11:输出模式,最大速度50MHz
0b0011 = 0x3 [3:0] = 0b0011
GPIOA01输出
端口输出数据寄存器(GPIOx_ODR) (x=A..E)
地址偏移:0Ch(0x0c)
GPIOA_ODR 0x4001080C
bit0 = 1
向量表
主要是堆栈指针+Reset_Handler部分
.word
.word
.syntax unified
.cpu cortex-m3
.thumb
.section .text
.global Reset_Handler
.global _start
/* 向量表:放在 0x08000000 开头 */
.word 0x20005000 @ 初始栈顶:SRAM 末地址(20KB -> 0x20005000)
.word Reset_Handler @ 复位向量,指向 Reset_Handler(Thumb 地址)
.thumb_func
Reset_Handler:
_start:
/* 1. 使能 GPIOA 时钟:RCC_APB2ENR[2] = 1 */
ldr r0, =0x40021018 @ RCC_APB2ENR
ldr r1, [r0]
orr r1, r1, #0x4 @ IOPAEN = 1
str r1, [r0]
/* 2. 配置 PA0 为 50MHz 推挽输出:GPIOA_CRL[3:0] = 0b0011 */
ldr r0, =0x40010800 @ GPIOA_CRL
ldr r1, [r0]
bic r1, r1, #0x0F @ 清除 PA0 的 4 位
orr r1, r1, #0x03 @ MODE0=11 (50MHz), CNF0=00 (GP 推挽)
str r1, [r0]
/* 3. 置位 PA0 输出高电平:GPIOA_ODR[0] = 1 */
ldr r0, =0x4001080C @ GPIOA_ODR
ldr r1, [r0]
orr r1, r1, #0x1 @ PA0 = 1
str r1, [r0]
loop:
b loop @ 死循环,保持灯亮编译链接
使用Ubuntu16中apt包中的gcc-arm-none-eabi交叉编译工具链(支持mcu cortex-m3内核)
# 1) 编译成目标文件
arm-none-eabi-gcc -c -mcpu=cortex-m3 -mthumb led.s -o led.o
# 2) 链接到 STM32 Flash 起始地址 0x08000000
arm-none-eabi-ld -Ttext=0x08000000 led.o -o led.elf
# 3) 导出为 hex,给 Proteus 用
arm-none-eabi-objcopy -O ihex led.elf led.hex最终成功点亮小灯!