STM32---MDK工程创建

本节我们带领大家学习如何新建一个寄存器库版本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.mzph.cn/news/190715.shtml

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

相关文章

导入seaborn的数据集方法load_datasets的问题

sns.load_dataset使用报错解决URLError: <urlopen error [Errno 11004] getaddrinfo failed>(windows)) import seaborn as sns import matplotlib.pyplot as plt ​ # 使用Seaborn自带的数据集 tips sns.load_datas…

Filebeat使用指南

Filebeat介绍主要优势主要功能配置日志的解析Kibana中设置日志解析安装步骤安装Filebeat安装监控通过prometheus监控 Filebeat和Logstash的主要区别 Filebeat介绍 Filebeat是使用Golang实现的轻量型日志采集器,也是Elasticsearch stack的一员。它可以作为一个agent…

CSS BFC特性和应用

目录 1,介绍2,BFC布局规则3,创建BFC4,BFC应用1,浮动子元素使父级高度坍塌2,非浮动元素被浮动元素覆盖3,margin 合并1,父子 margin 合并:父级和第1个/最后1个子元素2&…

深度学习之基于Django文本情感分析识别系统

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 深度学习在文本情感分析领域的应用已经取得了显著的进展。Django是一个流行的Python Web框架,它可以帮助…

代码随想录算法训练营第39天| 62.不同路径 63. 不同路径 II

JAVA代码编写 62.不同路径 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不…

灰度发布专题---3、Nginx+Lua灰度发布

上一章已经讲解了配置文件灰度发布、应用版本灰度发布、API网关灰度发布实现,但如果用户这时候在代理层如何做灰度发布呢? 代理层灰度发布分析 用户无论访问应用服务还是静态页,都要经过Nginx代理层,我们可以在Nginx这里做灰度发…

SeaTunnel扩展Source插件,自定义connector-webservice

代码结构 在seatunnel-connectors-v2中新建connector-webservice模块,可以直接赋值connector-http-base模块,webservice和http的方式比较类似,有些类直接复制了http中的代码。 核心类有WebserviceConfig,WebserviceParameter&am…

【上海大学数字逻辑实验报告】三、组合电路(二)

一、实验目的 掌握8421码到余3码的转换。掌握2421码到格雷码的转换。进一步熟悉组合电路的分析和设计方法。学会使用Quartus II设计8421码到余3码的转换电路逻辑图。学会使用Quartus II设计2421码到格雷码的转换电路逻辑图。 二、实验原理 8421码是最常用的BCD码&#xff0c…

TOP-K问题和向上调整算法和向下调整算法的时间复杂度问题的分析

TOP-K问题 TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大 比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等 对于Top-K问题,能想到的最简单直接的方式就是排序,但是…

【程序设计】简易生产者、消费者模型

需求: 创建消息队列时需要指定队列的容量上限,队列中没有消息时,消费者从队列中take元素会阻塞;队列中的消息数量达到容量上限时,生产者往队列中put元素会阻塞。要保证线程安全。 组成: (1&…

【NeurIPS 2023】PromptIR: Prompting for All-in-One Blind Image Restoration

PromptIR: Prompting for All-in-One Blind Image Restoration, NeurIPS 2023 论文:https://arxiv.org/abs/2306.13090 代码:https://github.com/va1shn9v/promptir 解读:即插即用系列 | PromptIR:MBZUAI提出一种基…

文件操作--IO

目录 ♫什么是文件 ♫文件路径 ♫文件类型 ♫文件的管理 ♪File的构造方法 ♪File的常用方法 ♫文件的内容操作 ♪InputStream ♪OutputStream ♪字符流读写文件 ♫Scanner与流对象 ♫什么是文件 文件在计算机里可以指“狭义”的文件(指硬盘上的文件和目录&…

c语言详解牛顿迭代法以及求解倒数和平方根

Newtons iteration method 是在实数域和复数域利用切线不断逼近方程根的一种求高次曲线方程的方法,区别于梯度下降法,它是二阶导,收敛速度比较快,对于非凸函数,牛顿法容易受到鞍点或者最大值点的吸引。由于牛顿迭代法是…

产品学习之路(一)

在做好开发的同时,还需要熟悉产品业务逻辑,不能为了功能而做功能,要从产品经理的角度去看待每个需求和客户痛点所在,这样针对产品设计出来的东西自己也有发言权; 目前作为一名前端开发人员,也在自学产品知识…

xxl-job 分布式任务调度框架

文章目录 分布式任务调度XXL-Job 简介XXL-Job 环境搭建XXL-Job (源码说明)配置部署调度中心docker安装 Bean模式任务(方法形式)-入门案例任务详解任务详解-执行器任务详解-基础配置任务详解-调度配置任务详解-基础配置任务详解-阻塞处理策略任务详解-路由策略 路由策略路由策略…

Redis数据结构之压缩列表

压缩列表是Redis为节约内存而开发的,是由一系列特殊编码的连续内存块组成的顺序型数据结构。一个压缩列表可以包含任意多个节点,每个节点可以保存一个字节数组或者整数值。 压缩列表构成 zlbytes: 记录整个压缩列表占用的内存字节数,对压缩列…

LD_PRELOAD劫持、ngixn临时文件、无需临时文件rce

LD_PRELOAD劫持 <1> LD_PRELOAD简介 LD_PRELOAD 是linux下的一个环境变量。用于动态链接库的加载&#xff0c;在动态链接库的过程中他的优先级是最高的。类似于 .user.ini 中的 auto_prepend_file&#xff0c;那么我们就可以在自己定义的动态链接库中装入恶意函数。 也…

Java数据结构之《折半查找》题目

一、前言&#xff1a; 这是怀化学院的&#xff1a;Java数据结构中的一道难度中等的一道编程题(此方法为博主自己研究&#xff0c;问题基本解决&#xff0c;若有bug欢迎下方评论提出意见&#xff0c;我会第一时间改进代码&#xff0c;谢谢&#xff01;) 后面其他编程题只要我写完…

自定义函数中的(int*a,int*b)与(int*a,int n)

事实上第一种更安全&#xff0c;不会因越界发生占位&#xff0c;从而导致错误。

C++的类和对象(一)

目录 1、面向过程和面向对象初认识 2、为什么要有类 3、类的定义 类的两种定义方式 4、类的访问限定符 5、类的作用域 5.1 为什么要有作用域&#xff1f; 5.2类作用域 6、类的实例化 6.1类的实例化的定义 6.2类的实例化的实现 6.3经典面试题 7、类对象 7.1类对…