STM32--新建STM32工程

一、STM32 工程开发方式介绍

STM32 工程结构复杂,代码建立在工程结构之上。

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

  1. 基于寄存器方式与五一单片机开发方式类似,直接配置寄存器,这种方式最底层、最直接、效率更高,但因 STM32 结构复杂、寄存器多,目前不推荐。
  2. 基于库函数方式使用官方封装好的函数间接配置寄存器,由于ST对于寄存器封装较好,所以这种方式既能满足对寄存器的配置,而且对开发人员友好,有利于提高开发效率,本文采用此方式。
  3. 基于 HAL 库方式可通过图形化界面快速配置 STM32,适合快速上手,但隐藏底层逻辑,不熟悉 STM32 时只能停留在较浅水平,推荐学过标准库后了解。

二、准备库函数压缩包

  1. 使用库函数方式需要准备 STM32 库函数压缩包,可在下方提供的资料链接中找到固件库文件。

解压后的固件库文件

  1. 解压后的库函数文件夹包含多个部分:
    第一个文件夹有两个图片,用处不大。
    第二个文件夹 “libraries” 是库函数文件,建工程时会用到。
    第三个文件夹 “project” 是官方提供的工程示例和模板,可参考使用。
    第四个文件夹 “utilities” 是 STM32 官方评估版的相关例程。
    还有库函数的发布文档和使用手册。

三、新建基于标准库的工程

  1. ’建立存放工程的文件夹,如在桌面新建 “sm32 project” 文件夹。
  2. 打开 Keil 软件,点击 “Project - New μVision Project”,选择新建的文件夹,再新建一个文件夹存放本次工程,命名为 “2-1 stm32 工程模板”。
  3. 给工程文件起通用名字 “project”,点击保存。
  4. 选择器件型号为 “STM32F103C8”,点击 OK。
  5. 此时弹出新建工程小助手,暂不用可擦掉。工程建好后文件为空,需添加必要文件。

四、添加工程必要文件

  1. 打开固件库文件夹,找到 STM32 的启动文件所在路径(打开Libraries, CMSIS, CM3, DeviceSupport, STM32F10x,startup, arm),将启动文件复制到新建的工程文件夹中的 “start” 文件夹。
  2. 回到固件库文件夹,将 “STM32F10x.h(外设寄存器描述文件)”、两个 “system(用于配置时钟)” 开头的文件及内核计算器描述文件复制到 “start” 文件夹。
  3. 由于STM32是内核和内核外围的设备组成,并且内核的寄存器描述与外围设备的描述文件是不在一起的,所以还需要添加一个内核寄存器的描述文件。其中的cm3文件就是内核寄存器描述文件。

补充:
外设寄存器描述文件:作用与51单片机头文件REGX52.H一样,用于描述STM32有哪些寄存器和它对应的地址的。
system(用于配置时钟):STM32主频72MHz,就是该文件里的函数配置的。
内核寄存器描述文件:其中还带了一些内核配置函数,所以有一个.c文件,也需要一并复制到Stat文件夹中。

到此工程的必要文件的复制就完成了,后面需要回到Keil软件将复制的文件添加到工程中。

五、在工程中添加文件及设置头文件路径

  1. 在 Keil 软件中,将复制的文件添加到工程里。点击选中 “Source Group”,改名为 “start”,右键选择 “添加已经存在的文件到组里来”,添加启动文件及其他文件,这里的文件都是STM32中最基本的文件,是不需要我们修改的我们添加进来即可
    添加进来的文件
    注意:文件中的小钥匙图标,表示该文件是只允许我们阅读,不允许我们修改的文件。

  2. 在工程选项中添加 “start” 文件夹的头文件路径,否则软件是找不到.h文件的,点击 “魔术棒按钮”,在 “C/C++” 里找到 “Include Paths” 栏,新建路径并添加 “start” 的路径。

