【STM32】标准库开发概述与GPIO简介

前言

  因为各种原因,STM32的学习势在必行,没办法,但是为了高质量学习,我先整理汇总了此前找到的多个资料,打算写一篇系统性的学习笔记。

对于一款单片机的学习,我认为一般要注意以下几点:

  • 明确芯片引脚及片上外设,如IO口,中断,定时器,串行口,ADC等
  • 数据手册,方便查阅在使用某个模块时查询响应的寄存器或者程序
  • 例程,一般来说,官方会给出一定的例程,方便使用者学习使用。
  • 多多练习

参考链接

以下文字和图片大部分出自本视频教程中的内容。

STM32F103系列芯片概述

  STM32是ST(意法半导体)公司基于ARM Cortex-M内核开发的32位单片机,所谓M,即Microcontroller的首字母缩写,32代表该单片机为32位。

内核认识与产品选型

  STM32是基于ARM内核设计的,但似乎很多人无法区分内核和单片机的关系。而这个视频就详细讲述了这点。如下图所示:
在这里插入图片描述
  简单来说,就是ARM公司提供内核,然后ST公司完善外围的存储器和外设等部分,使该单片机具有不同的功能。此外,还有其他的单片机公司也会基于ARM内核来添加其他类型的外设(Peripherals),从而形成基于ARM内核但功能、型号不同的单片机产品
  关于ARM内核的各个型号如下图所示:
在这里插入图片描述
  其中,Cortex-M系列主要用于嵌入式和单片机,也就是我们常见的STM32F103的内核。其他产品内核及特性如下图所示:
在这里插入图片描述

系统结构图

  查阅手册可以看出,小、中、大容量的产品内部结构是差不多的,如下图所示:
在这里插入图片描述
  其中,Cortex-M3为内核,ICode和DCode为内核相关的指令总线和数据总线,用来执行Flash中的程序指令,System为系统总线,用来连接其他的外设。AHB(Advanced High performance Bus)为先进高性能总线,用来连接性能要求较高的外设,如时钟RCC和复位。APB1和APB2(Advanced Peripheral Bus)为先进外设总线,用来连接片上外设,其中APB2最大时钟为72MHz,APB1最大时钟为36MHz,因为APB1、APB2时钟和AHB存在一定差异,因此需要使用桥接电路。
  需要记住的是,到底哪些外设是连接APB1,哪些是连接APB2,因为一般使用外设前都需要使能对应总线的时钟,否则外设无法运行。 其中,GPIO和各外设的 “1号选手” 挂载在APB2上,其他外设的 “非1号选手” 和ADC等就挂载在APB2上,相对较慢。

STM32F103C8T6

  以上描述的都是STM32F103系列整体性的功能与结构,具体到使用的最小系统板和它的芯片型号,也需要有一定的了解。
  该视频教程使用的是基于STM32F103C8T6芯片的最小系统板,根据选型手册,可以知道该型号的芯片主频为72MHz,供电为2.0~3.6V,一般选择3.3V供电。
  最小系统板的电路原理图如下所示:
在这里插入图片描述
  此外,还需要注意STM32的启动配置,即BOOT0和BOOT1的配置,这两个引脚决定了单片机从哪里开始执行程序,具体设置如下图所示:
在这里插入图片描述

  • 第一种模式下程序从主闪存开始启动,为正常运行程序的模式,如果使用的是ST-Link或者J-Link等仿真器来烧录程序,那么就使用这种模式。
  • 第二种模式为从系统存储器开始启动,即我们常说的BootLoader,一般用来作为串口下载使用。
  • 第三种模式使用较少,因为前面两种都是从内部的FLASH启动,也是ROM的一种,掉电程序不会消失,而从内置SRAM启动,即是将程序写入到RAM中,写入的程序掉电会消失,一般用在需要频繁调试程序的场合下。具体的应用场合和优缺点可以参考这篇文章

  此外,根据表格下面的注释可以知道,当系统复位之后,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存,此时就可以将BOOT0引脚配置为普通的IO口了。但是需要注意,如果配置成普通的IO口,那么下次就不能再直接用仿真器下载程序了。即第一种方式不能使用,需要考虑另外两种方式。

串口烧录

  如果手边没有ST-Link或者J-Link等仿真器,而且也只需要下载程序而不需要仿真,那么就可以考虑使用串口下载,也是比较方便的。
  前提是手边有一个USB转TTL模块,然后将其与芯片的串口1相连(R对T,T对R),再去网上下载FlyMcu软件,就可以烧录程序了,配置方法参考下图。

在这里插入图片描述

注意:这个软件不支持自动搜索串口,所以如果显示打不开串口,有可能是串口没有更新,点击一下搜索串口即可。

