前言
要验证一些基础代码,为了防止由于现有工程实现有问题。
想从自己干净的工程开始验证。
先从头搭一个STM34F407固件库模板。
已经搭好的STM32F407固件库模板下载点
project_template_stm32f407_stdlib.7z
试验
从0开始搭建一个STM34F4的固件库模板
参照STM32F4开发指南-库函数版本_V1.1.pdf
自己从头作一遍, 会感觉自己的工程模板很干净, 没有未知和多余的东西
ST官方固件库下载首页
https://www.st.com/en/embedded-software/stm32-standard-peripheral-libraries.html
从ST官方下载了STM32F4的固件库(https://www.st.com/en/embedded-software/stsw-stm32065.html), 当前版本为1.8.0
保存为 STM32F4xx_DSP_StdPeriph_Lib_V1.8.0_from_ST.7z
新建MDK工程
MDK代码页选为UTF8
在MDK中选MCU为STM32F407VGTx, 晶振为8MHZ, 这步要根据自己板子来
不勾选 "Use MicroLIB"
加入编译宏选项 STM32F40_41xxx, USE_STDPERIPH_DRIVER, USE_FULL_ASSERT
在"Flash Download"页面中,选上"Reset and Run", 这样程序下载完,就可以自动运行
在工程下新建4个文件夹:
/DOC 文档
/USER 用户代码
/BSP 板级驱动
/FWLIB ST固件库
/CORE CM4接口定义和启动文件
设置头文件路径
.\CORE;.\FWLIB;.\FWLIB\inc;.\FWLIB\src;.\BSP;.\USER
将ST固件库的文件拷贝进自己的模板工程
STM32F4xx_DSP_StdPeriph_Lib_V1.8.0_from_ST\Libraries\STM32F4xx_StdPeriph_Driver\inc\* => /FWLIB
STM32F4xx_DSP_StdPeriph_Lib_V1.8.0_from_ST\Libraries\STM32F4xx_StdPeriph_Driver\src\* => /FWLIB
\Libraries\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm\startup_stm32f40_41xxx.s => /CORE
\Libraries\CMSIS\Include\core_cm4.h => /CORE
\Libraries\CMSIS\Include\core_cmSimd.h => /CORE
\Libraries\CMSIS\Include\core_cmFunc.h => /CORE
\Libraries\CMSIS\Include\core_cmInstr.h => /CORE
\Libraries\CMSIS\Device\ST\STM32F4xx\Include\* => /USER
\Project\STM32F4xx_StdPeriph_Templates\main.c => /USER
\Project\STM32F4xx_StdPeriph_Templates\main.h => /USER
\Project\STM32F4xx_StdPeriph_Templates\stm32f4xx_conf.h => /USER
\Project\STM32F4xx_StdPeriph_Templates\stm32f4xx_it.c => /USER
\Project\STM32F4xx_StdPeriph_Templates\stm32f4xx_it.h => /USER
\Project\STM32F4xx_StdPeriph_Templates\system_stm32f4xx.c => /USER
将加入的文件全部填入工程管理组
工程管理组也建立5个文件夹 /DOC, /USER, /BSP, /FWLIB, /CORE
将实体文件夹的内容添加到工程管理组的文件夹中
将stm32f4xx_fmc.c从工程管理组/FWLIB中删掉, 这个文件不是F407用的, 否则编译不过
修改固件库
将main函数的官方模板实现挪到新建的函数中备用参考, 现在main函数为空
// @note ls main_example_by_st() // ST官方的例子
修改时钟配置, 使外部告诉时钟为8MHZ(这个要看自己板子的外部晶振的实际情况)
修改点在MDK中搜索就行
// @note ls PLL_M 要修改成8, 才能让系统时钟变成168MHZ
#define PLL_M 8 /*25*/
// @note ls 晶振频率改为8MHZ
// #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
#define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
// @note ls 设置系统时钟, 否则进不了SysTick_Handler
在main函数中设置系统时钟
RCC_GetClocksFreq(&RCC_Clocks); // 必须调用RCC_GetClocksFreq(), 才能载入前面修改过的时钟参数
SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000); // @note ls 168000000(168MHZ) / 1000(微秒) = 1ms 发生一次tick
// 现在系统tick才是1ms发生一次
void SysTick_Handler(void)
{
// @note ls 一个tick = 1ms
TimingDelay_Decrement();
}
// 根据自己的板子硬件情况, 随便初始化一个可以看出效果的硬件, 看看效果
// LED初始化
void bsp_Init_led(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); // 使能GPIOE的时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // 输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // 上拉
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; // 高速GPIO
GPIO_Init(GPIOE,&GPIO_InitStructure);
// 让LED灯初始化成灭的状态
GPIO_ResetBits(GPIOE, GPIO_Pin_3); // GPIOE3,10高电平
}
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
// @note ls main_example_by_st() // ST官方的例子
// @note ls 设置系统时钟, 否则进不了SysTick_Handler
RCC_GetClocksFreq(&RCC_Clocks);
SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000); // @note ls 168000000(168MHZ) / 1000(微秒) = 1ms 发生一次tick
bsp_Init_led(); // 初始化外设 - LED指示灯
// 验证一下固件库是否能正常运行
do {
delay_ms(500);
GPIO_ToggleBits(GPIOE, GPIO_Pin_3); // 将指示灯状态翻转, 形成闪烁
} while (1);
}
// 现在可以看到自己板子上的LED指示灯亮灭的时间总和为1S, 对着PC机的闹钟, 数LED亮灭60次,正好是1S
// STM32F4固件库的从零开始的移植完成
// 如果要加入后续的板级驱动, 就在/BSP文件夹和/BSP管理组中加
// END