一、核心步骤概览

  1. 准备工具链:安装交叉编译器 arm-none-eabi-gcc。
  2. 获取固件库:从 ST 官网下载 STM32F1xx 标准外设库。
  3. 创建工程结构:在你的工作目录下建立清晰的文件夹。
  4. 拷贝文件:从固件库中复制所需的核心文件到你的工程中。
  5. 编写代码:创建main.c和链接脚本等关键文件。
  6. 编译与链接:使用make命令自动构建生成.elf、.hex和.bin文件。

详细操作步骤
第 1 步:安装交叉编译工具链
打开终端,执行以下命令安装:

sudo apt update
sudo apt install gcc-arm-none-eabi binutils-arm-none-eabi gdb-arm-none-eabi

第 2 步:创建工程目录结构
假设你的工程名为 my_stm32_project,在你的工作目录下执行:

mkdir -p my_stm32_project/{src,inc,lib/{CMSIS,SPL},ld,build}

这会创建一个包含源文件 (src)、头文件 (inc)、库文件 (lib) 等的清晰结构。

第 3 步:拷贝固件库文件
假设你已下载并解压了固件库,解压后的路径为 STM32F10x_StdPeriph_Lib_V3.5.0。请按以下清单将文件从固件库拷贝到你的工程中:

  1. 拷贝 CMSIS 核心文件
# 内核核心头文件
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/CoreSupport/core_cm3.h my_stm32_project/lib/CMSIS/
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/CoreSupport/core_cm3.c my_stm32_project/lib/CMSIS/

# 设备特定文件 (选择你的芯片系列,这里以F10x为例)
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/stm32f10x.h my_stm32_project/lib/CMSIS/
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c my_stm32_project/lib/CMSIS/

# 启动文件 (根据你的芯片容量选择,这里以中容量(MD)为例)
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/gcc_ride7/startup_stm32f10x_md.s my_stm32_project/lib/CMSIS/
  1. 拷贝 SPL 外设驱动文件
# SPL 核心头文件
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/STM32F10x_StdPeriph_Driver/inc/*.h my_stm32_project/lib/SPL/

# SPL 核心源文件
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/STM32F10x_StdPeriph_Driver/src/*.c my_stm32_project/lib/SPL/
  1. 拷贝用户配置模板
cp STM32F10x_StdPeriph_Lib_V3.5.0/Project/STM32F10x_StdPeriph_Template/stm32f10x_conf.h my_stm32_project/inc/
cp STM32F10x_StdPeriph_Lib_V3.5.0/Project/STM32F10x_StdPeriph_Template/stm32f10x_it.h my_stm32_project/inc/
cp STM32F10x_StdPeriph_Lib_V3.5.0/Project/STM32F10x_StdPeriph_Template/stm32f10x_it.c my_stm32_project/src/

第 4 步:创建关键工程文件

  1. 创建主程序文件 src/main.c
    这是一个简单的 LED 闪烁示例:
#include "stm32f10x.h" // 包含所有外设头文件

// 假设LED连接在PC13引脚上
#define LED_PIN GPIO_Pin_13
#define LED_PORT GPIOC

void delay_ms(volatile uint32_t count) {
    while(count--) { __NOP(); }
}

int main(void) {
    // 1. 使能GPIOC时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    // 2. 配置PC13为推挽输出
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = LED_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(LED_PORT, &GPIO_InitStructure);

    while (1) {
        // 3. 翻转LED状态
        GPIO_WriteReverse(LED_PORT, LED_PIN);
        delay_ms(500000); // 简单延时
    }
}
  1. 创建链接脚本 ld/stm32f103.ld
    这个文件定义了程序在 Flash 和 RAM 中的存储布局。
/* STM32F103C8T6链接脚本 (中低密度芯片) */
MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 64K  /* 64KB Flash */
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 20K  /* 20KB RAM */
}

_estack = 0x20005000; /* 栈顶地址 (20KB RAM的结束地址) */

