在MDK5中新建STM32F4XX工程模板(基于固件库)

2023-11-17

0. 库函数和寄存器的区别

本质上是一样的。可以在库函数模板里面,直接操作寄存器,因为官方库相关头文件有寄存器定义。但是不能在寄存器模板调用库函数,因为没有引入库函数相关定义。

了解寄存器基本原理的目的是为了让我们对STM32相关知识有比较深入的理解,这样在开发过程中方可得心应手,游刃有余。底层代码配置出了问题需要调试的话,必须对寄存器有一定的了解才能找到问题,因为调试代码,底层只能查看寄存器相关配置。

1. 所用到的工具

开发环境:MDK5
固件库版本:V1.4(F4专用)

固件库的下载地址:https://download.csdn.net/download/mahoon411/13457727

2. 新建工程模板

  1. 首先建立一个文件夹为 Template。 这是工程的根目录文件夹。为了方便存放工程需要的一些其他文件,再新建下面 5 个子文件夹: CORE ,FWLIB,OBJ,SYSTEM,USER。
    在这里插入图片描述

至于这些文件夹名字,实际上是可以任取的,这样取名只是为了方便识别。

  1. 接下来, 打开 Keil,点击 Keil 的菜单: Project –>New Uvision Project ,然后将目录定位到刚才建立的文件夹 Template 之下的 USER 子目录, 同时,工程取名为 Template 之后点击保存, 我们的工程文件就都保存到 USER 文件夹下面。 操作过程如下图:
    在这里插入图片描述
    在这里插入图片描述
  2. 接下来会出现一个选择 Device 的界面,就是选择我们的芯片型号,这里我们定位到STMicroelectronics 下面的 STM32F407ZG。选择 STMicroelectronics→STM32F4 Series→STM32F407→STM32F407ZG(如果使用的是其他系列的芯片,选择相应的型号就可以了)。
    在这里插入图片描述

特别注意: 一定要提前安装好对应的器件 pack 之后,才会显示相应芯片的内容。器件的pack可以直接从官网下载。
在这里插入图片描述

点击 OK, MDK 会弹出 Manage Run-Time Environment 对话框
在这里插入图片描述
这是 MDK5 新增的一个功能,在这个界面,可以添加自己需要的组件,从而方便构建开发环境,不过这里不做介绍。直接点击 Cancel即可。
做完以上步骤,keil的project的界面应如下图所示。
在这里插入图片描述

  1. USER 目录下面包含 四 个文件,如下图所示。
    在这里插入图片描述
    这里说明一下, Template.uvprojx 是工程文件,非常关键,不能轻易删除, MDK51.4生成的工程文件是以.uvprojx 为后缀。
    Listings 和 Objects 文件夹是 MDK 自动生成的文件夹,用于存放编译过程产生的中间文件。这里,我们把两个文件夹删除,我们会在下一步骤中利用之前新建的 OBJ 文件夹,存放编译产生的中间文件。当然,我们不删除这两个文件夹也是没有关系的,只是我们不用它而已。
    在这里插入图片描述
  2. 下面我们要将官方的固件库包里的源码文件复制到我们的工程目录文件夹下面。
    打开官方固件库包,定位到我们之前准备好的固件库包的目录:\STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\Libraries\STM32F4xx_StdPeriph_Driver 下面,将目录下面的 src,inc 文件夹 copy 到我们刚才建立的 FWLib 文件夹下面。
    在这里插入图片描述
    在这里插入图片描述

src 存放的是固件库的.c 文件, inc 存放的是对应的.h 文件,每个外设对应一个.c 文件和一个.h 头文件。 文件内容如下图所示。
在这里插入图片描述
在这里插入图片描述

  1. 下面我们要将固件库包里面相关的启动文件复制到我们的工程目录 CORE 之下。
    打开官方固件库包。定位到目录\STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\Libraries\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm 下面,将文件 startup_stm32f40_41xxx.s 复制到 CORE 目录下面。
    在这里插入图片描述
    在这里插入图片描述

然后定位到目录\STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\Libraries\CMSIS\Includ , 将 里 面 的 四 个 头 文 件 :core_cm4.h、 core_cm4_simd.h、 core_cmFunc.h 以及 core_cmInstr.h 同样复制到 CORE 目录下面。

