参考
:正点原子在哔站发布的视频以及《STM32F4开发指南》
第10讲 新建工程模板-基于固件库_哔哩哔哩_bilibili
【经验分享】STM32 新建基于STM32F40x 固件库的MDK5 工程 (stmicroelectronics.cn)
STM32官方固件库(标准固件库)下载及介绍_stm32固件库简介_csdndgq的博客-CSDN博客
说明一下,本来是完全按照原子哥的视频做的,但视频内容比较老,和更新后的网盘内容不一致,网盘里是关于HAL库的,而我要安装的是基础库的。所以有找了下面的两篇帖子。不过还是可以结合《STM32F4开发指南》看的。
打开《STM32F4开发指南》的3.3.2 新建工程模板。
1、建立一个文件夹为 Template。
这是工程的根目录文件夹。然后为了方便我们存放工程需要的一些其他文件,这里我们还新建下面 5 个子文 件夹:CORE ,FWLIB,OBJ,SYSTEM,USER。
2、打开 Keil
点击 Keil 的菜单:Project –>New Uvision Project ,然后将目录定位到刚
现在打开user目录可以看到
3、下面我们要将官方的固件库包里的源码文件复制到我们的工程目录文件夹下面。
打开官方固件库包,定位到我们之前准备好的固件库包的目录:\STM32F4xx_DSP_StdPeriph_Lib_V1.9.0\Libraries\STM32F4xx_StdPeriph_Driver下面, 将目录下面的 src,inc 文件夹 copy 到我们刚才建立的 FWLib 文件夹下面。 src 存放的是固件库的.c 文件,inc 存放的是对应的.h 文件。
4、下面我们要将固件库包里面相关的启动文件复制到我们的工程目录 CORE 之下。
定位到目录:
\Libraries\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm
找到“startup_stm32f40_41xxx”复制到 CORE 目录下面。
然后定位到目录:\Libraries\CMSIS\Include 将 里 面 的 四 个 头 文 件 :core_cm4.h 、core_cm4_simd.h 、core_cmFunc.h 以及 core_cmInstr.h 同样复制到 CORE 目录下面。现在看看我们的 CORE 文件夹下面的文件,
5、接下来我们要复制工程模板需要的一些其他头文件和源文件到我们工程。
目录:\Libraries\CMSIS\Device\ST\STM32F4xx\Include
将里面的 2 个头文件 stm32f4xx.h 和 system_stm32f4xx.h 复制到 USER 目录之下。这两个头文件是STM32F4 工程非常关键的两个头文件。
\Project\STM32F4xx_StdPeriph_Templates找到下 面 的 5 个 文 件 main.c , stm32f4xx_conf.h , stm32f4xx_it.c , stm32f4xx_it.h ,system_stm32f4xx.c 复制到 USER 目录下面。
6、将文件加入到工程
Project Targets一栏,我们将Target名字修改为Template,然后在Groups一栏删掉一个SourceGroup1,建立三个 Groups:USER,CORE,FWLIB。然后点击 OK。
添加FWLIB目录下的文件
右键点击点击Template,选择 Manage Project Items.然后选择需要添加文件的 Group,这里第一步我们选择 FWLIB,然后点击右边的 Add Files,定位到我们刚才建立的目录\FWLIB\src 下面,将里面所有的文件选中(Ctrl+A),然后点击 Add,然后 Close.可以看到 Files 列表下面包含我们添加的文件。
这里有个文件 stm32f4xx_fmc.c 比较特殊。这个文件是 STM32F42 和 STM32F43 系列才用到,所以我们这里要把它删掉(是 注意是 stm32f4xx_fmc.c 要删掉,不要删掉 stm32f4xx_fsmc.c)。
添加CORE目录下的文件
用同样的方法,将 Groups 定位到 CORE,添加需要的文件。这里我们的 CORE 下面需要添加的文件为 startup_stm32f40_41xxx.s( 注意,默认添加的时候文件类型为.c, 也就是添加 startup_stm32f40_41xxx.s 启动文件的时候,你需要选择文件类型为 All files件才能看得到这个文件),
添加USER目录下文件
USER 目录下面需要添加的文件为 main.c,stm32f4xx_it.c,system_stm32f4xx.c。 这样我们需要添加的文件已经添加到我们的工程去了,最后点击 OK,回到工程主界面。
添加完成后记得保存一下。
7、设置头文件路径
我们要在 MDK 里面设置头文件存放路径。也就是告诉 MDK 到那些目录下面去寻找包含了的头文件。这一步骤非常重要。 如果没有设置头文件路径,那么工程会出现报错头文件路径找不到。
这一步骤非常重要。 如果没有设置头文件路径,那么工程会出现报错头文件路径找不到!
这一步骤非常重要。 如果没有设置头文件路径,那么工程会出现报错头文件路径找不到!
这一步骤非常重要。 如果没有设置头文件路径,那么工程会出现报错头文件路径找不到!
(我第一次就是因为这里错了,查错查好久)
下图这种形式不对可以看后面的。要点那三个点进去后选择具体的文件夹后确认保存!
这里我们需要添加的头文件路径包括:\CORE, \USER\以及\FWLIB\inc。这里大家务必要仔细,固件库存放的头文件子目录是\FWLIB\inc,不是 FWLIB\src。
点进去选择!
8、添加宏定义
接下来对于 STM32F40 系列的工程,还需要添加一个全局宏定义标识符。添加方法是点击魔术棒之后,进入 C/C++选项卡,然后在 Define 输入框连输入:STM32F40_41xxx,USE_STDPERIPH_DRIVER。注意这里是两个标识符 STM32F40_41xxx和USE_STDPERIPH_DRIVER, 他们之间是用逗号隔开的,请大家注意。
9、设置中间文件存放路径
然后选择“Output”选项下面的“Select folder for objects…”,然后选择目录为我们上面的 新建的 OBJ 目录。同时将下方的三个选项框都勾上。
Create HEX File 选项选上是要求编译之后生成 HEX 文件。Browse Information 选项选上是方便我们查看工程中的一些函数变量定义。
10、修改主函数代码
#include "stm32f4xx.h"
void Delay(__IO uint32_t nCount);
void Delay(__IO uint32_t nCount)
{
while(nCount--){}
}
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
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_UP;
GPIO_Init(GPIOF, &GPIO_InitStructure);
while(1)
{
GPIO_SetBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10);
Delay(0x7FFFFF);
GPIO_ResetBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10);
Delay(0x7FFFFF);
}
}
与此将 同时,我们要将 USER 分组下面的 stm32f4xx_it.c 。 文件内容清空。的 或者删掉其中的 32 行对main.h 头文件的引入以及 144 行 行 SysTick_Handler 函数内容.
编译工程
可以看到工程编译通过没有任何错误和警告.
但是我在这一步的时候突然报出来很多警告,找了好半天。最终发现在文件路径设置上出现了问题。参考解决办法cannot open source input file “core_cm4.h”解决方法_cannot open source input file "core_cm4.h_我吃我家大米的博客-CSDN博客
正确的是这样
点进去找到所在位置后,点击选择文件夹。
之后ok保存。再次编译不会出错。还有一点是
这里的版本选择要是5.不然还是会报错。
此时我的代码是这样的
编译成功但是代码有红线,解决办法,博主讲的很清楚,跟着做就行。KEIL5出现红色波浪线的解决办法_keil红色波浪线_尐唲靌呗的博客-CSDN博客
到这里,一个基于固件库 V1.8 的工程模板就建立完成,同时在工程的 OBJ 目录下面生成了对应的 hex 文件
系统时钟配置
我们要修改 System_stm32f4xx.c 文件,把 PLL 第一级分频系数 M 修改为 8,这样达到主时钟频率为 168MHz。
因为文件是只读的,所以要在keil外部修改。可以打开Visualstdio修改。
添加其他功能函数
delay.C
#include "stm32f4xx.h"
/**
* @brief 微秒级延时
* @param xus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 168 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
/**
* @brief 毫秒级延时
* @param xms 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_ms(uint32_t xms)
{
while(xms--)
{
Delay_us(1000);
}
}
/**
* @brief 秒级延时
* @param xs 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_s(uint32_t xs)
{
while(xs--)
{
Delay_ms(1000);
}
}
delay.h
#ifndef __DELAY_H
#define __DELAY_H
void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);
#endif
LED.C
#include "stm32f4xx.h" // Device header
// * 实验平台:正点原子 M144Z-M4最小系统板STM32F407版
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
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_UP;
GPIO_Init(GPIOF, &GPIO_InitStructure);
}
void LED0_ON(void)
{
GPIO_SetBits(GPIOF,GPIO_Pin_10);
}
void LED0_OFF(void)
{
GPIO_ResetBits(GPIOF,GPIO_Pin_10);
}
void LED0_Turn(void)
{
if (GPIO_ReadOutputDataBit(GPIOF, GPIO_Pin_10) == 0)
{
GPIO_SetBits(GPIOF, GPIO_Pin_10);
}
else
{
GPIO_ResetBits(GPIOF, GPIO_Pin_10);
}
}
void LED1_ON(void)
{
GPIO_SetBits(GPIOF,GPIO_Pin_9);
}
void LED1_OFF(void)
{
GPIO_ResetBits(GPIOF,GPIO_Pin_9);
}
void LED1_Turn(void)
{
if (GPIO_ReadOutputDataBit(GPIOF, GPIO_Pin_9) == 0)
{
GPIO_SetBits(GPIOF, GPIO_Pin_9);
}
else
{
GPIO_ResetBits(GPIOF, GPIO_Pin_9);
}
}
LED.H
#ifndef __LED_H
#define __LED_H
void LED_Init(void);
void LED1_ON(void);
void LED1_OFF(void);
void LED1_Turn(void);
void LED0_ON(void);
void LED0_OFF(void);
void LED0_Turn(void);
#endif