六、新建 main 函数并测试工程

  1. 在工程文件夹中新建 “user” 文件夹,在 Keil 软件中右键添加组,命名为 “User”,然后添加新文件,选择 C 文件并命名为 “main”,放在 “User” 文件夹下(记得修改路径否则是放在User文件夹外面的)。

  2. 在 “main.c” 文件中插入头文件 “stm32f10x.h”,写一个 main 函数,包含一个 while 死循环,注意 main 函数的返回值和参数类型,文件最后一行必须为空行(不然会报警告)
    插入头文件

  3. 点击编译并建立工程,若提示零错误零警告,则工程没问题。此时工程还没有添加STM32的库函数,所以还是基于寄存器开发的工程,如果你想利用寄存器开始STM32,那么到这里就可以了。以下会演示配置寄存器实现点灯操作。

七、通过配置寄存器点灯

  1. 连接 STM32 最小系统板、ST-Link 和杜邦线,配置调试器。
    其中配置调试器需要注意:
    在 Keil 软件中,点击魔术棒按钮选择 “Debug”。此时调试器默认是 “unlink”,由于使用的是 ST-Link,所以选择 “ST-Link Debug”。
    点击右边的设置按钮,在 “Flash Download” 这一项中,把 “Reset and run” 这一项勾上。勾上这一项之后,下载程序后会立马复位并执行,这样更加方便,否则每次下载之后还需要按一下板子上的复位按键才能执行程序。
    配置好调试器之后点击确认 “OK”。重新编译工程,如果没有错误,点击 “Load” 按钮将程序下载到 STM32 里面。
  2. 通过配置三个寄存器来点灯:
    配置 RCC 的一个寄存器使能 GPIOC 的时钟。
    配置 PC13 口的模式为通用推挽输出模式,最大速度 50 兆赫兹。
    给 PC13 口输出数据,低电平点亮灯。
    点灯操作的程序
    注意:
    这种通过配置寄存器来实现点灯操作,需要我们不断地查手册来了解寄存器的每一位都是干什么的,并且该方式也有弊端,就是我们把除了PC13之外的位都配置成了0,这样就会影响到其他端口的原有配置,如果要做到只配置PC13而不影响其他位那还需要&=和|=的操作,那这样就会更加麻烦。所以这种寄存器的操作方式虽然代码简洁,但是还是不太方便。所以下面会使用STM32标准库的方式进行开发,但是在使用标准库开发的前提是配置好相关的库函数文件。

八、添加库函数

  1. 在工程文件夹中新建 “library” 文件夹,存放库函数。
  2. 打开固件库文件夹,将库函数的源文件和头文件复制到 “library” 文件夹。
  3. 在 Keil 软件中添加组 “library”,将库函数文件添加进来(打开固件库的文件夹,打开Libraries,STM32标准外设驱动(STM32F10x_StdPeriph_Driver),src/inc),其中src中存放着库函数的源文件,inc存放着库函数的头文件,将他们添加进工程文件中,但是此时的库函数还不能直接使用。
  4. 复制固件库中的三个文件到工程的 “user” 目录下(打开固件库文件夹,打开Project,STM32Template,stm32f10x conf.h和两个it结尾的文件),并在 Keil 软件中添加到右侧组里。
    这三个文件分别为:
    stm32f10x_conf.h 文件
    用途:用来配置库函数头文件的包含关系。
    特点:这里面还有一个用来参数检查的函数定义。所有库函数都需要这个文件,它起到了协调和组织各个库函数头文件之间关系的作用。
    两个以 it 结尾的文件
    用途:用来存放中断函数。
    特点:启动文件中定义了 STM32 所有的其他中断,当中断达到触发条件后就会自动执行,而这些中断函数的定义就在这两个以 it 结尾的文件里。同时,ST 公司也建议可以把自己定义的中断写在这个位置,当然也可以根据习惯写在其他地方使用中断的位置。
    这三个文件对于构建基于库函数的 STM32 工程非常重要,确保了工程在中断处理和库函数配置方面的完整性和正确性。
  5. 头文件中添加宏定义,打开工程选项(魔术棒),在 “C/C++”“Define” 栏目粘贴字符串**“USE_STDPERIPH_DRIVER”,并添加头文件路径以确保软件能够找到头文件,通过以上步骤,就完成了添加头文件的操作,使得基于库函数的工程能够正确地包含所需的头文件,从而能够顺利地调用库函数进行开发**。
    这里已经将库函数的文件已经配置完成,下面就可以利用这些库函数实现点灯的操作了。