在这里插入图片描述
在这里插入图片描述

  1. 接下来我们要复制工程模板需要的一些其他头文件和源文件到我们工程。
    首先定位到目录:STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\Libraries\CMSIS\Device\ST\STM32F4xx\Include。将里面的 2 个头文件 stm32f4xx.h 和 system_stm32f4xx.h 复制到 USER 目录之下。 这两个头文件是STM32F4 工程非常关键的两个头文件。
    在这里插入图片描述
    在这里插入图片描述

然后进入目录\STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\Project\STM32F4xx_StdPeriph_Templates ,将目录下面的5个文件main.c ,stm32f4xx_conf.h,stm32f4xx_it.c,stm32f4xx_it.h,system_stm32f4xx.c 复制到 USER 目录下面。
在这里插入图片描述
在这里插入图片描述

  1. 前面 7 个步骤,我们将需要的固件库相关文件复制到了我们的工程目录下面。
    下面我们将这些文件加入我们的工程中去。
    打开keil,右键点击 Target1,选择 Manage Project Items,如下图所示。
    在这里插入图片描述

  2. Project Targets 一栏,我们将 Target 名字修改为 Template,然后在 Groups 一栏删掉一个 SourceGroup1,建立三个 Groups: USER,CORE,FWLIB。然后点击 OK,可以看到我们的 Target名字以及 Groups 情况如下图所示。
    在这里插入图片描述
    点击OK,project的情况如下图所示。
    在这里插入图片描述

  3. 下面我们往 Group 里面添加我们需要的文件。
    我们按照步骤 9 的方法, 右键点击点击Tempate, 选择 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)。 如
    下图所示:删除之后,点击OK。进入下一步
    在这里插入图片描述

这里需要说明一下,对于我们写代码,如果我们只用到了其中的某个外设,我们就可以不用添加没有用到的外设的库文件。例如我只用 GPIO,我可以只用添加 stm32f4xx_gpio.c 而其他的可以不用添加。这里我们全部添加进来是为了后面方便,不用每次添加,当然这样的坏处是工程太大,编译起来速度慢,用户可以自行选择。

  1. 用同样的方法,将 Groups 定位到 CORE 和 USER 下面,添加需要的文件。
    CORE 下面需要添加的文件为 startup_stm32f40_41xxx.s(注意,默认添加的时候文件类型为.c,也就是添加 startup_stm32f40_41xxx.s 启动文件的时候,你需要选择文件类型为 All files才能看得到这个文件 )。
    在这里插入图片描述
    在这里插入图片描述

USER 目录下面需要添加的文件为 main.c, stm32f4xx_it.c,system_stm32f4xx.c。 这样我们需要添加的文件已经添加到我们的工程中去了。
在这里插入图片描述

最后点击 OK,回到工程主界面。
在这里插入图片描述

  1. 接下来我们要在 MDK 里面设置头文件存放路径。
    也就是告诉 MDK 到那些目录下面去寻找包含了的头文件。这一步骤非常重要。 如果没有设置头文件路径,那么工程会出现报错:头文件路径找不到
    具体操作如下图, 5 步之后添加相应的头文件路径。
    在这里插入图片描述
    这里我们需要添加的头文件路径包括: \CORE, \USER\以及\FWLIB\inc。这里大家务必要仔细,固件库存放的头文件子目录是\FWLIB\inc,不是 FWLIB\src。
    在这里插入图片描述
    点击OK后,C/C++页面变化为。
    在这里插入图片描述
  2. 接下来对于 STM32F40 系列的工程,还需要添加一个全局宏定义标识符。
    添加方法是点击魔术棒之后,进入 C/C++选项卡,然后在 Define 输入框连输入:
    STM32F40_41xxx,USE_STDPERIPH_DRIVER
    注意这里是两个标识符 STM32F40_41xxx和 USE_STDPERIPH_DRIVER, 他们之间是用逗号隔开的。
    在这里插入图片描述
  3. 接下来我们要编译工程,在编译之前我们首先要选择编译中间文件编译后存放目录。
    方法是点击魔术棒 ,然后选择“Output”选项下面的“Select folder for objects…” ,然后选择目录为我们上面新建的 OBJ 目录。
    在这里插入图片描述
    在这里插入图片描述

然后将下方的三个选项框都勾上。Create HEX File 选项选上是要求编译之后生成 HEX 文件。Browse Information 选项选上是方便我们查看工程中的一些函数变量定义。
在这里插入图片描述

  1. 在编译之前,我们先把 main.c 文件里面的内容替换为如下内容:
#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);
	
	}
}

