STM32配置库函数新建工程(2)

这里跳过了软件安装过程,如需资料,可到B站江科大STM32视频处下载。


目录

一、STM32的开发方式

二、新建一个基于寄存器开发的工程

三、通过配置寄存器来完成点灯

1、硬件接线

2、配置调试器

3、配置寄存器点灯

四、配置库函数

五、通过库函数来完成点灯

六、新建工程的启动文件选择

七、新建工程步骤

八、工程架构


一、STM32的开发方式

        目前STM32的开发方式主要有基于寄存器的方式、基于标准库(库函数)的方式和基于HAL库的方式。

        基于寄存器的方式和51单片机的开发方式一样,是用程序直接配置寄存器,来达到我们想要的功能,这种方式最底层、最直接、效率会更高一些,但是由于STM32的结构复杂、寄存器太多,所以基于寄存器的方式不是很推荐。

        基于库函数的方式是使用ST官方提供的封装好的函数,通过调用这些函数来间接地配置寄存器,由于ST对寄存器封装的比较好,所以这种方式既能满足对寄存器的配置,对开发人员也比较友好,有利于提高开发效率,本课程使用的就是库函数的开发方式。

        基于HAL库的方式可以用图形化界面快速配置STM32,这个比较适合快速上手STM32的情况,但是这种方式隐藏了底层逻辑,如果对STM32不熟悉,基本只能停留在很浅的水平,所以暂时不推荐HAL库,但是推荐学过标准库以后,再去了解HAL库的方式。


二、新建一个基于寄存器开发的工程

新建一个文件夹在桌面,命名为STM32Project。

打开安装完的Keil uVision5 文件,点击Project,选择创建新的工程

选择刚刚创建的STM32Project文件夹,再新建一个文档,命名为2.1  STM32工程模板。

 点击进入2.1  STM32工程模板文件夹,给工程命名为Project,然后再选择保存。

选择器件型号,选中STM32F103C8,点击OK

 

这里会跳出一个新建工程小助手,可以帮助我们快速新建工程,但是现阶段暂不需要,直接关掉即可。 

这样工程就建好了,但是这里的工程文件还是空的,这个工程还不能直接使用,我们需要添加一些工程的必要文件。

 

在B站江科大视频下载的资料中,打开固件库,依次打开如下文件 

固件库\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\

STM32F10x\startup\arm

这些就是STM32的启动文件,STM32的程序就是从启动文件开始执行的,将这写文件都复制下来,复制到工程模板文件中。

 

在工程模板文件中,新建一个文件夹Start,然后将这些启动文件复制到其中。 

接下来回到固件库的STM32F10x文件中,将红框内的三个文件复制到工程文件夹中的Start文件中。

stm32f10x.h就是STM32的外设寄存器描述文件, 它的作用就跟51单片机的头文件REGX52.H一样,是用来描述STM32有哪些寄存器和它对应的地址的。

下面两个system文件是用来配置时钟的,STM32主频是72MHz,就是system文件里的函数配置的。

 

然后再回到固件库中的CM3文件夹中的CoreSupport文件夹,将这两个core_cm3文件也复制到工程文件夹中的Start文件中。

因为STM32是内核和内核外围的设备组成的,而且这个内核的寄存器描述和外围设备的描述文件不是在一起的,所以还需要添加一个内核寄存器的描述文件,上图中红框内的两个文件core_cm3,即内核的寄存器描述文件。 

将Source Group 1文件名,改成Start后,在选择添加文件夹,如上图所示,选择第三个

选择Start文件夹,然后在下面的文件类型中,选择ALL files ,这样我们就能看到文件夹里的所有文件。

 先添加一下启动文件,这个启动文件有很多分类,我们只能选择添加其中一个,选择后缀为md.s的启动文件,然后剩下的.c和.h文件都要添加进去,我们可以按住Ctrl键,然后依次选中它们,点击add,最后Close。

 这样,Start文件夹里的文件就添加好了,这里的文件都是STM32里最基本的文件,是不需要我们修改的,添加进来即可,文件的图标上面带了一个小钥匙,这个意思是它是个只读文件,里面的信息我们是无法修改的。

