将 STM32F103 工程转换为 STM32F4 工程的详细步骤:
一、硬件配置方面
-
时钟配置
- STM32F103 时钟配置:STM32F103 的时钟源主要有内部高速时钟(HSI)和外部高速时钟(HSE)等。通过配置 RCC(复位和时钟控制)相关寄存器来设置系统时钟。例如,要使用外部 8MHz 晶振作为 HSE,并通过 PLL(锁相环)倍频到 72MHz 作为系统时钟,配置代码如下:
// 使能外部高速时钟(HSE)
RCC_HSEConfig(RCC_HSE_ON);
// 等待HSE稳定
while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
// 配置PLL,将HSE倍频到72MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
// 使能PLL
RCC_PLLCmd(ENABLE);
// 等待PLL稳定
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
// 选择PLL作为系统时钟源
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
// 等待系统时钟切换完成
while (RCC_GetSYSCLKSource()!= 0x08);
- STM32F4 时钟配置:STM32F4 的时钟系统更为复杂,有多个时钟源和不同的时钟域。通常使用 HSE 作为主时钟源,经过 PLL 倍频后得到系统时钟、USB 时钟等。以下是一个简单的配置示例(使用 HSE 和 PLL 得到 168MHz 的系统时钟):
// 使能HSE
RCC_HSEConfig(RCC_HSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
// 配置PLL
RCC_PLLConfig(RCC_PLLSource_HSE, 8, 336, 2, 7);
RCC_PLLCmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
// 设置系统时钟
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while (RCC_GetSYSCLKSource()!= 0x08);
-
引脚配置
- 参考数据手册:STM32F103 和 STM32F4 的引脚复用功能和默认功能不同,需要参考各自的数据手册。例如,在 F103 中,PA9 和 PA10 默认作为 USART1 的 TX 和 RX 引脚;而在 F4 中,这些引脚可能有不同的复用选项。
- 修改引脚初始化代码:根据新的硬件设计,修改 GPIO(通用输入 / 输出)引脚的初始化代码。例如,在 F103 中,如果要将 PB0 设置为推挽输出,配置代码如下:
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
- 在 F4 中,同样的功能可能需要这样配置:
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
二、软件库和驱动的修改
-
启动文件和内核相关文件
- 内核差异:STM32F103 基于 Cortex - M3 内核,STM32F4 基于 Cortex - M4 内核。这两种内核在指令集、中断处理等方面存在差异。
- 替换启动文件和内核库:将工程中的启动文件(.s 文件)替换为适合 STM32F4 的启动文件。同时,确保使用的编译器链接到正确的内核库。例如,在 Keil 开发环境中,把 F103 的启动文件
startup_stm32f10x_md.s
(假设是中等容量的 F103 芯片)替换为 F4 的启动文件startup_stm32f4xx.s
,并在编译器设置中确保链接到 Cortex - M4 的库文件。
-
外设驱动
- 外设差异:STM32F103 和 STM32F4 的外设在功能和寄存器设置上有不同。以定时器为例,F103 的基本定时器和 F4 的基本定时器在计数模式、中断产生机制等方面存在区别。
- 修改外设驱动代码:
- 串口驱动修改:在 F103 中,串口初始化代码可能如下:
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
- 在 F4 中,串口初始化需要根据 F4 的串口寄存器结构进行调整:
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
- 定时器:
- STM32F103 的定时器有基本定时器、通用定时器和高级定时器等,配置包括计数模式、预分频系数、自动重装载值等。
- STM32F4 的定时器在功能和配置上与 F103 类似,但在一些寄存器的位定义和操作顺序上有所不同。例如,在设置定时器中断时,中断使能的寄存器位可能不同。
- ADC(模数转换器):
- STM32F103 的 ADC 配置包括通道选择、采样时间、转换模式等。
- STM32F4 的 ADC 在这些配置参数的基础上,还增加了一些新的特性,如可配置的分辨率等。在转换工程时,需要根据 F4 的 ADC 特性进行配置。
-
中断处理
- 中断向量表:
- STM32F103 和 STM32F4 的中断向量表不同。在转换工程时,需要将中断服务程序的入口地址按照 F4 的中断向量表进行重新映射。
- 中断优先级:
- 两种芯片的中断优先级分组和设置方式存在差异。STM32F103 有 5 个优先级组,而 STM32F4 有 16 个优先级组。在转换工程时,需要根据 F4 的中断优先级设置规则重新设置中断优先级。
- 中断向量表:
三、编译和调试
-
编译选项设置
- 选择正确的芯片型号:在开发环境(如 Keil、IAR 等)的项目设置中,将目标芯片从 STM32F103 改为 STM32F4。例如,在 Keil 中,通过 Project - Options for Target - Device 选项,选择相应的 STM32F4 芯片型号。
- 调整编译优化选项:根据工程的实际情况,可能需要调整编译优化级别。一般来说,可以先使用默认的优化选项进行编译,如果出现问题再进行调整。
-
调试和测试
- 硬件调试器配置:如果使用硬件调试器(如 J - Link、ST - Link 等),需要确保调试器能够正确识别 STM32F4 芯片,并设置好调试接口(如 SWD 或 JTAG)。
- 功能测试:在完成转换和编译后,将程序下载到 STM32F4 的硬件开发板上进行调试和测试。从简单的功能模块(如 GPIO 输出、定时器计数等)开始测试,逐步验证整个系统的功能是否正常。如果发现问题,根据错误信息和调试结果对代码进行修改。