本节我们带领大家学习如何新建一个寄存器库版本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工程,分为以下5个步骤,我们会分别详细介绍:
1、新建工程文件夹;2、新建工程框架、工程命名以及选择芯片;3、添加文件;4、魔术棒的设置;5、添加main.c文件;
新建工程文件夹的作用是,由于32的一个工程涉及的.c、.h等功能文件很多如果把它们全部放在一个文件夹中,那很容易混乱,寻找哪个文件也很不方便;所以我们对于文件进行分类,把它按照不同为文件夹进行划分;就好比:51是我们小学时候,班级的同学比较少,不需要进行分班就能直接找到每一个同学;而32是等我们上到初中了,一个年级的同学就有很多,这时我们就需要对这些同学进行分班,按照班级寻找同学。建立文件夹的作用是一样的;
我们对于32工程共分5个大的文件夹(如同5各班级),分别为:
文件夹名称 | 作用 |
Drivers | 存放与硬件相关的驱动层文件 |
Middlewares | 存放正点原子提供的中间层组件文件和第三方中间层文件 |
Output | 存放工程编译输出文件 |
Projects | 存放 MDK 工程文件 |
User | 存放用户编写的代码,如 main.c |
建立完这5个文件夹后,现在里面都是空的,对于新手来说,这5个文件夹是用来干啥的?不知道!为什么要分为5个文件夹?不知道!当然,为什么这么划分,我确实也不知道,但是,官方能给出这样的划分,就说明有一定的原因,我们先按照这个来进行;
工程根目录及其相关文件夹新建好以后,我们需要拷贝一些工程相关文件过来(主要是在 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 的工程文件;
新建工程框架就是新建一个工程,在这个工程中进行操作,也可以实现一个项目,一个功能等等;
首先,打开 MDK 软件。然后点击 Project→New uVision Project;
然后,设置工程的路径与名称;
工程路径,就选择我们上节新建在Project中的文件MDK-ARM 文件夹;
工程名字,自行选择,好记就行;
保存后,下一步就是对应的芯片选型,此处对应自己的芯片选型即可;
在选好芯片后,界面会弹出这样的页面,我们不需要管,关闭即可;
然后就会在主界面显示这个内容,表明新建工程框架完成;
最后,我们看一下,新建完工程后,在第一节中新建的文件夹中有什么变化呢?
在开 MDK-ARM 文件夹,会看到 MDK 在该文件夹下自动创建了 2 个文件夹 (Listings 和 Objects)以及生成.uvprojx文件,这个文件就是新建的工程文件;而Listings文件夹,用于存放编译过程产生的链接列表等文件;Objects文件夹,用于存放编译过程产生的调试信息、.hex、预览、.lib 文件等;我们后面回把输出在 Listings 和 Objects 文件夹的内容,统一改为输出到 Output 文件夹,不按照他这个进行输出,此处需要注意一下下;
添加文件的作用是什么呢?我们在建立完一个工程后,需要用到这个工程,32的功能比较复杂,我们需要添加一些已经封装好的函数文件.c、.h等等;
同样,由于涉及的文件较多,我们需要在工程内部,对所添加的文件进行分类;
注意:第一节是对文件在外部文件夹中分类,这节是对文件在工程内部进行分类
分为三个步骤:1、设置工程名与分组名(也就是分班);2、添加启动文件;3、添加SYSTEM源码;
在 Project→Target 上右键,选择 Manage Project Items…(方法一)或在菜单栏点击品字形 红绿白图标(方法二)进入工程管理界面。
在工程管理界面,我们可以执行设置工程名字(Project Targets)、分组名字(Groups)以 及添加每个分组的文件(Files)等操作。
我们设置工程名字为:Template,并设置四个分组: Startup(存放启动文件)、User(存放 main.c 等用户代码)、Drivers/SYSTEM(存放系统级驱 动代码)、Readme(存放工程说明文件);
这里我们只是新建了一个简单的工程,并没有添加 BSP、Middlewares 等分组,后面随着工 程复杂程度的增加,我们需要一步步添加对应的分组,使内外分组进行一致;
启动文件(.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
在我们工程里面,由Drivers/SYSTEM的文件夹,注意这个不是或的意思,这是Drivers文件夹下的文件夹SYSTEM,我们前面对SYSTEM进行了复制(就是百度网盘中的文件),这会需要添加进来。如果之前没拷贝,是找不到这些源码的。
为避免编写代码和编译报错,我们需要通过魔术棒对 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 选项卡
在 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进行下载;
点击下载,底部会显示下载成功的标志;
在用ST-LINK进行下载后,将串口同单片机以及电脑连接,这是一个有关串口的实验现象,通过串口向单片机发送数据;
连接方式如下:
新建MDK文件
总结:写到此处,第一个MDK工程已经创建完毕,当然这是一个漫长而又繁琐的过程,多少人都很难坚持下来。而且往往看第一遍的时候总是耐不下心,觉得很难、很烦,很啰嗦,这是每个人都会遇到的,但是只要你坚持看完第一遍,再去第二遍看的时候,就会熟悉很多,再到第三遍,这或许就是学习的过程吧。
本文大多数内容参考的是正点原子:STM32F103 开发指南,特此说明!!!
创作不易,还请大家多多点赞支持!!!