与此同时,要删掉stm32f4xx_it.c 文件中的第32行对main.h 头文件的引入以及 144 行 SysTick_Handler 函数内容。
在这里插入图片描述
在这里插入图片描述

  1. 下面我们点击编译按钮编译工程,可以看到工程编译通过没有任何错误和警告。
    在这里插入图片描述
    在这里插入图片描述
  2. 到这里,一个基于固件库 V1.4 的工程模板就建立完成,同时在工程的 OBJ 目录下面生成了对应的 hex 文件。
    在这里插入图片描述
  3. 这里还有个非常重要的关键点,就是系统时钟的配置,这里我们要修改 System_stm32f4xx.c 文件,把 PLL 第一级分频系数 M 修改为 8,这样达到主时钟频率为 168MHz。
    在这里插入图片描述
    PLL_M 这里我们要修改为 8,这样我们的系统时钟就是 168MHz。
    在这里插入图片描述
    同时,我们要在 stm32f4xx.h 里面修改外部时钟 HSE_VALUE 值为 8MHz, 因为我们的外部高速时钟用的晶振为 8M,具体修改方法如下:
    在这里插入图片描述
    如果编译之后,你的stm32f4xx_it.c文件的左边没有加号,请关闭keil后,重新打开工程就有了(这是keil的一个bug)。
    至此,工程模板就建立完成了。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在MDK5中新建STM32F4XX工程模板(基于固件库) 的相关文章

  • c项目makefile多重定义错误

    这个问题是一个对应于创建的repexthis问题 在我的嵌入式 C 项目中 我有两个独立的板 我想为每个板创建两个 c 文件 master c 和 Slave c 其中包含自己的特定main 功能 我使用 stm32cumbemx 生成带有
  • 在没有 IDE 的情况下如何使用 CMSIS?

    我正在使用 STM32F103C8T6 并想使用 CMSIS 这本质上只是寄存器定义 没有代码 让我的生活更轻松 同时仍保持在较低水平 问题是我不知道如何安装该库以便在命令行上使用 Makefile 使用 所有文档似乎都与特定于供应商的 I
  • 如何让printf在STM32F103上工作?

    我是 STM32F103 世界的新手 我有一个STM32F103的演示代码 我正在使用arm none eabi来编译它 我尝试了在谷歌上可以找到的内容 但到目前为止没有任何效果 我已经花了三天时间来解决这个问题 任何人都可以给我一个运行良
  • 138-基于stm32单片机汽车多功能仪表盘显示系统Proteus仿真+源程序

    资料编号 138 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 ds1302时钟 LED灯 蜂鸣器 电位器 制作一个基于stm32单片机汽车多功能仪表盘显示系统Proteus仿真 2 通过DHT1
  • STM32F4 通过软复位跳转到引导加载程序,无需 BOOT0 和 BOOT1 引脚

    我问这个问题是因为可以在这里找到类似问题的答案 通过应用程序跳转到 STM32 中的引导加载程序 即从用户闪存在引导模式下使用引导 0 和引导 1 引脚 用户 JF002 JF002回答 当我想跳转到引导加载程序时 我在其中一个备份寄存器中
  • STM32用一个定时器执行多任务写法

    文章目录 main c include stm32f4xx h uint32 t Power check times 电量检测周期 uint32 t RFID Init Check times RFID检测周期 int main Timer
  • 物联网网关

    物联网网关是 连接物联网设备和互联网的重要桥梁 它负责将物联网设备采集到的数据进行处理 存储和转发 使其能够与云端或其它设备进行通信 物联网网关的作用是实现物联网设备与云端的无缝连接和数据交互 物联网网关功能 数据采集 物联网网关可以从物联
  • 硬件基础-电容

    电容 本质 电容两端电压不能激变 所以可以起到稳定电压作用 充放电 电容量的大小 想使电容容量大 使用介电常数高的介质 增大极板间的面积 减小极板间的距离 品牌 国外 村田 muRata 松下 PANASONIC 三星 SAMSUNG 太诱
  • 擦除后无法写入闪存

    所以我不能在擦除后直接写入内部闪存 如果写操作之前没有擦除操作 那么我可以 有什么想法吗 编程函数返回 成功写入 值 但查看内存时 没有写入任何数据 这是代码 uint32 t pageAddress 0x08008000 uint16 t
  • 串口通讯第一次发送数据多了一字节

    先初始化IO再初始化串口 导致第一次发送时 多出一个字节数据 优化方案 先初始化串口再初始化IO 即可正常通讯
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • STM32的HAL中实现单按、长按和双按功能

    我正在尝试实现单击 双击和长按功能来执行不同的功能 到目前为止 我已经理解了单击和长按的逻辑 但我不知道如何检测双击 至于代码 我使用计数器实现了单击和长按 但代码仅停留在第一个 if 条件上 bool single press false
  • STM32F207 I2C 测试失败

    我正在使用 STM32F207 微控制器在 STM3220G EVAL 板上学习嵌入式开发 我尝试通过连接同一芯片上的两个 I2C2 和 I2C3 模块并发送 接收字符来测试 I2C 接口 这是我当前编写的代码 使用 mdk arm 5 i
  • 无法使用 OpenOCD 找到脚本文件

    我正在尝试按照本教程将 OpenOCD 与我的 ST 发现板一起使用 https japaric github io discovery README html https japaric github io discovery READM
  • 核心耦合内存在 STM32F4xx 上可执行吗?

    尝试从 STM32F429s CCM 运行代码 但每当我命中 CCM 中的第一条指令时 我总是会遇到硬故障 并且 IBUSERR 标志被设置 该指令有效且一致 STM32F4xx 是否可能不允许从 CCM 执行 数据访问效果良好 alios
  • STM32 上的 ADC 单次转换

    我正在研究 STM32 F103x 上的 ADC 编程 并从最简单的情况 单次转换开始 测量内部温度传感器 连接到 ADC1 的值 并使用 USART 将其发送到 COM 端口 目标似乎很明确 但是当我尝试将源代码下载到闪存时 它不会向 C
  • STM32 上的位置无关代码 - 指针

    我已成功在 STM32 上构建并运行位置无关的代码 向量表和 GOT 已修补 一切正常 但我对这样的代码有问题 double myAdd double x return x 0 1 double ptrmyAdd double myAdd
  • PWM DMA 到整个 GPIO

    我有一个 STM32F4 我想对一个已与掩码进行 或 运算的 GPIO 端口进行 PWM 处理 所以 也许我们想要 PWM0b00100010一段时间为 200khz 但随后 10khz 后 我们现在想要 PWM0b00010001 然后
  • 使用 STM32 USB 设备库将闪存作为大容量存储设备

    我的板上有这个闪存IC 它连接到我的STM32F04 ARM处理器 处理器的USB端口可供用户使用 我希望我的闪存在通过 USB 连接到 PC 时被检测为存储设备 作为第一步 我在程序中将 USB 类定义为 MSC 效果很好 因为当我将主板
  • 使用 STM32F0 ADC 单独读取不同的输入

    STM32F072CBU 微控制器 我有多个 ADC 输入 并且希望单独读取它们 STMcubeMX 生成样板代码 假设我希望按顺序读取所有输入 但我无法弄清楚如何纠正这个问题 这篇博文 http blog koepi info 2015