标准库开发之Keil新建工程

  STM32的开发方式,一共有三种:寄存器开发、标准库开发、HAL库开发,其中,由于STM32的寄存器都是32位,而且数量众多,所以目前很少有人用寄存器开发,大部分都是使用标准库或者HAL库来开发。这里主要介绍标准库的开发方式,因此只需要使用Keil即可。

以下操作均基于Keil v5.35版本

标准外设库配置方法

  但是,标准库开发有点小复杂,那就是这个工程文档建立较为麻烦,需要先到ST官网下载标准外设库的压缩包,然后在项目工程中添加标准外设库中的一些文件,详细步骤如下所示。

  • 打开ST官网,然后根据自己所开发的芯片系列选择对应的标准库,然后下载即可(需要登录账户)。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 创建一个工程,选择对应的芯片型号
    在这里插入图片描述
    在这里插入图片描述

  • 在项目文件夹下建立Start文件夹(名字可以随便取,以易读性为准),然后将标准库文件夹下的这些文件复制到该文件夹下:

    • Libraries\CMSIS\CM3\CoreSupport下的core_cm3.ccore_cm3.h文件
    • Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x下的stm32f10x.hsystem_stm32f10x.c, system_stm32f10x.h文件
    • Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm下的所有.s文件

    最终的复制的结果如下图所示。
    在这里插入图片描述然后再在Keil同样建立一个名为Start的group,并把这些文件都添加进去。注意:.s文件只需要添加一个,f103c8t6对应的md.s
    在这里插入图片描述
    还需要在项目包含中加入这个文件夹:
    在这里插入图片描述

配置到这一步,理论上就可以使用寄存器编程了,因为stm32f10x.h文件中就包含了寄存器的各种操作,因此可以在只包含该头文件的前提下使用寄存器进行编程。
但是实测发现编译时疯狂报错,经过查找资料发现问题出在编译器上,新版的keil默认采用的编译器是v6,在添加文件时不能包含core_cm3.c文件。或者也可以把编译器改成v5,虽然编译速度会慢一些,但兼容性更好。操作如下:
在这里插入图片描述
参考链接

  • 如果需要使用库函数,还需要继续添加库函数文件。在项目文件夹下建立一个文件夹,命名Libraries,用来存放库函数文件,将Libraries\STM32F10x_StdPeriph_Driver路径下的inc和src下的文件都复制到Libraries文件夹下。同样在Keil软件新建同名group并添加所有复制过来的文件。结果如下图所示。
    在这里插入图片描述

    考虑到h文件可以展开看到,所以只添加c文件

  • 到这里还没结束,还需要添加几个文件。新建一个User文件夹,再把Project\STM32F10x_StdPeriph_Template下的stm32f10x_conf.h, stm32f10x_it.c, stm32f10x_it.h文件复制过去。然后和前面一样,在keil中添加同名group,然后添加这些文件,并将其文件夹路径添加到包含目录下。最后在define下新增宏定义USE_STDPERIPH_DRIVER.
    在这里插入图片描述
    在这里插入图片描述
    最后,再点击编译,如果没有意外,应该是0 Error(s) 0 Warning(s),那就说明工程模板创建成功。

关于分组的一些思考
不同的人对Keil下的这些文件应该怎么分组有不同的看法,我一开始不太理解上述这种分组方式,但是当我仔细看过这些代码的结构之后,也发现了一定的合理性。
首先是Start文件下的东西,因为具备了这些之后,就能够使用寄存器编程了,所以放到一起也很合理。其次是将conf和it文件放到User文件夹,因为conf文件是配置需要使用哪些外设,如果不需要使用那么多外设可以在conf文件中注释,或者就不要直接#include "stm32f10x.h",而是使用了啥外设再include;而it文件则是配置一些异常情况下对应的中断服务程序,可以添加用户排错的一些代码,所以,将这些文件放到User文件夹还是有一定合理性的。
最后剩下的就是一些具体外设相关的代码或者是一些完善的代码,比如延时和printf重定向等,可以分为SystemPeripheral

踩坑记录

  • 1、报错FCARM - Output Name not specified, please check ‘Options for Target - Utilities’
    原因:添加文件时类型选择错误
    在这里插入图片描述
    应改为All files。而且右键添加的文件,可以发现其属性对应错误。

    参考链接

  • 2、使用ST-Link下载程序到开发板,发现只有按下复位按钮才能运行程序
    解决:出在设置中勾选Reset and run之外,还需要取消勾选Enable
    在这里插入图片描述
    在这里插入图片描述

    参考链接

GPIO