最后我们需要在工程选项里添加上这个文件夹的头文件路径,不然软件是找不到.h文件的 ,按上面图片内,红色框内依次点击下来,就可添加成功头文件路径。

在工程文件夹中,新建一个文件命名User,main函数就放在这个文件夹里。

 在Keil软件中,右键Target,点击Add Group添加组,改个名叫User

右键User文件夹,点击第二个添加新文件,选择第一个C File,然后输入Name名字,main,

注意路径是放再User文件夹中,点击右边三个点,选中User文件夹,

最后再点击Add添加,这样主函数就创建好了。

在主函数空白处,右键,选则第二个插入头文件,选则stm32f10x.h

在主函数输入下面代码

#include "stm32f10x.h"                  // Device header

int main(void)			//int型返回值,void参数的函数
{
	while(1)
	{
	
	}

}

先点击保存后,然后点击上图红色框内按钮,编译并建立工程。

出现0错误,0警告,即工程建立成功。 

这个工程目前还没有添加STM32的库函数,所以它还是一个基于寄存器开发的工程,如果想用寄存器开发STM32,那工程建到这里就可以了。


三、通过配置寄存器来完成点灯

1、硬件接线

需要STM32最小系统板、杜邦线、ST-LINK,按上图方式连接,STM32最小系统板上有英文标识,在ST-LINK没有,注意是连接在ST-LINK上的下面这排线上。

插上以后,电源灯(红灯)会一直常亮,蓝灯是芯片里的一个测试程序,默认是闪烁状态。

2、配置调试器

接下来在Keil里配置调试器,首先点击魔术棒按钮,然后点击Debug,在Use选项中,调试器默认是ULINK,我们用的是ST Link,所以更改成ST Link Debugger,之后再点击右边的Settings,进入另外一个界面,点击Flash Download,把Reset and Run选项勾上,这样我们下载程序后会立马复位并执行,否则每次下载程序后,还需要按一下板子上面的复位按键才能执行程序,再点击确定,退出页面,再点击OK,完成设置。

配置完调试器后,点击上图中的LOAD按钮,如果一切正常的话,这个程序就会下载到STM32里面了,这时候可以看到板子上的蓝等已经不闪烁了,因为程序里面什么都没有。

3、配置寄存器点灯

打开STM32的参考手册,首先是RCC的一个寄存器,来使能GPIOC的时钟,GPIO都是APB2的外设,所以在APB2外设时钟使能寄存器RCC_APB2ENR里面配置。

第四位IOPCEN,使能GPIOC的时钟。

写1就是打开GPIOC的时钟,所以第四位写1,其他无关项都给0,0000 0000 0000 0000
0000 0000 0001 0000B,整个寄存器的二进制数据换成16进制,即0000 0010H。

在主函数写上,RCC->APB2ENR = 0x00000010,这样就可以打开GPIOC的时钟了。

然后是第二个寄存器,我们需要配置一下PC13口的模式,找到端口配置高寄存器GPIOx CRH,这个x可以是A到E的任意一个字母,右边的CNF13和MODE13就是用来配置13号口的。

CNF需要配置为通用推挽输出模式,也就是这两位为00,MODE要配置为输出模式,最大速度可以给到50MHz,也就是这两位为11,其他位都位0,这样整个寄存器的值二进制为
0000 0000 0011 0000 0000 0000 0000 0000,转换成16进制为0030 0000H。

在主函数上写上GPIOC->CRH = 0X00300000,这样就完成了P13口的模式配置。

最后即可以给P13口输出数据,端口输出寄存器为GPIOx_ODR,中间有一位ODR13,
这一位写1,13号口就是高电平,写0就是低电平。

