Bootstrap

STM32F103 GPIO

基于寄存器、基于库函数


引脚描述

GPIO是MCU与外设设备连接、实现人机交互的基本接口

通过GPIO端口内部寄存器动态地配置为输入或输出,可以同时对任意个输出引脚进行置位或清零,也可以读出输出寄存器的值以及引脚的当前状态。

STM32F103微控制器最多可以提供112个多功能双向I/O引脚

端口号:端口号通常以大写字母命名,从A开始,依次类推。例如,GPIOA、GPIOB、GPIOC、…等。 引脚号:每个端口有16个I/O引脚,分别命名为0-15。例如,STM32F103RCT6微控制器的GPIOA端口有16个引脚,分别为PA0、PA1、PA2、PA3、…、PA14和PA15。

通用输入输出、复用为其他接口的引脚 ,通过内部寄存器的设置

流水灯、按键控制LED灯(仿真proteus)


内部结构


工作模式

输入模式
输入浮空(GPIO_Mode_IN_FLOATING) ****

        在此状态下,I/O口的电平信号进入输入数据寄存器,此时的I/O电平信号是不确定的,完全由外部输入决定,如果在该引脚悬空(在无信号输入)的情况下,读取该端口的电平是不确定的,且电压具有不确定性。

输入上拉  (GPIO_Mode_IPU)   ******

上拉就是将一个不确定的信号拉到一个固定的值,如上图所示,通过I/O口来的信号就被上拉电阻拉到了VDD。所以,和浮空输入相比来说,当I/O口被悬空的状态下,输入端的电平可以保持在高电平。

输入下拉  (GPIO_Mode_IPD)      *****

下拉与上拉类似,通过I/O口来的信号被下拉电阻拉到了VSS,当I/O口被悬空的状态下,输入端的电平可以保持在低电平。

模拟输入  (GPIO_Mode_AIN)

 模拟输入模式下,I/O端口的模拟信号(电压信号,而非电平信号)直接模拟输入到片上外设模块,比如ADC模块等等。

输出模式
开漏输出  (GPIO_Mode_Out_OD)

输出寄存器上的‘0’激活N-MOS,而输出寄存器上的‘1’将端口置于高阻态(P-MOS从不被激活)。 N-MOS管,当设置输出的值为高电平的时候,N-MOS管处于关闭状态,此时I/O端口的电平就不会由输出的高低电平决定,而是由I/O端口外部的上拉或者下拉决定;当设置输出的值为低电平的时候,N-MOS管处于开启状态,此时I/O端口的电平就是低电平。所以开漏输出只能输出强低电平,高电平得靠外部电阻拉高。

开漏复用功能  (GPIO_Mode_AF_OD)

开漏复用与开漏类似,只是电平信号的来源不是来自CPU的输出数据寄存器,而是来自片上外设模块。

推挽式输出  (GPIO_Mode_Out_PP)   ****

输出寄存器上的‘0’激活N-MOS,而输出寄存器上的‘1’将激活P-MOS。P-MOS管和N-MOS管,当设置输出的值为高电平的时候,P-MOS管处于开启状态,N-MOS管处于关闭状态,此时I/O端口的电平就由P-MOS管决定:高电平;当设置输出的值为低电平的时候,P-MOS管处于关闭状态,N-MOS管处于开启状态,此时I/O端口的电平就由N-MOS管决定:低电平。所以推挽输出可以输出强高低电平,连接数字器件。

推挽式复用功能  (GPIO_Mode_AF_PP)

推挽复用与推挽类似,只是电平信号的来源不是来自CPU的输出数据寄存器,而是来自片上外设模块。


STM32F103R6 具有GPIOA(PA[15:0])、GPIOB(PB[15:0])、GPIOC(PC[15:0])、GPIOD(PD[2:0])四个GPIO端口,共51个输入/输出引脚。这些GPIO引脚都可以通过软件动态配置为输出(推挽输出或开漏输出)、输入(带或不带上拉或下拉电阻)或复用的外设功能端口。多数GPIO引脚都与数字或模拟的复用外设共用。除了具有模拟输入功能的端口外,其他所有GPIO引脚都有大电流通过能力。GPIO寄存器可以同时对任意若干个输出引脚进行置位或清零操作。用户可以读出输出寄存器的值及引脚的当前状态。

GPIO引脚的输出速度

STM32微控制器I/O引脚内部有多个响应速度(2MHz,10MHz,50MHz)不同的驱动电路,用户可根据自己的需要选择合适的驱动电路。

对于连接LED、数码管和蜂鸣器等外部设备,一般设置为2MHz。

对于串口来说,这样只需要用2MHz的GPIO的引脚速度就可以了。

对于I2C接口,可以选用10MHz的GPIO引脚速度。

对于SPI接口,需要选择呢50MHz的GPIO引脚速度 对于用作FSMC复用功能连接存储器的输出引脚,一般设置为50MHz的I/O引脚速度。

内部寄存器

用户使用通用GPIO接口来实现人机交互的过程就是通过编程来操作相应GPIO端口内部寄存器的过程。编程时,可以通过端口地址来访问对应的GPIO端口中相应的寄存器。

*配置寄存器GPIOx_CRL和GPIOx_CRH:   

32位,设置GPIO引脚的工作模式和输出速率。

GPIOx_CRL——[7:0], GPIOx_CRH ——[15:8]

输入数据寄存器GPIOx_IDR:32位

输出数据寄存器GPIOx_ODR:32位

*置位/复位寄存器GPIOx_BSRR:32位*

复位寄存器GPIOx_BRR: 16位

锁定寄存器GPIOx_LCKR: 32位

配置寄存器GPIOx_CRL 

GPIOx_CRH
输入数据寄存器 GPIOx_IDR

输出数据寄存器GPIOx_ODR

位设置/清除寄存器BSRR(之前的图里)

端口位设置/清除寄存器 GPIOx_BSRR

低十六位输出高电平。高十六位输出低电平

端口位清除寄存器 GPIOx_BRR

APB2外设时钟使能寄存器 RCC_APB2ENR

GPIO库函数开发原理

(1)直接操作端口寄存器   (移位)

假设GPIO端口的引脚PA0连接了LED灯,其电路连接为低电平点亮LED灯,高电平熄灭LED灯。其底层操作过程如下:

使能外设时钟

初始化GPIO引脚

操作控制

GPIOA_CRL的地址:0x4001 0800 + 0x00 = 0x4001 0800

GPIOA_ODR的地址:0x4001 0800 + 0x0C = 0x4001 080C

RCC_APB2ENR的地址:0x4002 1000 + 0x18 = 0x4002 1018

宏定义

bite2

按照CRL进行配置

(2)将端口寄存器封装成结构体

  定义一种 GPIO 端口的结构体,结构体的地址为端口的基地址,结构体的成员为端口寄存器,成员的顺序按照寄存器的偏移地址从低到高排列,成员类型跟寄存器类型相同。操作寄存器时,操作该结构体的成员即可。

(3)封装成库函数

库函数是架设在寄存器和用户代码之间的代码,向下与寄存器相关,向上为用户提供相关接口,开发人员不需要特别关注底层寄存器的操作,可以提高程序的可读性和可移植性,有利于快速开发和维护。 在外设结构体的基础上按照功能的不同进一步封装成不同的库函数 把外设寄存器的每个位置为 1 都用宏定义来实现

 最小系统电路

 基于寄存器的GPIO输入输出

基于标准外设库的GPIO输入输出

;