STM32学习笔记2.1 第一个外设——GPIO:硬件和寄存器

Posted ZeroP1Kelvin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32学习笔记2.1 第一个外设——GPIO:硬件和寄存器相关的知识,希望对你有一定的参考价值。

GPIO的硬件结构

你的单片机上有48到144根等等不同的引脚,除去其中的一些引脚作为电源输入、启动线等用途之外,几乎所有的引脚都具有这样的功能:输出特定的电平、或者读取引脚的当前电平。这一功能看似简单,但是构成了各种通讯、定时、控制的基石。实现这种功能的外设叫做GPIO(General Purpose Input Output, 通用输入输出)。
STM32的GPIO被分成A、B、C、D……等等若干组,每组拥有16个GPIO引脚,记为PA0,PA1,……,PA15等等。STM32F1的GPIO外设硬件结构如下,每个引脚里都连接了一组这样的电路。


缺乏硬件经验的学习者看到这张图可能会眼前发昏,不过你只要做过一点数字电路相关设计,这张图还是很容易读懂的。笔者将以椭圆框出的五个区域内元件展开带你读图。之后,你必须拥有这种将原理图模块化的能力。
1是两个保护用二极管。一般VDD接到3.3V,VSS接地。当IO引脚输入电压过高时(比如一不小心连接到了不能容忍的直流电平,或者是你用IO口去推了感性元件导致反向电压过高),上方的保护二极管会导通,使IO口内部承受的电压仍在3.3V+二级管导通压降附近,以最大限度保护设备(当然外部输入电压过高时,这个二极管也会被烧断,芯片难免损坏)。当然下方的二极管也是同理,可以防范过大的负电压。
之后看输入相关控制,也就是2和3。如果你之前对数电有些许了解,应该知道2的功能是提供输入的上下拉。简单说来,是为了稳定引脚电平,同时给浮空状态一个确定的输入值。展开来讲,如果一个引脚不连接任何电路内的其他节点直接面对空气,我们说这个引脚处于“浮空”状态。对浮空状态读取到的输入值,有些设备会默认为高或低。但更多的设备只会因为周围环境给出一个随机的值(甚至会照着50Hz的工频在高低电平之间狂跳),这在很多时候是不允许的。上拉或者下拉电阻可以很有效地避免这种读取到意外输入的情况。内部上拉电阻处的两个开关由寄存器的某两个位控制(大概)。当然,如果内部上下拉电阻的性能无法满足你的要求,你也可以在设计外围电路时自己在引脚外加上下拉电阻。
输入信号电压在与上下拉电阻做过基尔霍夫定律之后,被交给TTL施密特触发器。你应该知道TTL电平——输入2.0V以上表示高电平,否则表示低电平。施密特触发器会将前级输入的电压值按照这个规则“翻译”成更标准的3.3V或0V(近似),如下图。

之后是3,这个寄存器位直接存储了施密特触发器的状态,你可以通过直接读寄存器或者用库函数将这个值取走用于你的各种用途。施密特触发器的状态也可以被其他用到这个引脚的外设读取(图中的复用那路)
输入一路说完了,我们再来看输出。4是一对互补的MOS管……嗯?没学过模电?我能不管吗()。
好吧,这样想。“输出控制”方框接到上方P-MOS的线给出低电平时,输出脚类似于接一个不太大的电阻到电源;给出高电平时,输出脚类似于接一个无穷大电阻到电源。接到N-MOS的线给出高电平时,输出类似于用一个不大的电阻接到地;给出低电平时类似于用无穷大的电阻接到地。可能有点晕,没学过模电的多读两遍,知道大概就好。借助这种用不同电阻接到不同电压的排列组合,可以给出这几种输出状态,如下表:

P-MOS的控制电平为高时,不妨认为P-MOS是关断状态。这个状态被称为“开漏”模式,内部电源VDD无法参与输出。此时N-NOS的控制电平为高时,N-MOS处于开启状态,输出电平接近0;为低时,输出电平不确定,IO口对外相当于一个很大的电阻,所以叫“高阻态”,如果要让它输出高电平,需要在IO口外接上拉电阻(当然内部上拉启用也是可以的)。
P-MOS的控制电平为低时,P-MOS是开启状态,这个状态叫“推挽”模式,电源可以参与输出。此时N-MOS控制电平为高时,输出电平为0;否则为1。
如果你看不下去上面那段裹脚布,请记住,GPIO输出有推挽和开漏两种模式,开漏输出可输出低电平和高阻态、想输出高电平需要加上拉电阻;推挽输出可输出高电平和低电平。
GPIO的输出高电平一般能达到3.0V左右,输出电阻在千欧级,灌入和吐出最大电流在25mA(吐出一般到不了红线,但是灌入很容易出现问题)。所以说,GPIO的输出带载能力真的很弱,连一盏大点的LED都点不亮,做各种控制需要继电器和模拟开关等的辅助。GPIO也比较脆弱,用IO口测量电平时,要尽可能地在接口和被测电压间加保护电阻;更不要用IO口去尝试直接驱动电机、蜂鸣器、扬声器等等感性元件,带不动是小事,更要命的是电感上因为输入电压突变产生的大反向电压很容易烧毁IO口。
最后是5,两组寄存器,在寄存器映射中表示为BSRR和ODR。前者只可以写入,负责控制IO口电平,后者可以写入也可以读出,直接决定并可以用来监控IO口电平。初学时修改BSRR或ODR都可以修改电平,但更推荐使用BSRR。

GPIO相关寄存器

了解了硬件结构之后,你便可以读懂参考手册里GPIO寄存器的大部分内容了。且GPIO的寄存器不太典型,所以我这里只讲寄存器的大致功能。
每组GPIO都拥有一套这种结构的寄存器:

typedef struct{
	__IO uint32_t CRL;
	__IO uint32_t CRH;
	__IO uint32_t IDR;
	__IO uint32_t ODR;
	__IO uint32_t BSRR;
	__IO uint32_t BRR;
	__IO uint32_t LCKR;
}GPIO_TypeDef;

从上到下分别是配置寄存器低32位(Configure Rigister Low),控制寄存器高32位,输入数据寄存器(Input Digital Rigister),输出数据寄存器、置位复位寄存器(Bit Set Reset Rigister)、复位寄存器(Bit Reset Rigister)和配置锁定寄存器。
CRL和CRH的作用差不多、只是CRL控制低8位的引脚(P0-P7),CRH控制高8位(P8-P15)。它们中每四位控制一个引脚,决定了该引脚的输入输出相关模式(输入输出、上下拉、推挽开漏等等)。
IDR只有低16位有意义,分别代表P0-P16的输入电平,可以直接读走。ODR类似,代表P0-P16的输出电平,可以用于修改电平但不推荐。
BSRR和BRR同样只有低16位有意义,都能控制引脚的电平。不同的是,BRR只能将引脚电平置低,但BSRR可以置低或置高。
LCKR是配置锁定寄存器。
最后,请你回忆1.3节中我们写的一句代码

GPIOA->CRL = 0x44442222

请参考参考手册,说明一下这句代码有什么作用。
下一节,我们将走进标准库的世界,详细了解其封装手段、各函数及其作用,看看它是怎么帮我们减少查阅寄存器的工作量的。

以上是关于STM32学习笔记2.1 第一个外设——GPIO:硬件和寄存器的主要内容,如果未能解决你的问题,请参考以下文章

STM32H7视频教程第9期:STM32H7的GPIO专题,通过驱动源码,参考手册,数据手册应用笔记系统学习GPIO知识点(2022-03-06)

正点原子STM32探索者学习笔记1

stm32-再谈GPIO

第13章 GPIO输入—按键检测

stm32读取gpio高低电平速度

STM32外设:GPIOEXIT