九、用库函数实现点灯操作

用库函数也是间接配置寄存器实现点灯操作与寄存器方式步骤类似,但更方便。

步骤:

一、使能(开启)时钟

使用库函数开启时钟,找到函数

RCC_APB2PeriphClockCmd(外设时钟控制)

该函数有两个参数,第一个参数选择外设,可以通过右键跳到函数定义查看函数的简介和说明,找到APB2 外设 GPIO C这一项,复制作为第一个参数(即RCC_APB2Periph_GPIOC)。
第二个参数选择新的状态,查看参数说明可知newstate的值可以是ENABLE或者DISABLE,复制ENABLE放在第二个参数的位置。

完整的代码为:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

这样就配置好了GPIOC的外设时钟,并且不会影响寄存器的其他位。
补充:
在翻找函数简介时可以找到这函数的具体内容,内部还是配置了RCC_APB2ENR这个寄存器,但是在经过了函数的包装之后,就不需要再去查手册,来确认哪一位具体是干什么的了,并且在函数中也利用了**|=&=帮助我们操作过了,所以此库函数的配置也不会影响到寄存器的其他位**,这就是库函数和寄存器的区别,虽然库函数的代码比寄存器更长,但是语义更加明确,也不需要再去查表计算寄存器的值了,只需要调用库函数,在按照函数提示填好参数即可。

使能时钟函数的具体内容

二、配置端口模式

使用函数GPIO_Init来配置端口模式,该函数有两个参数。
第一个参数选择要配置的GPIO,因为是配置PC13口的LED,所以第一个参数写GPIOC
第二个参数是一个参数的结构体需要先定义一个结构体变量
定义结构体变量的步骤如下:

  1. 首先在上面写下结构体的类型,然后给结构体起名为GPIO_InitStructure(根据官方推荐命名)
    复制粘贴结构体的名字,用点引出结构体的参数,该结构体有三个参数,分别是GPIO 模式GPIO 端口GPIO 速度
  2. 右键转到各个参数的定义去查找对应的配置值(参数中的定义需要使用Ctrl + F+Find Next查找):
    对于GPIO 模式,选中参数按Ctrl + F搜索定义位置,找到发现是一个枚举,选择GPIO_Mode_Out_PP(通用推挽输出) 复制,然后在结构体参数中写上GPIO_Mode_Out_PP。
    对于GPIO 端口,右键的方法发现其有多个定义,双击member这一项,再利用Ctrl + F的方法查找GPIO_ pins_define找到对应的宏定义列表,选择GPIO_Pin_13复制,在结构体参数中填上该值,表示配置PC13口
    对于GPIO 速度,找到 50 兆赫兹的速度对应的配置值复制,在结构体参数中填上该值。

最后,因为函数的第二个参数是一个指向结构体的指针,所以需要传递结构体的地址,复制结构体的名字粘贴到该位置,前面加上一个取地址符号,再加上右括号和分号,完整的代码为

GPIO_InitTypeDef GPIO_InitStructure;   //定义结构体
GPIO_Initstructure.GPIO_Mode = GPIO_Mode_outPP;
GPIO_Initstructure.GPIO_Pin = GPIO_Pin_13;
GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure);  //声明函数

这样就完成了GPIOC端口模式的配置。

三、设置端口高低电平来点灯

设置端口为高电平:使用函数GPIO_SetBits(指定端口输出高电平的函数),参数说明可以通过右键查看。这里直接填参数,第一个参数是GPIOC,第二个参数是GPIO_Pin_13

