【嵌入式】工程模板的编写以及工程代码的理解
21/100
保存草稿
发布文章
weixin_52621323
未选择文件
1)前言
从我目前的学习中总结而来,要说51和STM32的最大区别,应该是STM32可以面向固件库编程了。
什么意思呢,在51中,是具体落实到操作的引脚,但是在STM32中,为了方便我们更加系统化的编程,咱们是面向固件库,就相当于已经有人把工具造好,我们只需要按照说明书来规范的利用这些工具完成我们的需求。
对工程模板的创建规定,算是行业内对工具使用规范的一个小贡献。
这篇文章是通过创建项目,阐述清楚正点原子和野火两个主流教育风格创建的项目中,各个目录结构都是用来服务什么功能的。
比如正点原子
的目录结构可能是这种的:
比如野火教育
的目录结构可能是这种的:
它们主要的思想是差不多的,但是模块化思想有区别,可能导致干扰我们阅读项目源码
2)STM32工程模板(基于标准库) – 野火版本
2.1)整理标准库文件夹
对于官方提供的v3.5.0标准库,在我们目前的开发中,其实只是会用到其中的一部分,那么我更加建议将需要使用的标准库进行整理,方便自己更加快捷的获取到自己需要的标准库文件。
咱们解压出来的标准库文件大致是这种的:
① 整理内容1
将
Libraries目录下
CMSIS目录下
CM3目录下
CoreSupport目录中
的两个文件夹剪切到 CMSIS文件的根目录
中
记住,单片机的核心,仍旧是操作寄存器。
core_cm3.h实现了内核寄存器的映射,相当于其中书写了宏定义呀,结构体呀,函数声明等等。
至于core_cm3.c,则是实现了在头文件中声明的函数。
② 整理内容2
将
DeviceSupport目录下
,
ST目录下
,
STM32F10x目录下
,
剪切如下三个文件以及一个文件夹到 CMSIS文件夹的根目录
1、stm32f10x.h —— 包含了所有片上寄存器的映射
2、system_stm32f10x.c —— 包含STM32时钟配置
3、system_stm32f10x.h —— 对应于时钟配置.c文件的头文件
4、startup文件夹
③ 整理完的最终效果:
2.2)在本地新建工程文件夹
注意,整个项目的全部路径中,不要包含中文,不要包含中文。本地新建的这个文件夹相当于整个项目工程所有代码的家
主要需要建立四个文件夹,每个文件夹中需要放置的内容如下图:
① Doc文件夹 —— 工程说明
② Libraries文件夹 —— 管理内核以及外设库
将刚才整理的固件库中Libraries文件夹下的内容复制过来即可
③ Project文件夹 —— Keil新建工程后存储文件夹
④ User文件夹
新建main.c文件,其中的代码在这张图片下方,其他三个文件需要去去标准库中复制粘贴 移植
浅插播一句,在STM32固件库开发中,几乎都是.c文件和.h文件配套出现。
#include "stm32f10x.h" // 相当于51单片机中的 #include <reg51.h>
// 软件延时
void Delay(__IO uint32_t nCount)
{
for(; nCount != 0; nCount--);
}
int main(void)
{
// 来到这里的时候,系统的时钟已经被配置成72M。
}
2.3)在Keil5软件新建工程
Keil中创建工程,相当于将项目的代码交给一位管家管理。
打开Keil5的软件,假如没有安装的小伙伴,可以跟着这篇博客:
【keil5安装教程】
他的操作没有问题,只是不能优雅的使用到2032年了,用我下面这个链接。
链接:https://pan.baidu.com/s/147DFxMYESuOgvgWsY1NXlA?pwd=1024
提取码:1024
① 新建工程
打开Keil5,新建一个工程,工程名根据自己喜好命名,必须是英文名字。
我目前取Template(中文是模版的意思),保存在Project文件夹下,相当于将管家安插在本地代码存储的位置中
② 选择CPU型号
当选择好工程在磁盘的放置位置以及工程的名字之后,会弹出如下界面,让咱们选择CPU的型号。
Tips:出现下面界面的前提是已经安装了 Keil.STM32F1xx_DFP.2.2.0.pack
因为我手上拿着的是野火的指南者,它官网上给出了CPU的型号:
③ 关闭在线添加库文件
④ 添加组文件夹
在新建的工程中添加5个组文件夹,分别负责五个不同的模块。
逐步将上面五个组新建出来后的效果:
⑤ 添加文件
根据上图中各个文件夹中应该放置的文件,具体的添加文件。
双击组文件夹就会出现添加文件的路径,然后选择文件即可。
对于STARTUP
对于CMSIS
对于FWLB
对于USER
其实可以发现,添加的都是.c文件
对于Doc
⑥ 配置魔术棒选项卡
1、Target位置:选中Use Micro LIB + 更改ARM Compiler
,对于MDK537后的版本才需要选择V5.06,之前的版本保持默认
MDK537后需要独立安装 ARMCompiler_506_Windows_x86_b960.zip (80.94MB) MDK 兼容包
2、Output位置:勾选 Create HEX File
指定完成Output文件夹之后,点击OK
3、Listing:几乎不用动,一般可直接跳过。当然,也是类似Output,在有需求时,可以指定位置。
4、C/C++位置:这里需要进行的操作比较多
① 添加宏
对于STM32F103VE系列的开发板,可以直接复制下方代码:
STM32F10X_HD, USE_STDPERIPH_DRIVER
在这个选项中添加宏
,就相当于我们在c文件中使用“#define”语句进行定义宏。
在编译器中添加宏的好处就是,只要用了这个模版,就不用每次使用,都要到源文件中修改代码。
下面是关于宏的介绍,以及如何根据开发板编写自己的宏
① STM32F10X_HD宏:为了告诉STM32标准库,我们使用的芯片类型是STM32型号是怎么样的,HD就是大容量的类型。
中间使用英文输入状态下的逗号分隔开
② USE_STDPERIPH_DRIVER宏:为了让stm32f10x.h包含stm32f10x_conf.h这个头文件。
第二个宏是这种获得的:
先进入stm32f10x.h头文件,划到底部,有这样两行代码:
② 添加的是头文件的路径
但凡工程中需要用到的头文件(.h文件
),都需要指定路径(不然软件会默认到安装位置找头文件,可能就找不到)。
比如User文件
下有.h文件,那么我就要找到User文件夹的位置,将其路径添加到这里。
比如CMSIS文件
下有.h文件,那么就将这个文件夹的位置,添加到这里。
5、Debug 位置:—— SPI下载再进行这步
假如是SPI下载的小伙伴,这里只是需要到Setting
中,选择Flash Download
,然后选择Reset and Run
【如何用串口下载程序】
勾选之后,咱们烧录进去的代码就不需要手动按开发板上的RESET
按键之后,程序才会执行。
最终编译的结果:
3)STM32工程模板(基于HAL[固件库]库) – 正点原子版本
对于正点原子版本的,其实和指南者差不多,模块化的命名和归类不太相同。
然后正点原子这边几乎使用的是HAL库(固件库)编程,比野火的标准库编程更高一个level。
3.1)标准外设库 和 硬件抽象层库(固件库)的区别
3.1.1)总体认识
ST为开发者提供了非常方便的开发库。到目前为止,有标准外设库(STD库)、HAL库、LL库
三种。
标准外设库全名是 Standard Peripheral Libraries
硬件抽象层HAL库全名是 Hardware Abstraction Layer
STD库和HAL库两者相互独立,互不兼容。
都是面向开发板兼容,比如HAL库做了更深的封装,可以很方便的移植在F0/F1/F3/F4/F7的各个系列的芯片上。因此,能够用了标准外设库的板子,完全可以更换使用HAL库
3.1.2)分类探讨
① 标准外设库用得最多,但是没有移植性
标准外设库(Standard Peripherals Library)是对STM32芯片的一个完整的封装,包括所有标准器件外设的器件驱动器。这应该是目前使用最多的ST库,几乎全部使用C语言实现。但是,标准外设库也是针对某一系列芯片而言的,没有可移植性。
② 现在ST公式主推HAL库,HAL库已经支持STM32全线产品,可以说HAL库就是用来取代之前的标准外设库的。
HAL库与新增的LL库,都是ST公司提供的新标准库,包含在ST为新的标准库注册了一个新商标:STMCube™当中。LL库和HAL库两者也是相互独立,只不过LL库更底层。部分HAL库会调用LL库(例如:USB驱动)。同样,LL库也会调用HAL库。
ST目前主推的图形化配置工具CubeMX,生成的代码就是使用HAL库,使用CubeMX开发可以大大减轻开发者的工作量。
STM32Cube初始化代码生成器
相比标准外设库,STM32Cube HAL库表现出更高的抽象整合水平,HAL API集中关注各外设的公共函数功能,这样便于定义一套通用的用户友好的API函数接口,从而可以轻松实现从一个STM32产品 移植
到另一个不同的STM32系列产品
HAL库是ST未来主推的库,从前年开始ST新出的芯片已经没有STD库了,比如F7系列。
3.1.3)各种库文件包的下载
STM32标准外设库、HAL库、LL库的下载地址(ST官网)汇总
三种库的认知 —— 大佬介绍版
HAL库中的文件有点多,不整理了…
3.2)在本地新建工程文件夹
① CORE文件夹 —— 放置核心依赖
将CMSIS文件夹中,Include文件夹下的六个个头文件(省流:假如觉得麻烦,其实可以将Include文件夹下的头文件全部复制 ),分别是:
cmsis_armcc.h
头文件 、
cmsis_armclang.h
头文件、
cmsis_compiler.h
头文件、
core_cm3.h
头文件、
cmsis_version.h
头文件、
mpu_armv7.h
头文件
和arm文件夹下的startup_stm32f103xe.s
复制到CORE文件夹中
找到启动文件
最后效果:
解读:
CORE的意思是核心,放置的是开发板的一些核心依赖文件,主要是CMSIS文件夹下的文件
CMSIS文件夹下,arm文件夹中的启动文件,比如Include文件夹下的头文件。
启动文件的选择标准如下:
标准库:
这是ST提供的3个启动文件,分别适用于不同容量的STM32芯片。
这三个文件为:
startup_stm32f10x_ld.s
startup_stm32f10x_md.s
startup_stm32f10x_hd.s
其中,ld.s适用于小容量 产品;md.s适用于中等容量产品;hd适用于大容量产品;
这里的容量是指FLASH的大小.判断方法如下:
小容量:FLASH≤32K
中容量:64K≤FLASH≤128K
大容量:256K≤FLASH
HAL库:
这是ST提供的4个启动文件,分别适用于不同容量的STM32芯片。
这4个文件为:
startup_stm32f103x6.s
startup_stm32f103xb.s
startup_stm32f103xe.s
startup_stm32f103xg.s
其中,x6.s适用于小容量 产品;xb.s适用于中等容量产品;
xe适用于大容量产品;xg适用于超大容量产品
这里的容量是指FLASH的大小.判断方法如下:
小容量:16K<=FLASH≤32K
中容量:64K≤FLASH≤128K
大容量:256K≤FLASH<=512k
超大容量:768K≤FLASH<=1024K
我自己的板子stm32f103大容量类型的,所以选择的是startup_stm32f103xe.s
比如CMSIS下,Include文件夹中
和实现内核寄存器映射的core_cmx.h文件
和微控制器软件接口标准相关的cmsis_xxxx.h文件
② HALLIB文件夹
将Drivers
文件夹下中的的STM32F1xx_HAL_Driver
复制到HALLIB文件夹中
HALLIB是HAL库的缩写了,所谓的库,其实就是很多ST已经写好了,能够供咱们直接使用的.c文件
为了省事一点,直接将这个文件夹Copy到咱们自己的目录下。
③ OBJ文件夹 —— 存放杂文件
暂时放着,待会用于放置Keil5创建项目之后会生成的零零散散的文件,包括.hex文件
④ SYSTEM文件夹 —— 正点原子官方给的工具
SYSTEM 文件夹是正点原子为开发板用户编写的一套非常实用的函数库,比如系统时钟初始化
,串口打印
,延时函数
等,从它们给的 HAL 库版本下任何一个实验中复制过来即可。
这里提供一下正点原子官方的资料,它们B站上的链接好像挂了。
链接:https://pan.baidu.com/s/14fNVsHeWp2wf8Mh_vsFm-w?pwd=ac24
提取码:ac24
⑤ USER文件夹
步骤 ① —— 移植头文件
1、CMSIS\Device文件夹下,
进入ST文件夹,
再进入STM32F1xx文件夹,
最后进入Include文件夹中,将
stm32f1xx.h,system_stm32f1xx.h 和 stm32f103xe.h
复制到 USER 目录之下。
1)stm32f1xx.h 头文件
它是所有 stm32f1 系列的顶层头文件。 使用 STM32F1任何型号的芯片,都需要包含这个头文件。
同理,假如使用的是F4或者F7的芯片,就得包含其他的顶层头文件了。
同时,因为 stm32f1 系列芯片型号非常多,ST为每种芯片型号其实都是有自己的头文件,这里的f1xx
是一个抽象的描述,它自己会根据咱具体的板子的型号(容量作为主要区分标准),引入它们相对应的头文件。
2)stm32f103xe.h文件
这里是因为咱们的目前这块开发板需要会在stm32f1xx.h 的代码中,涉及这个头文件(上方图)。
假如讲究一点的开发者可以详细根据自己的开发板选择对应该的头文件,假如想省事一点,直接Ctrl + A ,然后复制所有的头文件,都放到USER目录下,反正不会报错
3)system_stm32f1xx.c/system_stm32f1xx.h 文件
头文件system_stm32f1xx.h和源文件system_stm32f1xx.c主要是声明和定义了系统初始化函数 SystemInit
以及系统时钟更新函数SystemCoreClockUpdate
。
SystemInit 函数
会帮我们配置好系统时钟配置相关的各个寄存器。在启动文件 startup_stm32f103xx.s 中会设置系统复位后,直接调用 SystemInit 函数进行系统初始化
。
SystemCoreClockUpdate 函数
是在系统时钟配置进行修改后,调用这个函数来更新全局变量 SystemCoreClock 的值,变量 SystemCoreClock 是一个全局变量,开放这个变量可以方便我们在用户代码中直接使用这个变量来进行一些时钟运算。
步骤② —— 复制固件库中Templat文件夹中的文件
2、将Projects文件夹下,再逐层进入到Templates文件中,Inc 和 Src 文件夹中的全部内容(总共七个文件 4个.c + 3个.h ),复制到USER目录之下。
移植完的效果:
步骤③ —— 更新main.c的内容
#include "sys.h"
#include "delay.h"
#include "usart.h"
/***这个代码最后烧到开发板,跑出来的效果是两个led灯,交替闪烁***/
void Delay(__IO uint32_t nCount);
void Delay(__IO uint32_t nCount)
{
while(nCount--){}
}
int main(void)
{
GPIO_InitTypeDef GPIO_Initure;
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72M
__HAL_RCC_GPIOB_CLK_ENABLE(); //开启GPIOB时钟
__HAL_RCC_GPIOE_CLK_ENABLE(); //开启GPIOE时钟
GPIO_Initure.Pin=GPIO_PIN_5; //PB5
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; //高速
HAL_GPIO_Init(GPIOB,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_5; //PE5
HAL_GPIO_Init(GPIOE,&GPIO_Initure);
while(1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET); //PB5置1
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET); //PE5置1
Delay(0x7FFFFF);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET); //PB5置0
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET); //PE5置0
Delay(0x7FFFFF);
}
}
⑥ HARDWARE文件夹
该文件夹在正点原子里是用来放项目用到的外设,比如ADC、LED、DMA等等。在野火的教学中,是在User目录下,各自创建相应的外设的文件夹,这里比较灵活,不一定有,根据自己需求吧,只是简单介绍一下。
3.3)在Keil5中新建项目
在Keil中新建的工程时,命名可以完全和本地磁盘新建的文件夹名字相同。
这里的流程就和野火中差不多了,新建工程时候,位置选择为本地创建工程中USER文件夹下,不反复造轮子啦~
USER文件夹最后是会作为Keil5中创建的项目的保存路径,也就是将Keil这个管家放到USER目录。
文章目录
1)前言
2)STM32工程模板(基于标准库) – 野火版本
2.1)整理标准库文件夹
2.2)在本地新建工程文件夹
① Doc文件夹 —— 工程说明
② Libraries文件夹 —— 管理内核以及外设库
③ Project文件夹 —— Keil新建工程后存储文件夹
④ User文件夹
2.3)在Keil5软件新建工程
① 新建工程
② 选择CPU型号
③ 关闭在线添加库文件
④ 添加组文件夹
⑤ 添加文件
⑥ 配置魔术棒选项卡
3)STM32工程模板(基于HAL[固件库]库) – 正点原子版本
3.1)标准外设库 和 硬件抽象层库(固件库)的区别
3.1.1)总体认识
3.1.2)分类探讨
3.1.3)各种库文件包的下载
3.2)在本地新建工程文件夹
① CORE文件夹 —— 放置核心依赖
② HALLIB文件夹
③ OBJ文件夹 —— 存放杂文件
④ SYSTEM文件夹 —— 正点原子官方给的工具
⑤ USER文件夹
⑥ HARDWARE文件夹
3.3)在Keil5中新建项目
1)前言
从我目前的学习中总结而来,要说51和STM32的最大区别,应该是STM32可以面向固件库编程了。
什么意思呢,在51中,是具体落实到操作的引脚,但是在STM32中,为了方便我们更加系统化的编程,咱们是面向固件库,就相当于已经有人把工具造好,我们只需要按照说明书来规范的利用这些工具完成我们的需求。
对工程模板的创建规定,算是行业内对工具使用规范的一个小贡献。
这篇文章是通过创建项目,阐述清楚正点原子和野火两个主流教育风格创建的项目中,各个目录结构都是用来服务什么功能的。
比如正点原子的目录结构可能是这种的:
在这里插入图片描述
比如野火教育的目录结构可能是这种的:
在这里插入图片描述
它们主要的思想是差不多的,但是模块化思想有区别,可能导致干扰我们阅读项目源码
在这里插入图片描述
2)STM32工程模板(基于标准库) – 野火版本
2.1)整理标准库文件夹
对于官方提供的v3.5.0标准库,在我们目前的开发中,其实只是会用到其中的一部分,那么我更加建议将需要使用的标准库进行整理,方便自己更加快捷的获取到自己需要的标准库文件。
咱们解压出来的标准库文件大致是这种的:
在这里插入图片描述
① 整理内容1
将
Libraries目录下
CMSIS目录下
CM3目录下
CoreSupport目录中
的两个文件夹剪切到 CMSIS文件的根目录 中
在这里插入图片描述
记住,单片机的核心,仍旧是操作寄存器。
core_cm3.h实现了内核寄存器的映射,相当于其中书写了宏定义呀,结构体呀,函数声明等等。
至于core_cm3.c,则是实现了在头文件中声明的函数。
在这里插入图片描述
② 整理内容2
将
DeviceSupport目录下,
ST目录下,
STM32F10x目录下,
剪切如下三个文件以及一个文件夹到 CMSIS文件夹的根目录
1、stm32f10x.h —— 包含了所有片上寄存器的映射
2、system_stm32f10x.c —— 包含STM32时钟配置
3、system_stm32f10x.h —— 对应于时钟配置.c文件的头文件
4、startup文件夹
在这里插入图片描述
③ 整理完的最终效果:
在这里插入图片描述
在这里插入图片描述
2.2)在本地新建工程文件夹
注意,整个项目的全部路径中,不要包含中文,不要包含中文。本地新建的这个文件夹相当于整个项目工程所有代码的家
主要需要建立四个文件夹,每个文件夹中需要放置的内容如下图:
在这里插入图片描述
① Doc文件夹 —— 工程说明
在这里插入图片描述
② Libraries文件夹 —— 管理内核以及外设库
将刚才整理的固件库中Libraries文件夹下的内容复制过来即可
在这里插入图片描述
③ Project文件夹 —— Keil新建工程后存储文件夹
在这里插入图片描述
④ User文件夹
新建main.c文件,其中的代码在这张图片下方,其他三个文件需要去去标准库中复制粘贴 移植
浅插播一句,在STM32固件库开发中,几乎都是.c文件和.h文件配套出现。
在这里插入图片描述
#include “stm32f10x.h” // 相当于51单片机中的 #include <reg51.h>
// 软件延时
void Delay(__IO uint32_t nCount)
{
for(; nCount != 0; nCount–);
}
int main(void)
{
// 来到这里的时候,系统的时钟已经被配置成72M。
}
在这里插入图片描述
在这里插入图片描述
2.3)在Keil5软件新建工程
Keil中创建工程,相当于将项目的代码交给一位管家管理。
打开Keil5的软件,假如没有安装的小伙伴,可以跟着这篇博客:
【keil5安装教程】
他的操作没有问题,只是不能优雅的使用到2032年了,用我下面这个链接。
链接:https://pan.baidu.com/s/147DFxMYESuOgvgWsY1NXlA?pwd=1024
提取码:1024
① 新建工程
打开Keil5,新建一个工程,工程名根据自己喜好命名,必须是英文名字。
我目前取Template(中文是模版的意思),保存在Project文件夹下,相当于将管家安插在本地代码存储的位置中
在这里插入图片描述
在这里插入图片描述
② 选择CPU型号
当选择好工程在磁盘的放置位置以及工程的名字之后,会弹出如下界面,让咱们选择CPU的型号。
Tips:出现下面界面的前提是已经安装了 Keil.STM32F1xx_DFP.2.2.0.pack
在这里插入图片描述
因为我手上拿着的是野火的指南者,它官网上给出了CPU的型号:
在这里插入图片描述
③ 关闭在线添加库文件
在这里插入图片描述
④ 添加组文件夹
在新建的工程中添加5个组文件夹,分别负责五个不同的模块。
在这里插入图片描述
在这里插入图片描述
逐步将上面五个组新建出来后的效果:
⑤ 添加文件
根据上图中各个文件夹中应该放置的文件,具体的添加文件。
双击组文件夹就会出现添加文件的路径,然后选择文件即可。
在这里插入图片描述
对于STARTUP
在这里插入图片描述
对于CMSIS
在这里插入图片描述
对于FWLB
在这里插入图片描述
对于USER
在这里插入图片描述
其实可以发现,添加的都是.c文件
对于Doc
在这里插入图片描述
⑥ 配置魔术棒选项卡
1、Target位置:选中Use Micro LIB + 更改ARM Compiler,对于MDK537后的版本才需要选择V5.06,之前的版本保持默认
MDK537后需要独立安装 ARMCompiler_506_Windows_x86_b960.zip (80.94MB) MDK 兼容包
在这里插入图片描述
2、Output位置:勾选 Create HEX File
在这里插入图片描述
指定完成Output文件夹之后,点击OK
在这里插入图片描述
3、Listing:几乎不用动,一般可直接跳过。当然,也是类似Output,在有需求时,可以指定位置。
在这里插入图片描述
4、C/C++位置:这里需要进行的操作比较多
① 添加宏
对于STM32F103VE系列的开发板,可以直接复制下方代码:
STM32F10X_HD, USE_STDPERIPH_DRIVER
在这里插入图片描述
在这个选项中添加宏,就相当于我们在c文件中使用“#define”语句进行定义宏。
在这里插入图片描述
在编译器中添加宏的好处就是,只要用了这个模版,就不用每次使用,都要到源文件中修改代码。
下面是关于宏的介绍,以及如何根据开发板编写自己的宏
① STM32F10X_HD宏:为了告诉STM32标准库,我们使用的芯片类型是STM32型号是怎么样的,HD就是大容量的类型。
中间使用英文输入状态下的逗号分隔开
② USE_STDPERIPH_DRIVER宏:为了让stm32f10x.h包含stm32f10x_conf.h这个头文件。
第二个宏是这种获得的:
先进入stm32f10x.h头文件,划到底部,有这样两行代码:
在这里插入图片描述
② 添加的是头文件的路径
但凡工程中需要用到的头文件(.h文件),都需要指定路径(不然软件会默认到安装位置找头文件,可能就找不到)。
比如User文件下有.h文件,那么我就要找到User文件夹的位置,将其路径添加到这里。
比如CMSIS文件下有.h文件,那么就将这个文件夹的位置,添加到这里。
在这里插入图片描述
5、Debug 位置:—— SPI下载再进行这步
假如是SPI下载的小伙伴,这里只是需要到Setting中,选择Flash Download,然后选择Reset and Run
【如何用串口下载程序】
在这里插入图片描述
勾选之后,咱们烧录进去的代码就不需要手动按开发板上的RESET按键之后,程序才会执行。
最终编译的结果:
在这里插入图片描述
在这里插入图片描述
3)STM32工程模板(基于HAL[固件库]库) – 正点原子版本
对于正点原子版本的,其实和指南者差不多,模块化的命名和归类不太相同。
然后正点原子这边几乎使用的是HAL库(固件库)编程,比野火的标准库编程更高一个level。
3.1)标准外设库 和 硬件抽象层库(固件库)的区别
3.1.1)总体认识
ST为开发者提供了非常方便的开发库。到目前为止,有标准外设库(STD库)、HAL库、LL库 三种。
标准外设库全名是 Standard Peripheral Libraries
硬件抽象层HAL库全名是 Hardware Abstraction Layer
STD库和HAL库两者相互独立,互不兼容。
都是面向开发板兼容,比如HAL库做了更深的封装,可以很方便的移植在F0/F1/F3/F4/F7的各个系列的芯片上。因此,能够用了标准外设库的板子,完全可以更换使用HAL库
3.1.2)分类探讨
① 标准外设库用得最多,但是没有移植性
标准外设库(Standard Peripherals Library)是对STM32芯片的一个完整的封装,包括所有标准器件外设的器件驱动器。这应该是目前使用最多的ST库,几乎全部使用C语言实现。但是,标准外设库也是针对某一系列芯片而言的,没有可移植性。
② 现在ST公式主推HAL库,HAL库已经支持STM32全线产品,可以说HAL库就是用来取代之前的标准外设库的。
HAL库与新增的LL库,都是ST公司提供的新标准库,包含在ST为新的标准库注册了一个新商标:STMCube™当中。LL库和HAL库两者也是相互独立,只不过LL库更底层。部分HAL库会调用LL库(例如:USB驱动)。同样,LL库也会调用HAL库。
ST目前主推的图形化配置工具CubeMX,生成的代码就是使用HAL库,使用CubeMX开发可以大大减轻开发者的工作量。
STM32Cube初始化代码生成器
相比标准外设库,STM32Cube HAL库表现出更高的抽象整合水平,HAL API集中关注各外设的公共函数功能,这样便于定义一套通用的用户友好的API函数接口,从而可以轻松实现从一个STM32产品 移植 到另一个不同的STM32系列产品
HAL库是ST未来主推的库,从前年开始ST新出的芯片已经没有STD库了,比如F7系列。
3.1.3)各种库文件包的下载
STM32标准外设库、HAL库、LL库的下载地址(ST官网)汇总
三种库的认知 —— 大佬介绍版
HAL库中的文件有点多,不整理了…
3.2)在本地新建工程文件夹
① CORE文件夹 —— 放置核心依赖
将CMSIS文件夹中,Include文件夹下的六个个头文件(省流:假如觉得麻烦,其实可以将Include文件夹下的头文件全部复制 ),分别是:
cmsis_armcc.h头文件 、
cmsis_armclang.h头文件、
cmsis_compiler.h头文件、
core_cm3.h头文件、
cmsis_version.h头文件、
mpu_armv7.h头文件
和arm文件夹下的startup_stm32f103xe.s复制到CORE文件夹中
找到启动文件
在这里插入图片描述
在这里插入图片描述
最后效果:
解读:
CORE的意思是核心,放置的是开发板的一些核心依赖文件,主要是CMSIS文件夹下的文件
CMSIS文件夹下,arm文件夹中的启动文件,比如Include文件夹下的头文件。
启动文件的选择标准如下:
标准库:
这是ST提供的3个启动文件,分别适用于不同容量的STM32芯片。
这三个文件为:
startup_stm32f10x_ld.s
startup_stm32f10x_md.s
startup_stm32f10x_hd.s
其中,ld.s适用于小容量 产品;md.s适用于中等容量产品;hd适用于大容量产品;
这里的容量是指FLASH的大小.判断方法如下:
小容量:FLASH≤32K
中容量:64K≤FLASH≤128K
大容量:256K≤FLASH
HAL库:
这是ST提供的4个启动文件,分别适用于不同容量的STM32芯片。
这4个文件为:
startup_stm32f103x6.s
startup_stm32f103xb.s
startup_stm32f103xe.s
startup_stm32f103xg.s
其中,x6.s适用于小容量 产品;xb.s适用于中等容量产品;
xe适用于大容量产品;xg适用于超大容量产品
这里的容量是指FLASH的大小.判断方法如下:
小容量:16K<=FLASH≤32K
中容量:64K≤FLASH≤128K
大容量:256K≤FLASH<=512k
超大容量:768K≤FLASH<=1024K
我自己的板子stm32f103大容量类型的,所以选择的是startup_stm32f103xe.s
比如CMSIS下,Include文件夹中
和实现内核寄存器映射的core_cmx.h文件
和微控制器软件接口标准相关的cmsis_xxxx.h文件
② HALLIB文件夹
将Drivers文件夹下中的的STM32F1xx_HAL_Driver复制到HALLIB文件夹中
在这里插入图片描述
HALLIB是HAL库的缩写了,所谓的库,其实就是很多ST已经写好了,能够供咱们直接使用的.c文件
为了省事一点,直接将这个文件夹Copy到咱们自己的目录下。
③ OBJ文件夹 —— 存放杂文件
暂时放着,待会用于放置Keil5创建项目之后会生成的零零散散的文件,包括.hex文件
④ SYSTEM文件夹 —— 正点原子官方给的工具
SYSTEM 文件夹是正点原子为开发板用户编写的一套非常实用的函数库,比如系统时钟初始化,串口打印,延时函数等,从它们给的 HAL 库版本下任何一个实验中复制过来即可。
这里提供一下正点原子官方的资料,它们B站上的链接好像挂了。
链接:https://pan.baidu.com/s/14fNVsHeWp2wf8Mh_vsFm-w?pwd=ac24
提取码:ac24
⑤ USER文件夹
步骤 ① —— 移植头文件
1、CMSIS\Device文件夹下,
进入ST文件夹,
再进入STM32F1xx文件夹,
最后进入Include文件夹中,将
stm32f1xx.h,system_stm32f1xx.h 和 stm32f103xe.h
复制到 USER 目录之下。
在这里插入图片描述
1)stm32f1xx.h 头文件
它是所有 stm32f1 系列的顶层头文件。 使用 STM32F1任何型号的芯片,都需要包含这个头文件。
同理,假如使用的是F4或者F7的芯片,就得包含其他的顶层头文件了。
同时,因为 stm32f1 系列芯片型号非常多,ST为每种芯片型号其实都是有自己的头文件,这里的f1xx是一个抽象的描述,它自己会根据咱具体的板子的型号(容量作为主要区分标准),引入它们相对应的头文件。
在这里插入图片描述
2)stm32f103xe.h文件
这里是因为咱们的目前这块开发板需要会在stm32f1xx.h 的代码中,涉及这个头文件(上方图)。
假如讲究一点的开发者可以详细根据自己的开发板选择对应该的头文件,假如想省事一点,直接Ctrl + A ,然后复制所有的头文件,都放到USER目录下,反正不会报错
3)system_stm32f1xx.c/system_stm32f1xx.h 文件
头文件system_stm32f1xx.h和源文件system_stm32f1xx.c主要是声明和定义了 系统初始化函数 SystemInit 以及系统时钟更新函数SystemCoreClockUpdate。
SystemInit 函数会帮我们配置好系统时钟配置相关的各个寄存器。在启动文件 startup_stm32f103xx.s 中会设置系统复位后,直接调用 SystemInit 函数进行系统初始化。
SystemCoreClockUpdate 函数 是在系统时钟配置进行修改后,调用这个函数来更新全局变量 SystemCoreClock 的值,变量 SystemCoreClock 是一个全局变量,开放这个变量可以方便我们在用户代码中直接使用这个变量来进行一些时钟运算。
步骤② —— 复制固件库中Templat文件夹中的文件
2、将Projects文件夹下,再逐层进入到Templates文件中,Inc 和 Src 文件夹中的全部内容(总共七个文件 4个.c + 3个.h ),复制到USER目录之下。
在这里插入图片描述
移植完的效果:
在这里插入图片描述
步骤③ —— 更新main.c的内容
#include “sys.h”
#include “delay.h”
#include “usart.h”
/这个代码最后烧到开发板,跑出来的效果是两个led灯,交替闪烁/
void Delay(__IO uint32_t nCount);
void Delay(__IO uint32_t nCount)
{
while(nCount–){}
}
int main(void)
{
GPIO_InitTypeDef GPIO_Initure;
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72M
__HAL_RCC_GPIOB_CLK_ENABLE(); //开启GPIOB时钟
__HAL_RCC_GPIOE_CLK_ENABLE(); //开启GPIOE时钟
GPIO_Initure.Pin=GPIO_PIN_5; //PB5
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; //高速
HAL_GPIO_Init(GPIOB,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_5; //PE5
HAL_GPIO_Init(GPIOE,&GPIO_Initure);
while(1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET); //PB5置1
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET); //PE5置1
Delay(0x7FFFFF);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET); //PB5置0
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET); //PE5置0
Delay(0x7FFFFF);
}
}
⑥ HARDWARE文件夹
该文件夹在正点原子里是用来放项目用到的外设,比如ADC、LED、DMA等等。在野火的教学中,是在User目录下,各自创建相应的外设的文件夹,这里比较灵活,不一定有,根据自己需求吧,只是简单介绍一下。
在这里插入图片描述
3.3)在Keil5中新建项目
在Keil中新建的工程时,命名可以完全和本地磁盘新建的文件夹名字相同。
在这里插入图片描述
这里的流程就和野火中差不多了,新建工程时候,位置选择为本地创建工程中USER文件夹下,不反复造轮子啦~
在这里插入图片描述
USER文件夹最后是会作为Keil5中创建的项目的保存路径,也就是将Keil这个管家放到USER目录。
在这里插入图片描述
Markdown 已选中 9 字数 1 行数 当前行 445, 当前列 11 文章已保存10:51:59HTML 7603 字数 247 段落