目录
目前STM32的开发方式主要有基于寄存器的方式、基于标准库也就是库函数的方式和基于HAL库的方式。
基于寄存器的方式和江协之前的51单片机的开发模式一样是用程序直接配置寄存器,来达到我们想要的功能。这种方式最底层、最直接、效率会更高一些。但是由于STM32的结构复杂、寄存器太多,所以基于寄存器的方式目前是不推荐的。基于库函数的方式是使用ST官方提供的封装好的函数,通过调用这些函数来间接地配置寄存器。由于ST对寄存器封装的比较好,所以这种方式既能满足对寄存器的配置,对开发人员也比较友好,有利于提高开发效率。
我们目前先用库函数的开发方式。
最后一个基于HAL库的方式可以用图形化界面快速配置STM32,适合快速上手STM32的情况,但是这种方式隐藏了底层逻辑,如果对STM32不熟悉,基本只能停留在很浅的水平。
所以目前暂时不推荐HAL库,但是推荐你学过标准库之后,再去了解一下这个方式
E:\STM32\STM32入门教程资料\固件库\固件库\STM32F10x_StdPeriph_Lib_V3.5.0\STM32F10x_StdPeriph_Lib_V3.5.0

第二个Libraries里面就是库函数的文件了,我们之后建工程时会用到
第三个Project是官方提供的工程示例和模板,以后使用库函数的时候可以参考一下
第四个Utilities是STM32官方评估版的相关例程,这个评估版就是官方用STM32做的一个小电路板,用来测评STM32的,里面存的就是这个小电路板的测评程序
后面两个文件,一个是库函数的发布文档,一个是使用手册。
1.新建工程
1.复制工程必要文件
新建
现在就正式开始新建一个基于标准库的工程。

弹出的可以先叉掉
E:\STM32\STM32入门教程资料\固件库\固件库\STM32F10x_StdPeriph_Lib_V3.5.0\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm

这些就是STM32的启动文件,STM32的程序就是从启动文件开始执行的
在我们自己建的工程文件下将这些复制到新建的Start文件夹内


这个stm32f10x.h,就是STM32的外设寄存器描述文件。作用跟51单片机的头文件REGX52.H一样,是用来描述STM32有哪些寄存器和它对应的地址的。
两个system文件是用来配置时钟的
这三个文件也粘贴到Start文件夹内
因为这个STM32是内核和内核外围的设备组成的,而且这个内核的寄存器描述和外围设备的描述文件不是在一起的,所以我们还需要添加一个内核寄存器的描述文件。

这两个cm3(Cortex M3)文件就是内核的寄存器描述,当然他还带了一些内核的配置函数,所以多了个.c文件,我们把它俩一并复制下来,也粘贴到Start文件夹下。
到此为止我们工程的必要文件就复制完成了。


将这个文件Add进去,剩下的.c和.h都要添加进来。可以按住Ctrl键,然后依次选择
这些就是添加进来的,这个钥匙就表明是个只读的文件,最后还要在工程选项里添加上这个文件夹的头文件路径,要不然软件是找不到.h文件的
按照如下添加,接着一路ok就可以了。

在这样添加一个组

改个名字,叫做User。然后右键创建一个新的C,main.c文件

编写一段如图的代码,必须多加一行要不然会报错

标红圈的是编译并建立工程。目前还没有添加STM32的库函数,所以还是一个基于寄存器开发的工程。如果想用寄存器开发STM32,那工程建到这里就可以了。
调字体


改成UTF-8,避免一些中文乱码。且TAB改成4

2.寄存器
拿出STM32的最小系统板、STLINK和四根母对母的杜邦线
如下接线

蓝灯亮

配置一下调试器



load一下可以看到板子蓝灯不闪了,因为我们目前程序什么都没有!
打开GPIOC的时钟
首先是RCC的一个寄存器,来使能GPIOC的时钟。
GPIO都是APB2的外设,所以在这个APB2外设时钟使能寄存器RCC_APB2ENR里面配置


IOPCEN使能GPIOC的时钟的

那这个给1,其他全给0.整个寄存器的2进制数据换成16进制,四个看一起
0 0 0 0 0 0 1 0
为什么要打开 GPIOC 时钟?
只有时钟使能后,才能访问 GPIOC 的寄存器 (如
GPIOC->CRL、GPIOC->ODR、GPIOC->IDR等)。如果没有使能时钟,对 GPIOC 的任何操作(配置引脚、读写电平)都会无效,甚至可能触发硬件错误(HardFault)。

