目录
一、GPIO结构及模式
1、推挽输出
2、开漏输出
3、复用功能输出
4、上拉/下拉输入
5、复用功能输入与模拟输入
二、寄存器映射
一、GPIO结构及模式
图1 GPIO基本结构
如图1所示为GPIO基本结构,右侧I/O引脚为外部端口位,通过改变内部寄存器状态,来对I/O引脚输入输出模式进行配置。
保护二极管作为限位保护内部结构。
1、推挽输出
输出控制模块可看作反相器,推挽输出如图2所示: 若输出1,反相后为0,使得PMOS导通,对外输出高电平;若输出0,反相后为1,使得NMOS导通,对外输出低电平。
图2 推挽输出
2、开漏输出
开漏输出如图3所示,若输出1,反相后为0,使得NMOS截止,上拉电路输出;若输出0,反相后为1,使得NMOS导通,对外输出低电平。
图3 开漏输出
3、复用功能输出
片上外设UART_DR寄存器输出到IO引脚Tx。
4、上拉/下拉输入
通过GPIOx_BSRR寄存器配置,1为上拉,0为下拉。输入数据存储到GPIOx_IDR寄存器。施密特触发器消除信号抖动,小于1.2V为0,大于2V为1。
5、复用功能输入与模拟输入
复用功能输入从IO引脚Rx通过触发器存储至UART_DR寄存器。模拟输入不通过触发器直接读取。
各种输入输出模式的配置,通过寄存器GPIOx_CRL/GPIOx_CRH,配置表如图4。
图4 端口配置模式表
其中,MODE为0x00则为输入模式,0x01、0x10、0x11为输出模式,不同之处在于输出速度,如图5。
图5 输出模式位
二、寄存器映射
通过day1的文章:笔记(STM32篇)day1——工程创建、操作寄存器点灯,操作GPIO时,要根据目标GPIO,查询参考手册找到时钟寄存器、端口配置寄存器、数据输出寄存器的地址及其偏移量,通过位操作来改变寄存器状态,从而实现功能。
例如将PB0置0,如果直接通过地址取值去赋值的话,程序如下所示,可读性差。
#include "stm32f10x.h"
int main(void)
{
*(unsigned int*)0x40021018 |= (1<<3);
//控制RCC寄存器打开时钟,RCC偏移0x18为APB2时钟,寄存器第三位为PB使能
*(unsigned int*)0x40010C00 |= ((1)<<(4*0));
//控制GPIOB_CRL低位配置寄存器,偏移0x00,PB0通用推挽输出00,模式为输出01
*(unsigned int*)0x40010C0C &= ~(1<<0);
//控制GPIOB_ODR输出数据寄存器,偏移0x0C,寄存器首位即PB0
}
因此,可以使用在自写库函数中,进行寄存器映射,在库函数中给寄存器的地址取个别名,这样在程序中进行赋值时会清晰很多。
//库函数stm32f10x.h
#define PERIPHERAL_BASE ((unsigned int)0x40000000) //外设基地址
#define APB1_PERIPHERAL_BASE PERIPHERAL_BASE //APB1外设基地址
#define APB2_PERIPHERAL_BASE (PERIPHERAL_BASE+0x10000) //APB2基地址
#define AHB_PERIPHERAL_BASE PERIPHERAL_BASE+0x20000) //AHB基地址
#define RCC_BASE (AHB_PERIPHERAL_BASE+0x1000) //RCC时钟寄存器基地址
#define GPIOB_BASE (APB2_PERIPHERAL_BASE+0x0C00) //GPIOB在APB2上的基地址
#define RCC_APB2ENR (*(unsigned int*)(RCC_BASE+0x18))
//APB2外设时钟使能,强制地址转换,此地址下寄存器内容
#define GPIOB_CRL *(unsigned int*)(GPIOB_BASE+0x00) //GPIO低位配置寄存器
#define GPIOB_CRH *(unsigned int*)(GPIOB_BASE+0x04) //GPIO高位配置寄存器
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE+0x0C) //GPIO输出数据寄存器
#include "stm32f10x.h"
int main(void)
{
RCC_APB2ENR |= (1<<3);
//控制RCC寄存器打开时钟,RCC偏移0x18为APB2时钟,寄存器第三位为PB使能
GPIOB_CRL |= ((1)<<(4*0));
//控制GPIOB_CRL低位配置寄存器,GPIOB偏移0x00,PB0通用推挽输出00,模式为输出01
GPIOB_ODR &= ~(1<<0);
//控制GPIOB_ODR输出数据寄存器,GPIOB偏移0x0C,寄存器首位即PB0
}
补充:考虑到寄存器重置时不确定寄存器值,因此在配置时需要将寄存器先初始化,在GPIOB_CRL赋值前先将低4位置0。
GPIOB_CRL &= ~((0x0F)<<(4*0)); //初始化,低4位为一组,全部置0
参考
[野火®]STM32库开发实战指南——基于野火指南者开发板 — [野火]STM32库开发实战指南——基于野火指南者开发板 文档
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)