1. 移植背景与核心挑战最近接手一个从STM32F103VET6迁移到C8T6的电机控制项目原工程基于HAL库实现了直流有刷电机的PID控制。VET6作为大容量芯片512KB Flash移植到仅有128KB Flash的C8T6时就像把大象塞进冰箱——不仅要解决空间问题还得重新安排外设布局。实测发现两个芯片的外设资源差异比想象中更大定时器VET6有8个定时器而C8T6只有4个TIM1高级定时器TIM2/TIM3/TIM4通用定时器串口VET6支持5个USARTC8T6仅保留3个GPIO复用相同外设的默认引脚位置可能不同比如TIM1_CH1在VET6是PE9在C8T6是PA8最头疼的是HAL库的AFIO重映像功能。之前用VET6时为了布线方便开启了引脚重映射但移植到C8T6后发现模块死活不工作最后发现是新芯片的默认引脚配置与重映射冲突。这个问题让我在实验室熬到凌晨三点——建议各位在移植时第一个检查这个配置。2. 硬件适配关键步骤2.1 启动文件与设备宏定义更换启动文件是移植的第一步也是新手最容易翻车的地方。HAL库提供了四种启动文件对应不同容量的STM32startup_stm32f103x6.s // 小容量(16-32KB Flash) startup_stm32f103xb.s // 中容量(64-128KB Flash) ← C8T6选这个 startup_stm32f103xe.s // 大容量(256-512KB Flash) startup_stm32f103xg.s // 超大容量(768-1024KB Flash)除了替换启动文件还要修改工程预定义宏。在MDK的Options for Target → C/C选项卡中把STM32F103xE改为STM32F103xB。这个宏定义直接影响HAL库内部的条件编译如果忘记修改会导致寄存器地址错位。2.2 引脚重映射与AFIO配置原工程中PWM输出使用了TIM1的PE9和PE11引脚而C8T6的PE端口只有PE0-PE1可用。需要改为PA8和PA9// 原VET6配置 #define PWM_TIM_CH1_GPIO_PORT GPIOE #define PWM_TIM_CH1_PIN GPIO_PIN_9 // C8T6修改后 #define PWM_TIM_CH1_GPIO_PORT GPIOA #define PWM_TIM_CH1_PIN GPIO_PIN_8致命陷阱如果原工程开启了AFIO重映射比如调用了__HAL_AFIO_REMAP_TIM1_ENABLE()在新工程中必须关闭因为C8T6的TIM1通道默认就在PA8/PA9再开启重映射反而会导致信号无法输出。检查步骤如下在工程中搜索__HAL_AFIO_REMAP相关调用确认使用的引脚是否为该外设的默认引脚参考STM32F103C8T6数据手册如果是默认引脚注释掉所有重映射使能代码3. 外设资源调整策略3.1 定时器替代方案原工程使用TIM6作为基础定时器产生1ms时基但C8T6没有TIM6/TIM7。替代方案有两种方案A改用TIM2通用定时器// 修改定时器定义 #define BASIC_TIM TIM2 #define BASIC_TIM_CLK_ENABLE() __HAL_RCC_TIM2_CLK_ENABLE() #define BASIC_TIM_IRQn TIM2_IRQn #define BASIC_TIM_IRQHandler TIM2_IRQHandler方案B使用SysTick如果只是需要时基HAL库已经内置了SysTick配置可以直接调用HAL_Delay()。但注意SysTick中断优先级最高不适合执行复杂逻辑。3.2 串口资源调整当PA9被PWM占用时需要将调试串口从USART1切换到USART2// USART1 → USART2 #define DEBUG_USART USART2 #define DEBUG_USART_CLK_ENABLE() __HAL_RCC_USART2_CLK_ENABLE() #define DEBUG_USART_RX_GPIO_PORT GPIOA #define DEBUG_USART_RX_PIN GPIO_PIN_2 #define DEBUG_USART_TX_GPIO_PORT GPIOA #define DEBUG_USART_TX_PIN GPIO_PIN_3特别要注意中断向量的变化// 原中断服务函数名 void USART1_IRQHandler(void); // 修改后 void USART2_IRQHandler(void);4. 代码瘦身技巧4.1 删除冗余外设初始化C8T6没有DAC、CAN等外设需要删除相关代码在stm32f1xx_hal_conf.h中注释掉不用的外设宏// #define HAL_DAC_MODULE_ENABLED // #define HAL_CAN_MODULE_ENABLED移除工程中对应的.c/.h文件删除main函数中相关初始化代码4.2 优化HAL库占用空间通过以下配置减少HAL库体积// 在stm32f1xx_hal_conf.h中关闭不必要功能 #define HAL_MODULE_ENABLED // 只保留用到的模块 #define HAL_UART_MODULE_ENABLED #define HAL_TIM_MODULE_ENABLED #define USE_FULL_ASSERT 0 // 关闭断言检查 #define USE_RTOS 0 // 不使用RTOS5. 验证与调试心得移植完成后建议按以下顺序验证时钟检查用示波器测量主时钟输出MCO确认频率正确GPIO测试临时配置一个LED引脚测试高低电平输出PWM验证连接示波器查看波形占空比串口回环短接TX-RX测试自发自收遇到外设不工作时我的排查三板斧检查__HAL_RCC_xxx_CLK_ENABLE()是否调用确认GPIO模式设置正确输入/输出/复用功能查看AFIO重映射状态最后分享一个血泪教训C8T6的PB3/PB4默认是JTAG功能要作为普通GPIO使用需要先禁用JTAG__HAL_AFIO_REMAP_SWJ_NOJTAG(); // 保持SWD调试功能禁用JTAG移植完成后工程体积从原来的180KB压缩到98KB完美适配C8T6的128KB Flash。这种减肥过程虽然痛苦但对理解STM32外设架构帮助巨大——毕竟资源受限时才能真正学会精打细算。