第二个寄存器,我们需要配置一下PC13口的模式

CNF13,MODE13配置13号口的。
这个CNF我们需要配置为通用推挽输出模式,也就是这两位为00
MODE要配置为输出模式,最大速度可以给50MHz,也就是这两位为11
因此这四位为0011

因此整个寄存器的值换算成16进制就是0 0 3 0 0 0 0 0
接下来给PC13口输出数据了


中间有一位ODR13,这一位写1,13号口就是高电平,写0就是低电平
如果写1的话,ODR的值就是0 0 0 0 2 0 0 0
因为这个灯是低电平点亮的,所以我们给ODR全为0就是亮,给ODR 0x00002000就是灭

先下载后编译也就是图中的标识。
ODR全为0就是亮(蓝灯亮),给ODR 0x00002000就是灭(蓝灯灭)
3.库函数
可以看出来,这种方式需要不断地查手册来了解每个寄存器的每一位都是干什么的。
而且这个操作方式也有个弊端,就是我们把除了PC13之外的位都配置成了0.
这样就会影响到其他端口的原有配置,如果要做到只配置PC13而不影响其他位,那还需要&=和|的操作。
这样配置就会特别麻烦,所以这种寄存器的操作方式,虽然代码简洁,但是还是不太方便。
那接下来我们就要为这个工程添加库函数了。
看看库函数和寄存器的操作方式有哪些区别
我们打开工程文件夹,在这里新建一个文件夹,叫Library,用来存放库函数

打开另外一个文件夹
E:\STM32\STM32入门教程资料\固件库\固件库\STM32F10x_StdPeriph_Lib_V3.5.0\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\src

除misc是内核的库函数,其他的都是内核外的外设库函数了
全复制到我们新建的文件Library中。
再打开固件库的inc文件夹,里面是库函数的头文件,同样全选复制到Library。
同样跟之前一样新建组Library,添加已存在文件,把Library的全部添加进来

但是对于这个库函数来说,现在还不能直接使用,我们需要再添加一个文件
E:\STM32\STM32入门教程资料\固件库\固件库\STM32F10x_StdPeriph_Lib_V3.5.0\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Template

这个conf (configuration) 文件是用来配置库函数头文件的包含关系的。另外这里面还有个用来参数检查的函数定义,这是所有库函数都需要的
两个it (interrupt)"文件是用来存放中断函数的
将三个文件复制下来,粘贴到工程的User目录下。

同样将新增的添加到User组里
最后还需要一个宏定义,我们可以在这个头文件右键,打开文件

滑到最下面,看到这个语句,这是一个条件编译

意思是如果你定义了USE_STDPERIPH_DRIVER这个字符串
标准外设驱动
下面这个include conf.h语句才有效
在C/C++的Define栏目粘贴这个字符串

这样才能包含标准外设库,也就是库函数
当然还有下面的头文件路径,也不要忘了
可以看到Library里面的有钥匙无法更改,所以更改User组里面的就可以

这样可以将Library上移。
现在用库函数实现点灯的操作。
库函数也是间接地配置寄存器,所以步骤也是一样的。
首先是使能时钟,那库函数就有这样一个函数来开启时钟
RCC_APB2PeriphClockCmd

两个参数,第一个是选择外设,第二个是选择新的状态
同样可以右键跳转过去,"跳到函数定义,上面有函数的简介和参数说明

简介说这个函数是用来使能或者失能APB2的外设时钟,第一个参数可以是下面这些值。
那我们可以找到APB2外设GPIOC这一项,然后复制直接作为第一个参数,
第二个参数可以是ENABLE或者DISABLE,复制ENABLE放在第二个参数的位置
这样GPIOC的外设时钟就配置好了
我们看这个源码,其实可以发现内部还是配置RCC_APB2ENR这个寄存器

但是经过函数的包装,我们不需要再去查手册,来确定哪一位是干啥的了。
而且,这里他已经帮我们用来|=和&=来操作了,所以这个库函数的配置是不会影响到寄存器的其他位的
这就是库函数和寄存器的区别
我们看到这个代码虽然比寄存器长,但是语义更加明确,也不需要我们再查表计算这个寄存器的值了。我们只需要调用库函数,按照它的提示,把参数填好就行了。
所以说从这点对比上来看,库函数是比寄存器是有很大优势的。
现在继续配置,我们需要用到GPIO_init这个函数。
然后有两个参数,第一个是选择哪个GPIO,第二个是参数的结构体


