面向 STM32F103ZET6 的 Keil MDK-ARM / VS Code + EIDE 固件模板。工程基于 STM32F1 HAL,默认运行在 8MHz HSE × 9 = 72MHz SYSCLK,适合作为外设实验和板级驱动开发起点。
- MCU: STM32F103ZE,Cortex-M3,512KB Flash,64KB SRAM
- Keil 工程:
Projects/MDK-ARM/atk_f103.uvprojx - Keil target:
LED - 编译器: ARM Compiler 5 (
ARMCCV5.06 update 5) - 编译选项: C99、microLIB、
USE_HAL_DRIVER、STM32F103xE - 输出:
Output/atk_f103.axf,Keil 工程已开启 HEX 生成 - 下载: Keil 可用 ST-LINK / CMSIS-DAP;EIDE 默认 OpenOCD +
cmsis-dap+stm32f1x
├── Drivers/
│ ├── BSP/
│ │ ├── KEY/
│ │ ├── LCD/
│ │ ├── LED/
│ │ ├── OLED/
│ │ ├── TPAD/
│ │ └── bsp_test/
│ ├── CMSIS/ # CMSIS
│ ├── STM32F1xx_HAL_Driver/ # HAL 库
│ └── SYSTEM/ # 系统支持
├── Projects/MDK-ARM/ # 工程配置
│ ├── .vscode/
│ ├── .eide/
│ ├── atk_f103.uvprojx
│ └── atk_f103.code-workspace
├── User/ # 应用入口
├── keilkill.bat # 清理 Keil 产物
├── CLAUDE.md # AI 项目指引
└── README.md
无 Makefile/CMake。构建依赖 Keil MDK-ARM 或 VS Code EIDE。
- Keil: 打开
Projects/MDK-ARM/atk_f103.uvprojx,targetLED,Build。ST-LINK/CMSIS-DAP SWD 下载。 - VS Code + EIDE: 打开
Projects/MDK-ARM/atk_f103.code-workspace,运行 taskbuild→flash。下载配置见.eide/eide.yml(OpenOCD, cmsis-dap, stm32f1x)。 - 清理:
keilkill.bat(编辑前检查删除范围)。
main.c: 应用入口,负责 HAL、时钟、延时、串口、BSP 初始化。默认流程:HAL_Init()→sys_stm32_clock_init(RCC_PLL_MUL9)→delay_init(72)→usart_init(115200)→key_init()。主循环为按键菜单(见下方 BSP 测试节),printf通过 USART1 输出。stm32f1xx_hal_conf.h: HAL 模块开关。当前模板启用了 GPIO/RCC/PWR/CORTEX/TIM/UART/DMA/EXTI 等模块,也保留部分暂未使用模块供扩展。stm32f1xx_it.c: Cortex 异常入口和SysTick_Handler(),其中SysTick_Handler()调用HAL_IncTick()。
sys/: 向量表、全局中断、待机、软复位、系统时钟初始化。delay/: 直接操作 SysTick 实现 busy-waitdelay_us()/delay_ms(),并重写HAL_Delay()。usart/: USART1,PA9/PA10,支持 RX 中断和printf重定向,无半主机依赖。
BSP 模块采用固定模式:头文件放引脚、时钟使能宏和公开 API;.c 文件放 HAL GPIO/TIM 初始化与业务逻辑。
| 模块 | 主要 API | 说明 |
|---|---|---|
| KEY | key_init()、key_scan(mode) |
PE4/PE3/PE2 低有效,PA0 WK_UP 高有效,带 10ms 消抖 |
| LCD | lcd_init()(自动探测型号)、lcd_show_char()、lcd_draw_point()、lcd_read_point()、lcd_clear()、lcd_set_window() |
GPIOB 16 位 8080 并口,ILI9341/ST7789(lcd_ex.c 寄存器初始化),240×320 |
lcd_init() 返回 uint8_t:0 = 成功,1 = 未检测到支持型号。探测链(读时序满足手册 tRDL≥45ns / tRC≥160ns,数据总线读模式为上拉输入):
| 探测命令 | 期望值 | 结果 |
|---|---|---|
| 0xD3 | 00h/93h/41h → 0x9341 | ILI9341,执行 lcd_ex_ili9341_reginit() |
| 0xD3 | 0x7789/0x7799 | ST7789(部分模块对 0xD3 的响应) |
| 0xDA/DB/DC | 85h/85h/52h | ST7789(ST7789V 手册 RDID1/2/3),执行 lcd_ex_st7789_reginit() |
| 全部未命中 | — | 打印"未检测到支持的 LCD 型号",返回失败,不执行后续初始化 |
读路径不可用时(RD 未接或时序不满足,探测全为垃圾值),lcddev.readable = 0,lcd_read_point() 直接返回 0。
| LED | led_init()、LED0()、LED1()、LEDx_TOGGLE() | PE5 可用;PB5 被 LCD 数据总线占用,LED0 不可用 |
| TPAD | tpad_init(psc)、tpad_scan(mode) | PA1 + TIM5_CH2,RC 充放电输入捕获,初始化时采样基线 |
| OLED | oled_init()、oled_refresh_gram()、oled_show_string()、oled_show_num()、oled_clear()、OLED_CMD/OLED_DATA | PC0-PC7 8080 并口,128×64 帧缓冲 |
Drivers/BSP/bsp_test/bsp_test.c 为全部 BSP 模块提供全功能测试函数,由 main.c 按键菜单触发,结果经 USART1 printf 输出。
| 按键 | 测试函数 | 内容 |
|---|---|---|
| KEY0 (PE4) | bsp_test_led() |
LED1 亮灭/翻转;LED0 跳过 |
| KEY1 (PE3) | bsp_test_lcd() |
四色块/四字库/背景模式/ID 尺寸/读点回读/坐标扫描;型号探测失败即 FAIL 跳过,读路径不可用时回读标记 SKIP |
| KEY2 (PE2) | bsp_test_oled() |
字符/字符串/数字/像素点 + 整屏刷新 |
| WK_UP (PA0) | bsp_test_tpad() |
基线校准 + 触摸状态/测量值实时打印 |
菜单按键本身即 KEY 模块的功能测试(四键均可触发测试)。
测试接口跨模块冲突说明(bsp_test.c 顶部注释同步说明):
- LED0 (PB5) vs LCD 数据总线:GPIOB 全 16 位归 LCD,
bsp_test_led()仅测 LED1 (PE5)。 - OLED D6/D7 (PC6/PC7) vs LCD RD/WR (PC6/PC7):OLED 与 LCD 不能同时有效,先后运行测试会互相重配 PC6/7。每个测试函数开头自行初始化所属模块,任意顺序均安全;需要哪个模块就重跑对应测试即可恢复。
- TPAD 独占 TIM5_CH2,与其他模块无冲突。
- 在
Drivers/BSP/<MODULE>/新增.h/.c - 在头文件定义引脚、GPIO/TIM/USART 等时钟使能宏、公开 API
- 在
.c文件实现 HAL 初始化和外设逻辑 - 在
User/stm32f1xx_hal_conf.h启用需要的 HAL 模块 - 在
User/main.cinclude 对应头文件并调用初始化 - 将新增
.c同步加入:Projects/MDK-ARM/atk_f103.uvprojxProjects/MDK-ARM/.eide/eide.yml
工程源文件是显式枚举的,只把文件放进目录不会自动参与构建。
- 默认外部晶振为 8MHz,系统时钟初始化目标为 72MHz。
delay_init()会接管 SysTick 做忙等待延时;调用后不要假设 HAL timeout /HAL_GetTick()行为等同于 stock HAL。- TPAD 注释和参数默认假设 TIM5 时钟为 72MHz;常用
tpad_init(72)让定时器 tick 为 1us。 - LCD 8080 并口占用 GPIOB 全部 16 引脚做数据总线(PB5 被占,LED0 不可用),控制线为 PC6(RD)/PC7(WR)/PC8(RS)/PC9(CS)/PC10(BL),无硬件复位引脚,初始化使用软件复位。添加其他外设时注意引脚不冲突。
- 当前
main.c为按键菜单,仅初始化 KEY 并在需要时经测试函数初始化各 BSP 模块;模块初始化以测试函数开头自行执行为主。 - OLED 8080 并口占用了 PC0-PC7(数据)、PD3(RS)、PD6(CS)、PG13(RD)、PG14(WR)、PG15(RST),添加其他外设时注意引脚不冲突。
- OLED 使用双缓冲 +
oled_refresh_gram()模式,所有绘图操作先写内存缓冲区,再一次性刷入 SSD1306 显存。 - Keil / EIDE 工程文件容易产生格式噪声,改 XML/YAML 时尽量只改必要片段。
Drivers/CMSIS/和Drivers/STM32F1xx_HAL_Driver/是 vendor 代码,除非升级库版本,否则避免大范围修改。