随机推荐

  • 进程和线程的区别

    简介 进程 进程是计算机中运行程序的实例 是操作系统进行资源分配和调度的基本单位 每个进程都有独立的内存空间和系统资源 不同进程之间相互独立 彼此不能直接访问对方的内存 进程之间的通信需要通过操作系统提供的特定机制 如管道 共享内存等 个人
  • nginx 之安全配置

    前言 看官网官网 一 控制并发连接数 1 在默认发布目录新建一个目录并保存一张图片 传送文件到server1 打开浏览器就能看到图片 2 测试 查看日至情况 cat usr local nginx logs access log http状
  • 时间计时android程序,Android实现时间倒计时功能

    本文实例为大家分享了Android实现时间倒计时功能展示的具体代码 供大家参考 具体内容如下 效果展示 MainActivity 主页面代码 public class MainActivity extends Activity privat
  • Nacos配置中心落地与实践

    一 背景 目前 我们公司各团队配置中心使用各异 电商使用的是 Spring Cloud Config 支付使用的是 Apollo APP 团队使用的是 Apollo Nacos 为了更好地应对公司业务的发展 统一基础设施技术栈必不可少 图片
  • ChatGPT-Next-Web:Vercel 和 Cloudflare 的快速部署

    项目地址 GitHub Chanzhaoyu chatgpt web 用 Express 和 Vue3 搭建的同时支持 openAI Key 和 网页 accessToken 的 ChatGPT 演示网页 依赖安装 1 安装node cur
  • BI-SQL丨行列转换

    行列转换 行列转换 在SQL Server中属于常见的基本操作 无论是搭建数仓 还是通过PowerBI进行数据分析 我们总会接触到各式各样的数据源 而在这些数据源中 除了标准的大型数仓外 我们很少能够拿到标准规范的数据表结构 接触最多的 往
  • 最熟悉的陌生人:ListView 中的观察者模式

    http blog csdn net u011240877 article details 52683711 RecyclerView 得宠之前 ListView 可以说是我们用的最多的组件 之前一直没有好好看看它的源码 知其然不知其所以然
  • tar分卷压缩解压

    1 使用tar分卷压缩 格式 tar cvzf filedir split d b 50m filename 样例 tar cvzf dir split d b 10m dirname tar gz 将 dir 打包 并切割为 10m 的包
  • python——*和**

    python中 和 的使用分两个方面 一个是计算 另一个是参数传递过程中元素的打包和解包 计算中的运用 和 在python中最常见的作用分别是 相乘 和 乘幂 如下 gt gt gt a 2 gt gt gt b 3 gt gt gt c
  • 20个Android游戏源码,…

    原文地址 分享20个Android游戏源码 希望大家喜欢哈 作者 我算哪根葱 分享20个 Android 游戏源码 希望大家喜欢哈 http www apkbus com android 21834 1 1 html Android 疯狂足
  • 凸优化学习(三)——凸函数

    注意 本文内容来自于吴恩达老师cs229课堂笔记的中文翻译项目 https github com Kivy CN Stanford CS 229 CN 中的凸优化部分的内容进行翻译学习 3 凸函数 凸优化的一个核心要素是凸函数的概念 定义
  • vtm配置以及编码示例

    vtm配置以及编码示例 下载VTM源码 网址 VTM源码 选择对应的版本下载 版本从2 0到最新的版本 1 0版本的VTM需要使用HM的工具svn下载 VTM 1 0源码地址 https jvet hhi fraunhofer de svn
  • STM32F4 IAP 跳转 APP问题

    1 概念 IAP 的作用 网上其他资料已经有很多介绍了 这里放一个链接 不进行深入的介绍 本文的关注重点是Bootloader在跳转APP程序中出现的问题 IAP的实现原理讲解以及中断向量表的偏移 2 程序 本人主要做应用层的开发 所有Bo
  • python--判断奇数偶数

    num int input 输入一个数 if num 2 0 print 0 是偶数 format num else print 0 是奇数 format num 优化 while True try num int input 输入一个整数
  • TS中类型推论、类型别名和never类型

    一 类型推论 TypeScript会在没有明确的指定类型的时候推测出一个类型 这就是类型推论 如果没声明变量 没定义类型 也没赋值 这时候TS会推断成any类型可以进行任何操作 let str str 456 str null 二 类型别名
  • 5分钟 教你搭建个人博客

    链接 https www jianshu com p 4eaddcbe4d12 五分钟倒数已经可以计时了 三步完成免费个人博客搭建 这是一篇小白也能看懂的文章 本文主要针对mac OS Windows 除了软件安装方式和命令有些区别 装了g
  • C++11之初始化列表

    系列文章 C 11之正则表达式 regex match regex search regex replace C 11之线程库 Thread Mutex atomic lock guard 同步 C 11之智能指针 unique ptr s
  • redis部署锦集,redis部署都在这了。

    大数据之Redis Redis各种部署方案和实现 Redis在大数据技术的发展中主要是用来作为中间值存储 快速计算 管道等工具使用 今天先给大家介绍一下关于Redis的部署方案和实现 其原理和应用将会在下一期和大家分享 直接上干货 一 单机
  • 从零起步:学习数据结构的完整路径

    文章目录 1 基础概念和前置知识 2 线性数据结构 3 栈和队列 4 树结构 5 图结构 6 散列表和哈希表 7 高级数据结构 8 复杂性分析和算法设计 9 实践和项目 10 继续学习和深入 11 学习资源 12 练习和实践 欢迎来到数据结
  • 在MDK5中新建STM32F4XX工程模板(基于固件库)

    0 库函数和寄存器的区别 本质上是一样的 可以在库函数模板里面 直接操作寄存器 因为官方库相关头文件有寄存器定义 但是不能在寄存器模板调用库函数 因为没有引入库函数相关定义 了解寄存器基本原理的目的是为了让我们对STM32相关知识有比较深入