STM32---MDK工程创建

news2025/1/21 18:57:13

本节我们带领大家学习如何新建一个寄存器库版本MDK的详细步骤;

由于51单片机的学习时,所涉及的寄存器很少,所以往往几个头文件、驱动文件就可以完成相关的功能,但是对于STM32来讲,涉及的寄存器、头文件等都很多,这也是为什么32的功能强大的原因,内容复杂才能功能庞大;所以在建立一个完整的工程时,也相对来说比较麻烦;

目录

一、新建寄存器版本MDK工程

1、新建工程文件夹

1.1 新建文件夹

1.2 复制相关文件 

2、新建工程框架 

3、添加文件

3.1设置工程名与分组名 

3.2添加启动文件

 3.3添加SYSTEM文件

4、魔术棒的设置 

5、添加 main.c,并编写代码

二、下载验证

1、实物连接

2、实验结果

一、新建寄存器版本MDK工程

        新建一个寄存器版本MDK工程,分为以下5个步骤,我们会分别详细介绍:

1、新建工程文件夹;2、新建工程框架、工程命名以及选择芯片;3、添加文件;4、魔术棒的设置;5、添加main.c文件;

1、新建工程文件夹

1.1 新建文件夹

        新建工程文件夹的作用是,由于32的一个工程涉及的.c、.h等功能文件很多如果把它们全部放在一个文件夹中,那很容易混乱,寻找哪个文件也很不方便;所以我们对于文件进行分类,把它按照不同为文件夹进行划分;就好比:51是我们小学时候,班级的同学比较少,不需要进行分班就能直接找到每一个同学;而32是等我们上到初中了,一个年级的同学就有很多,这时我们就需要对这些同学进行分班,按照班级寻找同学。建立文件夹的作用是一样的; 

我们对于32工程共分5个大的文件夹(如同5各班级),分别为:

文件夹名称作用
Drivers存放与硬件相关的驱动层文件
Middlewares存放正点原子提供的中间层组件文件和第三方中间层文件
Output存放工程编译输出文件
Projects存放 MDK 工程文件
User存放用户编写的代码,如 main.c

        建立完这5个文件夹后,现在里面都是空的,对于新手来说,这5个文件夹是用来干啥的?不知道!为什么要分为5个文件夹?不知道!当然,为什么这么划分,我确实也不知道,但是,官方能给出这样的划分,就说明有一定的原因,我们先按照这个来进行;

1.2 复制相关文件 

        工程根目录及其相关文件夹新建好以后,我们需要拷贝一些工程相关文件过来(主要是在 Drivers 文件夹里面),以便等下的新建工程需要。

        我们进入Drivers 文件夹,现在里面没有文件夹,我们先建立一个BSP 文件夹,用于存放正点原子提供的板级支持包驱动代码,如:LED、蜂鸣器、按键等。 本章我们暂时用不到该文件夹,不过可以先建好备用。

        然后是CMSIS文件夹,,用于存放 CMSIS 底层代码(ARM 和 ST 提供),如:启动文件(.s 文件)、 stm32f1xx.h 等各种头文件。该文件夹我们可以直接从 STM32CubeF1 固件包;因此我们根据实际情况,对其进行了大幅精简,精简后的 CMSIS 文件夹大小为 1MB 左右;

         最后是SYSTEM 文件夹,用于存放正点原子提供的系统级核心驱动代码,如:sys.c、delay.c 和 usart.c 等,方便大家快速搭建自己的工程。这里我给大家提供这个文件夹,大家对应着CV就行;

链接:https://pan.baidu.com/s/1_XOo_-zhc5Kwsu8Oo7uuIQ 
提取码:1022

        这样文件拷贝就完成了,总共在 Drivers 文件夹建立三个文件夹BSP 文件夹、CMSIS文件夹、SYSTEM 文件夹,其中BSP 文件夹为空文件夹,其余两个是复制粘贴得来的;

文件夹名称
BSP存放开发板板级支持包驱动代码,如各种外设驱动
CMSIS存放 CMSIS 底层代码,如启动文件(.s 文件)、stm32f1xx.h 等
SYSTEM存放正点原子系统级核心驱动代码,如 sys.c、delay.c 和 usart.c 等

        最后,我们还需要再Project文件中,新建一个MDK-ARM 文件夹,用于存放 MDK 的工程文件;

 