写1,ODR的值就是0000 2000H;写0,ODR的值就是0000 000H。

在主函数上写GPIOC->ODR = 0x00000000,将P13口点亮。

在主函数上写GPIOC->ODR = 0x00002000,将P13口熄灭。

#include "stm32f10x.h"                  // Device header

int main(void)							//int型返回值,void参数的函数
{
	RCC->APB2ENR = 0x00000010;			//打开GPIOC时钟
	GPIOC->CRH = 0x00300000;			//P13口的模式配置
	GPIOC->ODR = 0x00000000;			//给P13口输出数据,ODR第13位为0,P13口灯亮。
	while(1)
	{
	
	}

}

实物图

        这就是配置寄存器的方式进行电灯的操作,这种方式需要不断地查手册来了解每隔寄存器的每一位都是干啥的,但是这个操作方式也有个弊端,就是我们把除了PC13之外的位都配置成了0,这样会影响到其他端口的原有配置,如果要做到只配置PC13而不影响其他位,那还需要&=和|=的操作,这样就会更麻烦,所以这种寄存器的操作方式,虽然代码简洁,但是还是不太方便。


四、配置库函数

打开工程文件夹,在这里新建一个文件夹,命名Library,用来存放库函数。

打开固件库文件夹,按上图顺序依次打开文件Libraries > STM32F10x_StdPeriph_Driver > src, 这些就是库函数得源文件了,misc是内核的库函数,其他的就是内核外的外设库函数,将上面文件都复制到工程文件中的Library文件中。

然后再打开Libraries > STM32F10x_StdPeriph_Driver > inc 文件夹,这些是库函数的头文件,将这些文件也复制到工程文件中的Library文件中。

回到Keil软件,在Target处右键,然后添加组

将添加的Group改名为Libray。

 

 

按上述图片步骤操作,即可将Library的文件都添加到Keil软件中。

 

 

        接下来再打开固件库中的文件,目录如上,文件夹中的conf.h结尾的文件是用来配置库函数头文件的包含关系的,另外这里面还有个用来参数检查的函数定义,这是所有库函数都需要的;两个it结尾的文件是用来存放中断函数的。

        复制红框内的三个文件,到工程文件中的User文件下,然后再回到Keil软件中,在User组里,把刚才那三个文件添加进来。 

最后还需要一个宏定义,将鼠标放到主函数的第一行,在头文件处右键,打开stm32f10x.h,翻到最下面,将8296行红框内的英文复制下来,这个语句是一个条件编译,意思是如果定义了这个这个字符串,下面这个语句才有效,打开工程选项,在C/C++的Define栏目粘贴这个字符串,这样才能包含标准外设库,也就是库函数。

还有下面的头文件路径,把User和Library目录的路径也都添加上,然后OK,这样基于库函数的工程就建好了。

 最后将Library文件往上挪一下,这样就将不用改的文件都放上面了,User就是我们需要编辑的文件。

 将文件保存,然后编译运行,出现0错误,0警告,就说明我们的工程是建立成功的。


五、通过库函数来完成点灯

首先设置代码自动补全联想:点击上方Edit/最底下的Configuration/第一排Text Completion /勾选Symbols after3 Characters保存,这样能能快捷的找到想使用的函数。

输入完函数后,再输入一个单括号,能够出现提示后面参数的类型,第一个是选择外设,第二个是选择新的状态。

也可以在函数位置右键,跳到函数定义,这里面有函数的简介和参数说明。 

函数简介:使能(打开)或失能(关闭)APB2的外设时钟

第一个参数可以是下面这些值:

找到APB2外设GPIOC这一项,然后复制,作为第一个函数。

第二个参数NewState的值可以是ENABLE或者DISABLE;

复制 ENABLE,放在第二个参数的位置,输入一下代码,即完成使能时钟。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);	

第二步是配置端口模式,需要用到GPIO_Init这个函数,然后有两个参数,第一个是选择哪个GPIO口,第二个是参数的结构体。