概述

  GPIO, General-Purpose Input/Output,通用类型输入输出。STM32的GPIO较为复杂,但是了解原理之后掌握基础使用还是很简单的。其内部的IO口结构如下图所示:
在这里插入图片描述
  其中,值得一提的是,输入端的肖特基触发器,实质上是一个施密特触发器(属于翻译错误了),即具有滞回比较曲线,可以使得读入的信号不受波动的影响。输出端,位设置/清除寄存器是用来设置输出数据寄存器的,因为输出数据寄存器只能整体读写,而如果需要更改某一位时,就需要用到位设置/清除寄存器,来实现某一位的写入,而其他位不改变的效果。
  正是因为STM32的GPIO内部结构较为复杂,因此GPIO一共可以配置为8种输入输出模式,如下表所示:
在这里插入图片描述
  8种模式对应标准库中的代码如下图所示:
在这里插入图片描述

一般来说,使用GPIO的步骤如下:

  • 使能时钟(使能APB2总线上的时钟)
  • 初始化GPIO端口,包括设置引脚(Pin)、模式(Mode)、速度(Speed)等参数
  • 使用对应的API函数接口进行输入输出

  其中,初始化端口时,一般要先定义一个GPIO的结构体,然后分别配置结构体中的各参数,参考代码如下:
在这里插入图片描述

API函数总结

  初始化完GPIO端口之后,接下来的就是操作输入输出了,这里需要用到标准库给定的各种API函数。那如何找到这些函数呢?很简单,打开添加的stm32f10x_gpio.h文件,滑到最底下,就可以看到常用的API函数了。
在这里插入图片描述
  虽然数量有点多,但实际上常用的函数并不多。其功能如下图所示:
在这里插入图片描述
  如果需要查看函数具体的定义,可以在函数声明上右键,选择Go To Definition Of xxxxx,如果需要返回函数声明,在定义的函数上右键,选择Toggle Head
  下面附上一个LED闪烁的代码:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	while (1)
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_0);
		Delay_ms(500);
		GPIO_SetBits(GPIOA, GPIO_Pin_0);
		Delay_ms(500);
		
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
		Delay_ms(500);
		
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
		Delay_ms(500);
	}
}

参考链接

OUTPUT窗口信息查看

在这里插入图片描述

Code:即代码域,它通常是指编译器生成的机器指令,这些内容会被存储到ROM区。

RO-data:Read Only data,即只读数据域,它指程序中用到的只读数据,这些数据被存储在ROM区,因而程序不能被修改的内容。例如C语言中const关键字定义的变量就是典型的RO-data。

RW-data:Read Write data,即可读写数据域,它指初始化为“非0值”的可读写数据,程序刚运行时,这些数据具有非0的初始值,程序运行的时候它们又会常驻在RAM区,应用程序可以修改其内容。例如C语言中定义的全局变量,且定义时赋予“非0值”给该变量。

ZI-data:Zero Initialie data,即0初始化数据,它指初始化为“0值”的可读写数据域,它与RW-data的区别是程序刚运行时这些数据初始值全都为0,程序运行时和RW-data的性质一样,它们也常驻在RAM区,应用程序可以更改其内容。例如C语言中使用定义的全局变量,且定义时赋予“0值”给该变量(如若定义该变量时没有赋予初始值,编译器会把它当ZI-data来对待,初始化为0);

参考链接

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
STM32标准库开发教程是一套教学材料,旨在帮助初学者快速入门STM32嵌入式系统的开发。教程包括了安装开发工具、安装仿真器驱动、创建工程、配置工程、添加文件、编写代码、编译程序和下载程序等多个步骤。教程详细介绍了如何使用STM32标准库进行开发,并提供了丰富的实例代码和实验,以便初学者能够更好地理解和掌握相关知识。 在学习STM32标准库开发教程之前,初学者需要具备一定的电子和嵌入式系统的基础知识。教程会从基本的硬件知识和编程语言开始讲解,然后深入介绍STM32的应用和开发。通过逐步实践和探索,读者可以不断提高自己的技能水平。 在编写STM32标准库开发教程,需要将STM32标准库的源文件和头文件添加到工程,例如stm32f0x.h、stm32f0x_gpio.h、stm32f0x_rcc.h等。这些文件提供了对STM32芯片的访问接口,方便开发者进行开发和调试。 总之,STM32标准库开发教程是一个详细而全面的教学材料,旨在帮助初学者快速入门STM32嵌入式系统的开发。通过学习教程,读者可以掌握STM32的基础知识和开发技巧,并不断提高自己的技能水平。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [手把手教你STM32入门教程(标准库)](https://blog.csdn.net/yunsheng233/article/details/131403745)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

记录无知岁月

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

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

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

打赏作者

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

抵扣说明:

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

余额充值