2、新建工程框架 

        新建工程框架就是新建一个工程,在这个工程中进行操作,也可以实现一个项目,一个功能等等;

        首先,打开 MDK 软件。然后点击 Project→New uVision Project;

         然后,设置工程的路径与名称;

        工程路径,就选择我们上节新建在Project中的文件MDK-ARM 文件夹;

        工程名字,自行选择,好记就行;

        保存后,下一步就是对应的芯片选型,此处对应自己的芯片选型即可;

在选好芯片后,界面会弹出这样的页面,我们不需要管,关闭即可;

然后就会在主界面显示这个内容,表明新建工程框架完成;

 

 最后,我们看一下,新建完工程后,在第一节中新建的文件夹中有什么变化呢?

         在开 MDK-ARM 文件夹,会看到 MDK 在该文件夹下自动创建了 2 个文件夹 (Listings 和 Objects)以及生成.uvprojx文件,这个文件就是新建的工程文件;而Listings文件夹,用于存放编译过程产生的链接列表等文件;Objects文件夹,用于存放编译过程产生的调试信息、.hex、预览、.lib 文件等;我们后面回把输出在 Listings 和 Objects 文件夹的内容,统一改为输出到 Output 文件夹,不按照他这个进行输出,此处需要注意一下下;

3、添加文件

         添加文件的作用是什么呢?我们在建立完一个工程后,需要用到这个工程,32的功能比较复杂,我们需要添加一些已经封装好的函数文件.c、.h等等;

         同样,由于涉及的文件较多,我们需要在工程内部,对所添加的文件进行分类;

注意:第一节是对文件在外部文件夹中分类,这节是对文件在工程内部进行分类

分为三个步骤:1、设置工程名与分组名(也就是分班);2、添加启动文件;3、添加SYSTEM源码;

3.1设置工程名与分组名 

        在 Project→Target 上右键,选择 Manage Project Items…(方法一)或在菜单栏点击品字形 红绿白图标(方法二)进入工程管理界面。

         在工程管理界面,我们可以执行设置工程名字(Project Targets)、分组名字(Groups)以 及添加每个分组的文件(Files)等操作。

        我们设置工程名字为:Template,并设置四个分组: Startup(存放启动文件)、User(存放 main.c 等用户代码)、Drivers/SYSTEM(存放系统级驱 动代码)、Readme(存放工程说明文件);

        这里我们只是新建了一个简单的工程,并没有添加 BSP、Middlewares 等分组,后面随着工 程复杂程度的增加,我们需要一步步添加对应的分组,使内外分组进行一致;

3.2添加启动文件

        启动文件(.s 文件)包含 STM32 的启动代码,其主要作用包括:1、堆栈(SP)的初始化; 2、初始化程序计数器(PC);3、设置向量表异常事件的入口地址;4、调用 main 函数等,是每 个工程必不可少的一个文件。当然这些话使看不懂的,不过没事,这会看不懂是很正常,后面学习到对应的章节,就能够看的懂了;

启动文件的位置就在,我们第一节赋值的CMSIS简介版文件夹中Drivers→CMSIS→Device→ST→STM32F1xx→ Source→Templates→arm 文件夹下,我们开发板使用的是 STM32F103ZET6,对应的启动文 件为:startup_stm32f103xe.s。

如何添加启动文件呢?

如上图所示,按照上面步骤进行添加,双击Startup文件夹,选择对应的外部文件夹,选择文件类型为ALL,选中文件,添加;

添加完后,为了更好的匹配寄存器版本代码,我们对 startup_stm32f103xe.s 做了 2 处修改:

1,我们用不到编译器的内存管理函数,为节省内存,将 Heap_Size 改成 0,源码如下: ;未用到编译器自带的内存管理(malloc,free 等),设置 Heap_Szie 为 0

Heap_Size EQU 0x00000000 

 2、寄存器代码不需要调用 SystemInit 函数,因此修改 Reset_Handler 函数,去掉 SystemInit 调用,源码如下:

 Reset_Handler PROC

EXPORT Reset_Handler     [WEAK]

IMPORT __main ;