GPIO_SetBits(GPIOC, GPIO_Pin_13);

这一句就可以将PC13号口置为高电平

设置端口为低电平:使用函数GPIO_ResetBits(指定端口输出低电平的函数),参数同样是GPIOCGPIO_Pin_13

GPIO_ResetBits(GPIOC, GPIO_Pin_13);

这一句就可以将PC13号口设为低电平

通过以上步骤,就实现了使用库函数来点灯的操作。

使用库函数开启时钟,不会影响寄存器其他位。配置端口模式,使用结构体配置参数,代码逻辑较复杂但语义明确。设置端口高低电平来点灯。

十、补充内容

  1. 新建工程里启动文件(Strar文件夹中的文件(startup_stm32f10x_md.s))的选择根据芯片型号flash 大小确定。
    STM32F1系列型号分类

  2. 总结新建工程的步骤:
    第一步:建立工程文件夹,在 Keil 中新建工程选择型号。
    第二步:建立工程文件夹中的子文件夹,复制固件库文件到子文件夹,为了添加工程文件为准备,建立子文件夹是文件较多,为了方便管理。其实需要使用的文件一定要复制到子文件夹中,不要添加到工程文件夹之外,否则外面的文件一旦挪动位置,工程就找不到该文件了。
    第三步:在工程中建立与子文件夹同名的分组,添加文件,为了在keil中方便管理文件,因为keil没有办法直接添加文件夹,所以选择在keil中建立分组再把文件都添加进来。
    第四步:在工程选项中声明包含你自己设置的头文件的文件夹的路径。
    第五步:定义使用标准外设驱动的字符串,使用库函数的条件编译,使用库函数就必须定义这个。
    第六步:选择对应调试器并勾选 “reset and run”。
    新建工程的步骤

  3. 介绍工程架构:
    一、启动文件(start up)
    启动文件是程序执行最基本的文件,在 Keil 中用汇编写成。
    启动文件内定义了中断向量表中断服务函数
    中断服务函数中有个复位中断,是整个程序的入口。当 STM32 上电复位按下复位按键后,程序就会进入复位中断函数。
    执行复位中断函数主要做两件事:一是调用system_init函数,二是调用main函数。
    在 Keil 中可以看到复位中断函数的具体实现,先调用system_init,再调用main,然后程序进入main函数中的死循环,因为单片机程序实际上永远不会结束。
    二、system_init函数
    system_init函数定义在以 “system” 开头的.c文件里。
    函数作用是设置微控制器的启动初始化,包括嵌入式闪存接口锁相环更新系统内核的时钟变量等。
    函数简介和注释中说明了其作用以及仅在复位后需要调用。
    三、中断部分
    启动文件还定义了 STM32 所有的其他中断当中断达到触发条件后就会自动执行
    中断函数的定义在STM32F10x_it文件里。
    四、用户文件
    可以自己定义一些用户文件来分装一些模块,供主函数和中断调用。
    这样有利于程序结构的模块化,避免所有程序都堆在主函数里,使主函数过长。
    五、STM32 资源
    工程结构右边是 STM32 的资源,相当于被动执行的部分
    在主函数或中断函数里可以调用这些资源。
    右上角的STM32F10x.h和内核文件是外设和内核的寄存器描述文件。如果直接调用这些寄存器来使用 STM32,就是寄存器的开发方式,但这种方式有弊端且比较麻烦。
    ST 公司提供了库函数文件,每个外设都提供了一大堆函数,封装了寄存器的操作,提供更加人性化的函数调用方式。只要学会操作套路,配置一个外设就很简单,甚至连手册都不需要看一眼。
    conf文件用来配置头文件的包含关系在conf文件中include了所有的库函数头文件,同时在STM32F10x.h的最后又包含了conf文件,所以在使用库函数时,只需要包含STM32F10x.h这一个头文件,就相当于包含了所有的库函数头文件,这样就可以任意调用库函数了。

工程架构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值