笔记(STM32篇)day2——GPIO及寄存器映射

目录

一、GPIO结构及模式

1、推挽输出

2、开漏输出

3、复用功能输出

         4、上拉/下拉输入

5、复用功能输入与模拟输入

二、寄存器映射



一、GPIO结构及模式

笔记(STM32篇)day2——GPIO及寄存器映射_第1张图片

图1 GPIO基本结构

        如图1所示为GPIO基本结构,右侧I/O引脚为外部端口位,通过改变内部寄存器状态,来对I/O引脚输入输出模式进行配置。

        保护二极管作为限位保护内部结构。

1、推挽输出

        输出控制模块可看作反相器,推挽输出如图2所示: 若输出1,反相后为0,使得PMOS导通,对外输出高电平;若输出0,反相后为1,使得NMOS导通,对外输出低电平。

笔记(STM32篇)day2——GPIO及寄存器映射_第2张图片

 图2 推挽输出

2、开漏输出

        开漏输出如图3所示,若输出1,反相后为0,使得NMOS截止,上拉电路输出;若输出0,反相后为1,使得NMOS导通,对外输出低电平。

笔记(STM32篇)day2——GPIO及寄存器映射_第3张图片

 图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。

笔记(STM32篇)day2——GPIO及寄存器映射_第4张图片

图4 端口配置模式表

 其中,MODE为0x00则为输入模式,0x01、0x10、0x11为输出模式,不同之处在于输出速度,如图5。

笔记(STM32篇)day2——GPIO及寄存器映射_第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库开发实战指南——基于野火指南者开发板 文档

你可能感兴趣的:(STM32基础知识,stm32,嵌入式硬件,c语言,单片机,arm)