寄存器版本代码,因为没有用到 SystemInit 函数,所以注释掉以下代码为防止报错!

;HAL 库版本代码,建议加上这里(提供 SystemInit 函数),以初始化 stm32 时钟等。 ;IMPORT SystemInit

;LDR R0, =SystemInit

;BLX R0 LDR R0, =__main

BX R0

ENDP

 3.3添加SYSTEM文件

         在我们工程里面,由Drivers/SYSTEM的文件夹,注意这个不是或的意思,这是Drivers文件夹下的文件夹SYSTEM,我们前面对SYSTEM进行了复制(就是百度网盘中的文件),这会需要添加进来。如果之前没拷贝,是找不到这些源码的。

4、魔术棒的设置 

        为避免编写代码和编译报错,我们需要通过魔术棒对 MDK 工程进行相关设置。在 MDK 主界面,(魔术棒图标,即 Options for Target 按钮);

Target 选项卡设置使用编译器的版本,外部晶振
Output 选项卡设置输出文件夹、生成.hex文件、输出浏览信息
Listing 选项卡设置Listing输出文件
C/C++选项卡设置全局宏定义,优化等级
Debug 选项卡设置使用的仿真器,下载接口
Utilities 选项卡添加分散加载实验

1、Target 选项卡

外部晶振频率为 8Mhz。

2、Output 选项卡

勾选:Browse Information,用于输出浏览信息,这样就可以使用 go to definition 查看函数/变量的定义,对我们后续调试代码比较有帮助,如果不需要调试代码,则可以去掉这 个勾选,以提高编译速度。 

Select Folder Objects,为选择输出的文件夹,我们在第一节说过,建立的5个文件夹中Output就是用来存放输出的文件,这里我们需要对应的选择;而且在这里我们还需要选择创建.hex文件,即十六进制文件,因为往单片机里传输的文件就是.hex文件;

3、Listing 选项卡

同样我们将Listing 的输出文件也放在我们设置的Output文件夹中去;

4、C/C++选项卡 

        全局宏定义:STM32F103xE,用于定义所用 STM32 型号,在 stm32f1xx.h 里 面会用到该宏定义。

        设置了优化等级为-O0,可以得到最好的调试效果,当然为了提高优化效果提升性能 并降低代码量,可以设置-O1~-O3,数字越大效果越明显,不过也越容易出问题。注意:当使用 AC6 编译器的时候,这里推荐默认使用-O1 优化。

        C99 模式,即使用 C99 C 语言标准。

        进行头文件包含路径设置。

        头文件的包含路径共有以上四个,此处用到的是相对路径,并非绝对路径;

绝对路径:是指目录下的绝对位置,直接到达目标位置,通常是从盘符(即C\D盘等)开始的路径。 

相对路径:是指由某个文件所在路径引起的跟其他文件(或文件夹)的路径关系;

        直接路径简单来说,就是由明确的路径,根据其能直接找到对应的文件;例如:

F:\51单片机\【正点原子】精英STM32F103开发板 V2-资料盘(A盘)\8,STM32参考资料\8,STM32参考资料\1,STM32CubeF1固件包;

        相对路径就是,在一个文件(初始路径)的基础上,进行上一层目录。或者下一层,进行的一种关系,“../”表示当前目录的上一层目录;“./”表示当前目录;而我们默认的初始路径为MDK 工程所在的路径,即.uvprojx 文件所在路径。所以上面的路径前面都有../。

5、设置Debug 选项卡

        设置对应的仿真器,我使用的是ST-LINK仿真器,大家选择合适对应的即可;

6、Utilities 选项卡

 按照上面,设置为对应的选项;

5、添加 main.c,并编写代码

         在 MDK 主界面,新建一个 main.c 文件,并保存在 User 文件夹下。然后双击 User 分组,弹出添加文件的对话框,将 User 文件夹下的 main.c 文件添加到 User 分组下。并在main.c文件中加入下面的代码:

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
int main(void)
{
 uint8_t t = 0;
 sys_stm32_clock_init(9); /* 设置时钟, 72Mhz */
 delay_init(72); /* 延时初始化 */
usart_init(72, 115200); /* 串口初始化 */
 while (1)
 {
 printf("t:%d\r\n", t);
 delay_ms(500);
 t++;
 }
}

 编写完 main.c 以后,我们点击:(Rebuild)按钮,编译整个工程,编译结果如图 所示:

如果有一个警告,在最后一行敲一行空行,即不要让代码成为最后一行; 

并且,在Output中生成了.hex文件,可以直接传给单片机;

二、下载验证

        此处,我们采用的是ST-LINK进行下载;

1、实物连接

        点击下载,底部会显示下载成功的标志;

2、实验结果

         在用ST-LINK进行下载后,将串口同单片机以及电脑连接,这是一个有关串口的实验现象,通过串口向单片机发送数据;

        连接方式如下:

        

新建MDK文件

总结:写到此处,第一个MDK工程已经创建完毕,当然这是一个漫长而又繁琐的过程,多少人都很难坚持下来。而且往往看第一遍的时候总是耐不下心,觉得很难、很烦,很啰嗦,这是每个人都会遇到的,但是只要你坚持看完第一遍,再去第二遍看的时候,就会熟悉很多,再到第三遍,这或许就是学习的过程吧。

        本文大多数内容参考的是正点原子:STM32F103 开发指南,特此说明!!!

创作不易,还请大家多多点赞支持!!!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1279906.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

洛谷 P1998 阶乘之和 C++代码

前言 今天我们来做洛谷上的一道题目。 网址:[NOIP1998 普及组] 阶乘之和 - 洛谷 西江月夜行黄沙道中 【宋】 辛弃疾 明月别枝惊鹊,清风半夜鸣蝉。稻花香里说丰年,听取WA声一片。 七八个星天外,两三点雨山前。旧时茅店社林边&…

压缩docker在主机的虚拟磁盘容量

我们在windows里使用docker时会发现,即使我们已经删除了无用的镜像和容器,主机里挂在docker虚拟磁盘的那个盘,可用空间也没有增加,这是因为虚拟磁盘不会自动缩小,这里我分享一个可用的解决方案。 1.先通过docker回收空…

【Leetcode题单】(01 数组篇)刷题关键点总结01【数组的遍历】

【Leetcode题单】(01 数组篇)刷题关键点总结01【数组的遍历】(4题) Easy数组的遍历485. 最大连续 1 的个数 Easy495. 提莫攻击 Easy414. 第三大的数 Easy628. 三个数的最大乘积 Easy 大家好,这里是新开的LeetCode刷题系…

[力扣题]1.判断一棵树是否是平衡二叉树

1.判断一棵树是否是平衡二叉树 1.1 题目描述 给你一棵二叉树的根节点 root ,请你判断这棵树是否是一棵 完全二叉树 。 在一棵 完全二叉树 中,除了最后一层外,所有层都被完全填满,并且最后一层中的所有节点都尽可能靠左。最后一层…

【物联网无线通信技术】ZigBee从理论到实践(CC2530)

文章延续之前【物联网无线通信技术】系列文章的风格,首先对ZigBee这种在物联网发展初期出现的无线通信技术进行了相关背景概念的介绍,并横向介绍了几款时间跨度比较大的ZigBee芯片。然后以CC2530为例,从硬件到软件介绍了ZigBee这中无线通信技…

C++跨目录include问题

不同文件夹下使用预处理器指示符#include 使用举例 假设我们有如下一个工程,其中包含了几个源代码和头文件,其中main.cpp是主源代码文件,里面含有main函数: 在foldder main中包含:func4.hpp,func4.cpp&am…

C语言结构体详解(二)(能看懂文字就能明白系列)文章很长,慢慢品尝

系列文章目录 第一章 结构体的介绍和基本使用 🌟 个人主页:古德猫宁- 🌈 信念如阳光,照亮前行的每一步 文章目录 系列文章目录🌈 *信念如阳光,照亮前行的每一步* 前言前面一篇文章主要介绍了结构体的基础…

Java 使用对应arthas 调试程序

1、作用 使用 arthas 可以进行如下操作 ① 抓取对应函数的耗时结构,然后分析对应的代码优化代码 ② 抓取对应函数的 入参、出参函数 ③ 重放对应的函数执行 ④ 查询对应程序占用结构,比如 cpu, jvm ⑤ 查询对应的 执行最频繁的 线程 ⑥ 打印函数…