可以看到这个函数的介绍是根据GPIO_Init结构体的参数来配置GPIO
第一个参数GPIOX,其中x可以是A到G,来选择你要配置哪个GPIO
那我们是PC13口的LED,所以第一个参数就写GPIOC
第二个参数是一个GPIO_InitypeDef的结构体,我们需要先定义一个结构体
名字可以随便起,但是最好还是根据官方推荐

可以看到这个结构体有三个参数,分别是GPIO模式、GPIO端口、GPIO速度

Mode跳转一下

Ctrl+F搜索

点击Find Next,可以看到,这是个枚举,GPIOMode就是这里的其中一个值
然后我们选择Out_PP这一项,复制,这个就是通用推挽输出

这样这个参数就配置好了
同理
然后发现这个有框跳出来,说明定义有很多个

我们选择member的这个

同样去搜索

复制GPIO_Pin_13,填在第二个参数中
第三个一样


复制GPIO_Speed_50MHz

第二个参数是一个指向结构体的指针,所以这里我们需要传递结构体的地址。
复制结构体的名字,粘贴,然后前面加上一个取地址的符号(&)

这样就配置完成了。
这个配置的操作方式看上去比较难理解,但是STM32的这种方式都是固定的
最后我们设置端回的高低电平来进行点灯
这里有个函数GPIO_SetBits,这个就可以把指定端回设置为高电平
GPIO_SetBits(GPIOC,GPIO_Pin_13);//将PC13号口置为高电平
这里有个函数GPIO_ResetBits,这个就可以把指定端回设置为低电平
GPIO_ResetBits(GPIOC,GPIO_Pin_13);//将PC13号口置为低电平
2.
型号分类及缩写
我们新建文件加的第一个就是启动文件。启动文件有很多类型,至于选择哪一个,要根据芯片型号来选择。

我们看到这个表,这是STM32F1系列中的型号分类,其中根据Flash大小,分为了小容量产品,Flash为16-32K,简写为LD(Low Density)。
大容量产品,Flash为256~512K,简写为HD(High Density)
加大容量产品,Flash大于512K,简写为XL(Extra Large)
那STM32F100的系列呢,ST把它叫做超值系列,简写为VL(Value Line)
STM32F105和107,ST把它叫做互联型产品(CL,Connectivity Line)
反正就是根据自己对应的进行选择

再说一下新建工程步骤
建立工程文件夹,Keil中新建工程,选择型号
工程文件夹里建立Start、Library、User等文件夹,复制固件库里面的文件到工程文件夹
工程里对应建立Start、Library、User等同名称的分组,然后将文件夹内的文件添加到工程分组里
工程选项,C/C++,Include Paths内声明所有包含头文件的文件夹
工程选项,C/C++,Define内定义USE_STDPERIPH_DRIVER
工程选项,Debug,下拉列表选择对应调试器,Settings,Flash Download里勾选Reset and Run
工程架构

中断服务函数中有个复位中断,这就是整个程序的入口
当STM32上电复位或者按下复位键之后,程序就会进入复位中断函数执行
复位中断函数主要就做了两件事情,第一个是调用Systemlnit函数。第二个是调用main函数,对应启动文件的这里

Systemlnit函数就是定义在这个system开头.c里的
在Keil里我们也可以看到这个函数的定义

这里的简介写了这个函数的作用,是设置微控制器的启动
初始化嵌入式闪存接口、锁相环、更新系统内核的时钟变量
下面的note写的是这个函数仅在复位后需要调用
我们只需要知道,在main函数之前,单片机就已经执行了一堆西了
帮我们把这个闪存接口,时钟等一系列杂碎的东西都配置好了
另外在启动文件还定义了STM32所有的其他中断
这些中断达到触发条件后就会自动执行
右上角这两个stm32f10x.h和core_cm3这些文件,就是外设和内核外设的寄存器描述

这里面都是寄存器和寄存器每一位的名字,还有地址信息等
如果直接调用这些寄存器来使用STM32,那就是寄存器的开发方式
ST公司就提供了右下角这两个文件,这个就是库函数文件
每个外设都提供了一大堆的函数,这些函数封装了寄存器的操作,给我们提供更加人性化的函数调用方式,只要学会了操作套路,那配置一个外设就是很简单的,连手册都不需要看一眼
这个conf的文件就是用来配置头文件的包含关系的
所以,在使用这些库函数时,我们只需要包含stm32f10x.h这一个头文件,这样我就可以任意调用库函数了。
下一节,就开始从这个工程上学习STM32的第一个外设-GPIO。
感谢你的观看,期待我们下次再见!