跟之前相同,先去到函数的定义,可以看到函数的介绍,是根据GPIO_Init结构体参数来配置GPIO,第一个参数GPIOx,其中x可以是A到G,来选择要配置的GPIO口,我们是PC13口的LED,所以第一个参数就写GPIOC。

 第二个参数是一个GPIO_InitTypeDef 的结构体,我们需要先定义一个结构体,给它起一个名字,命名为GPIO_InitStructure,然后把结构体的每一个参数填上。

再下一行,复制粘贴结构体GPIO_InitStructure的名字,然后用.点来引出结构体的参数,可以看到结构体有三个参数,分别是GPIO模式、GPIO端口、GPIO速度。

然后将三个参数罗列出来,然后在GPIO模式参数哪一行,右键转到Mode的定义。

右边的介绍说,这个参数可以是GPIOMode_TypeDef里面的一个值,注释里面的东西没办法用右键跳转,这里需要选中字符,按一下Ctrl+F,点击Find_Next,搜索一下这个定义的位置。

可以看到,这里是个枚举,GPIOMode就是这里的其中一个值,然后我们选择OUT_PP这一项,复制,这个就是通用推挽输出,粘贴到GPIO_Mode那里这样这个参数就配置好了。

(枚举是 C 语言中的一种基本数据类型,用于定义一组具有离散值的常量。)

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

然后到下一个参数GPIO_Pin,转到它的定义,这里下面会出现一个Browser的框,意思是它的定义有很多个,选择member这一项,双击,就会跳转到还是刚才那个位置。

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; 

看一下这个GPIO_Pin的说明,这个参数在GPIO_pins_define里面定义了,然后选中GPIO_pins_define,Ctrl+F,点击Find_Next,搜索一下这个定义的位置,可以看到这里有一个宏定义的列表,选中GPIO_Pin_13,复制,然后填在第二个参数的位置。

第三个参数GPIO_Speed也一样,转到它的定义,选中说明里面的GPIOSpeed_TypeDef,Ctrl+F,点击Find_Next,搜索一下这个定义的位置,在这里选中50MHz的速度,复制GPIO_Speed_50MHz,粘贴到第三个参数的位置。

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

这样,结构体变量就有了,我们就可填这个GPIO_Init的第二个参数了,第二个参数是一个指向结构体的指针,所以这里我们需要传递结构体的地址,复制结构体的名字,然后前面加上一个取地址的符号(&),最后打上右括号,分号,这个GPIO模式配置就完成了。

GPIO_Init(GPIOC, &GPIO_InitStructure);

 最后我们设置端口的高低电平来进行电灯,这里有一个函数GPIO_SetBits,这个就可以把指定端口设置为高电平,同样也可以右键转到定义看参数类型,这里就直接填了,第一个参数填GPIOC,第二个是GPIO_Pin_13;另一个函数是将端口设置为低电平,叫 GPIO_ResetBits参数相同。

	GPIO_SetBits(GPIOC,GPIO_Pin_13);									//设置端口高电平
    GPIO_ResetBits(GPIOC,GPIO_Pin_13);									//设置端口低电平

通过以下代码,即可将最小系统板上的PC13关闭,将端口设置为低电平,即可将PC13点亮。

#include "stm32f10x.h"                  // Device header

int main(void)							//int型返回值,void参数的函数
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);		//使能时钟
	GPIO_InitTypeDef GPIO_InitStructure;						//GPIO_InitTypeDef结构体类型
																//GPIO_InitStructure用结构体类型定义的变量
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);						//GPIO模式配置
	GPIO_SetBits(GPIOC,GPIO_Pin_13);							//设置端口高电平
//	GPIO_ResetBits(GPIOC,GPIO_Pin_13);							//设置端口低电平
	while(1)
	{
	
	}

}

六、新建工程的启动文件选择