震惊!我和GPT玩了一天游戏·····

最近开始研究如何基于GPT构建一个游戏引擎,于是先从简单的文字游戏开始探索。 从最简单的选择机制、故事机制,完善成一个包括天气、事件、技能、属性、伙伴、建造系统的-生化危机版文字游戏-。 我唯一的体验是:AI游戏,大有可为! …

C++11--右值引用

目录 基本概念 左值和右值 左值引用和右值引用 右值引用使用场景和意义 左值引用使用场景 左值引用的短板 右值引用和移动语义 右值引用引用左值 右值引用的其他使用场景 完美转发 万能引用 完美转发保持值得属性 完美转发使用得场景 基本概念 左值和右值 什么…

二叉树链式结构的实现和二叉树的遍历以及判断完全二叉树

二叉树的实现 定义结构体 我们首先定义一个结构来存放二叉树的节点 结构体里分别存放左子节点和右子节点以及节点存放的数据 typedef int BTDataType; typedef struct BinaryTreeNode {BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right; }BTNode;…

solidity实现ERC20代币标准

文章目录 IERC20ERC20Remix 编译部署 IERC20 IERC20 是 ERC20 标准的接口规范,它定义和规范了一个标准 ERC20 代币合约应该实现的功能。这里让 ERC20 合约直接继承自 IERC20 接口。 // SPDX-License-Identifier: MIT pragma solidity ^0.8.4;interface IERC20 { // …

2023软件测试大赛总结

2023软件测试大赛总结 文章目录 2023软件测试大赛总结软件下载方式比赛方式个人总结断言使用java基础 预选赛省赛国赛 软件下载方式 进入官网下载插件(直接下载一个完整的Eclipse就可以,这样比较方便) 需要保证jdk版本和要求的一致,不然可能…

【Spring Boot 源码学习】ApplicationContextInitializer 详解

Spring Boot 源码学习系列 ApplicationContextInitializer 详解 引言往期内容主要内容1. 初识 ApplicationContextInitializer2. 加载 ApplicationContextInitializer3. ApplicationContextInitializer 的初始化 总结 引言 书接前文《初识 SpringApplication》,我们…

LeetCode(50)有效的括号【栈】【简单】

目录 1.题目2.答案3.提交结果截图 链接: 有效的括号 1.题目 给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合…

Linux基础项目开发1:量产工具——页面系统(六)

前言: 前面我们已经将显示系统、输入系统、文字系统、UI系统全部搭建好了,下面就到了开发板页面的布局,也就是实现按钮在开发板页面上的每个位置,下面让我们一起实现页面的搭建与布局设计吧。 目录 一、数据结构抽象 page_manager…

报考公务员简历(精选8篇)

想要成功进入公务员队伍,一份出色的个人简历是必不可少的。本文为大家精选了8篇报考公务员的个人简历案例,无论是应届毕业生还是有工作经验的求职者,都能从中汲取灵感,提升简历质量。找到心仪的公务员岗位。 报考公务员简历模板下…

java 工具类: CompareUtils(比较对象字段值变化)

一、前言 我们在工作中,可能会在日志中记录数据的变化情况或者在公共处理的数据增加一个日志页面,记录每次修改的变化。我们可以根据CompareUtils工具类比较数据前后发生了怎样的变化, 这样我们就可以知道数据做了哪些改变. 二、条件限制 在写这个通用…

Ontrack EasyRecovery2024数据恢复软件详细功能介绍

Ontrack EasyRecovery2024是一款功能强大的数据恢复软件,它可以帮助用户从各种存储设备中恢复丢失或删除的数据。它支持多种文件系统和文件类型,可以恢复包括照片、视频、音频、文档、电子邮件和归档文件等不同类型的数据。 EasyRecovery15Mac版本下载如…

轻易云AI:引领企业数智化转型提升企业AI效率

近期,轻易云AI与汤臣倍健的合作引起了业界的广泛关注。通过这一合作,轻易云AI不仅成功打造了集团小汤AI助手这一标志性的企业智能助手,更重要的是,这一合作凸显了轻易云AI作为专业AI应用集成专家的核心能力。轻易云AI已成功集成了…