SECTIONS
{
  /* 中断向量表 */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* 保留中断向量表 */
    . = ALIGN(4);
  } >FLASH

  /* 代码段 */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* 程序代码 */
    *(.text*)          /* 函数模板实例化代码 */
    *(.glue_7)         /* ARM与Thumb代码混合胶水代码 */
    *(.glue_7t)        /* ARM与Thumb代码混合胶水代码 */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* 代码段结束地址 */
  } >FLASH

  /* 初始化数据在Flash中的存储位置 */
  .data_init :
  {
    _sidata = .;       /* 初始化数据的起始地址 (关键符号,解决undefined reference错误) */
    *(.data_init)
  } >FLASH

  /* 初始化数据段 (加载到RAM) */
  .data : AT (_sidata)
  {
    . = ALIGN(4);
    _sdata = .;        /* 数据段起始地址 */
    *(.data)           /* 初始化数据 */
    *(.data*)          /* 初始化数据 */

    . = ALIGN(4);
    _edata = .;        /* 数据段结束地址 */
  } >RAM

  /* 未初始化数据段 */
  .bss :
  {
    . = ALIGN(4);
    _sbss = .;         /* BSS段起始地址 */
    *(.bss)            /* 未初始化数据 */
    *(.bss*)           /* 未初始化数据 */
    *(COMMON)          /* 公共未初始化数据 */

    . = ALIGN(4);
    _ebss = .;         /* BSS段结束地址 */
  } >RAM

  /* 用户堆空间 */
  .heap :
  {
    . = ALIGN(4);
    _heap_start = .;   /* 堆起始地址 */
    . += 2048;         /* 堆大小2KB,根据需要调整 */
    _heap_end = .;     /* 堆结束地址 */
    . = ALIGN(4);
  } >RAM
}
  1. 创建 Makefile
    这是自动化编译的核心。将下面的内容保存为 my_stm32_project/Makefile。
# --- 项目配置 ---
PROJECT = my_stm32_app
BUILD_DIR = build
SRC_DIR = src
LIB_DIR = lib
INC_DIR = inc
LD_DIR = ld

# --- 工具链配置 ---
CC = /opt/arm-none-eabi/bin/arm-none-eabi-gcc
OBJCOPY = /opt/arm-none-eabi/bin/arm-none-eabi-objcopy
OBJDUMP = /opt/arm-none-eabi/bin/arm-none-eabi-objdump
SIZE = /opt/arm-none-eabi/bin/arm-none-eabi-size

# --- 芯片与编译选项 ---
# 根据你的芯片型号修改,这里是STM32F103C8T6
CFLAGS = -mcpu=cortex-m3 -mthumb -msoft-float
CFLAGS += -DSTM32F10X_MD -DUSE_STDPERIPH_DRIVER
CFLAGS += -Wall -Wextra -O2 -g
CFLAGS += -ffunction-sections -fdata-sections

# --- 头文件路径 ---
INCLUDES = -I$(INC_DIR)
INCLUDES += -I$(LIB_DIR)/CMSIS
INCLUDES += -I$(LIB_DIR)/SPL

# --- 源文件列表 ---
# 1. 用户源文件
SRCS += $(wildcard $(SRC_DIR)/*.c)
# 2. CMSIS源文件
SRCS += $(LIB_DIR)/CMSIS/system_stm32f10x.c
# 3. SPL源文件
SRCS += $(wildcard $(LIB_DIR)/SPL/*.c)

# --- 目标文件 ---
OBJS = $(SRCS:%.c=$(BUILD_DIR)/%.o)
# 4. 启动文件 (汇编)
STARTUP_SRC = $(LIB_DIR)/CMSIS/startup_stm32f10x_md.s
STARTUP_OBJ = $(BUILD_DIR)/$(STARTUP_SRC:.s=.o)

# --- 链接选项 ---
LDFLAGS = -T$(LD_DIR)/stm32f103c8.ld
LDFLAGS += -mcpu=cortex-m3 -mthumb -msoft-float
LDFLAGS += -Wl,--gc-sections # 链接时去除未使用的代码和数据

# --- 目标 ---
all: $(BUILD_DIR)/$(PROJECT).elf $(BUILD_DIR)/$(PROJECT).hex $(BUILD_DIR)/$(PROJECT).bin

# 链接生成.elf文件
$(BUILD_DIR)/$(PROJECT).elf: $(OBJS) $(STARTUP_OBJ)
	@mkdir -p $(@D)
	$(CC) $(LDFLAGS) $^ -o $@
	$(SIZE) $@

# 生成.hex文件
$(BUILD_DIR)/$(PROJECT).hex: $(BUILD_DIR)/$(PROJECT).elf
	$(OBJCOPY) -O ihex $< $@

# 生成.bin文件
$(BUILD_DIR)/$(PROJECT).bin: $(BUILD_DIR)/$(PROJECT).elf
	$(OBJCOPY) -O binary $< $@

# 编译C文件
$(BUILD_DIR)/%.o: %.c
	@mkdir -p $(@D)
	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

# 编译汇编启动文件
$(BUILD_DIR)/%.o: %.s
	@mkdir -p $(@D)
	$(CC) $(CFLAGS) -c $< -o $@

# 清理
clean:
	rm -rf $(BUILD_DIR)

# 伪目标
.PHONY: all clean

第 5 步:编译工程
进入你的工程根目录 my_stm32_project,执行 make 命令:

cd my_stm32_project
make

如果一切顺利,你将在 build/ 目录下看到生成的 my_stm32_app.elf, my_stm32_app.hex, 和 my_stm32_app.bin 文件。

更多推荐