新建工程第一个加的就是启动文件,启动文件有很多类型,至于选择哪一个,我们要根据芯片型号来选择,如上表。

STM32F100系列,ST公司把它叫做超值系列,简写为VL,如果使用STM32F100的型号,就选择带VL的启动文件,然后再根据Flash的大小,选择LD、MD还是HD;

这里是STM32F1系列中的型号分类,其中根据Flash容量的大小,而进行了分类,如果使用STM32F101/102/103的型号,就选择不带VL的启动文件,然后再根据Flash的大小,选择LD、MD、HD和XL;

而STM32F105和107,ST公司把它叫做互联网产品,如果使用STM32F105/107的型号,直接选择CL的启动文件即可;

因此我们使用的是STM32F103的芯片,又C8T6的Flash是64K,所以选择MD的启动文件。


七、新建工程步骤

(1)建立工程文件夹,Keil中新建工程,选择型号

(2)工程文件夹里建立Start、Library、User等文件夹,复制固件库里面的文件到工程文件夹

(3)在Keil软件里对应建立Start、Library、User等同名称的分组,然后将文件夹内的文件添加到工程分组中

(4)工程选项,C/C++,Include Paths内声明所有包含头文件的文件夹

(5)工程选项,C/C++,Define内定义USE_STDPERIPH_DRIVER

(6)工程选项,Debug,下拉列表选择对应调试器,Settings,Flash Download里勾选Reset and Run


八、工程架构

        首先是左边的startup启动文件,这个是程序执行最基本的文件,Keil中的启动文件是用汇编写的,启动文件内定义了中断向量表,中断服务函数等,中断服务函数中有个复位中断,这就是整个程序的入口,当STM32上电复位或者按下复位键后,程序就会进入复位中断函数执行,复位中断函数主要就做了两件事情,第一个是调用SystemInit函数,第二个是调用main函数,对应启动文件如下图,这是复位的中断函数,然后调用SystemInit,再调用main。

         SystemInit函数就是定义在中间的system开头的.c文件里,在文件中,也能看到SystemInit函数的作用,是设置微控制器的启动,初始化嵌入式闪存接口,锁相环,更新系统内核的时钟变量,下面的note写的是这个函数仅在复位后需要调用。

        下面很多程序都是用来配置这个函数的,不需要我们更改,我们只要知道,在执行main函数前,单片机就已经执行了一堆东西了,帮我们把这个闪存接口,时钟等一系列杂碎的东西都配置好了。

        另外在启动文件中,还定义了STM32所有的其他中断,这些中断达到触发条件后,就会自动执行,这个中断函数的定义,就是在stm32fx_it里面的,这些就是中断部分的执行逻辑了。

                另外我们也可以自己定义一些用户文件,来封装一些模块供主函数和中断调用,同时也有利于我们程序结构的模块化,至此工程结构主动执行的部分就结束了。

        下面就是一些被动执行的东西了,相当于STM32的一些资源,我们在主函数或者中断函数中,就可以调用这些资源。

        stm32f10x.h和core_cm3这些文件就是外设和内核外设的寄存器描述,stm32f10x.h文件中都是寄存器和今存其每一位的名字,还有地址信息等,如果直接调用这些寄存器来使用STM32,那就是寄存器的开发方式,这种方式有一些弊端,也很麻烦,所以ST公司就提供了下面两个文件,这个就是库函数文件。

在Keil中可以看到,每个外设都提供了一大堆的函数,这些函数封装了寄存器的操作,给我们提供了更加人性化的函数调用方式,只要学会了操作套路,那配置一个外设就是很简单的,连手册都不需要看。

conf文件就是用来配置头文件的包含关系的,include了所有的库函数的头文件,同时我们在stm32fx.h的最后,又包含了conf,所以在使用这些库函数时,我们只需要包含stm32f10x.h这一个头文件,就相当于包含了所有的库函数头文件,这样我们就可以任意地调用库函数了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

剑鞘的流苏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值