什么是GPIO?(详细介绍) | 您所在的位置:网站首页 › io各引脚信号是什么意思 › 什么是GPIO?(详细介绍) |
以STM32F4系列的单片机做例子 一.引入 单片机最小系统的组成: 芯片 + 供电电路 + 复位电路 + 时钟(晶振)电路 一个完成的系统的组成 最小系统 + 项目所需要的其他硬件(外设) 芯片: 整个系统的核心 相当于人类的大脑 会提供引脚与外部电路相连接 引脚(俗称 官方称呼“GPIO”) 二. GPIO GPIO是什么? General Purpose Input Output 通用功能输出输出 GPIO就是从芯片内部引出来一根功能复用的口线(电线) 功能复用是指:GPIO的引脚可以由CPU配置成不同的功能 比如:输入功能 输出功能 模拟功能 复用功能等等 分析GPIO内部结构图如picture/STM32F4XX_GPIO内部结构.PNG 通过图我们可以得知 每个GPIO可以独立地被配置成不同的功能。 GPIO配置功能如下: (1)输入功能 CPU可以通过该GPIO的来获取外部电路输入的一个电平状态 输入功能又可以分为几种模式: a.带上拉的输入(input pull-up) 默认接一个上拉电阻 此时就算IO引脚没有外部输入信号时 CPU也能读到一个高电平 只有在外部电路输入低电平的时候 CPU读取到的才是低电平 b.带下拉的输入 默认接一个下拉电阻 此时就算IO引脚没有外部输入信号时 CPU也能读到一个低电平 只有在外部电路输入高电平的时候 CPU读取到的才是高电平 c.输入悬空 既不接上拉电阻 也不接下拉电阻 这种情况下 IO引脚的电平状态完全由外部输入所绝对 此时CPU可以通过读取数据的 操作来获取外部电路的工作状态 d.模拟输入 该引脚被设置为模拟输入的时候 能够获取到模拟信号 通过ADC转换为数字量
(2)输出功能 CPU可以通过该GPIO口往外部输出一个电平状态(相当于可以控制外部电路工作) 输出功能也可以分为以下两种模式 a.输出推挽 (PP: push-pull) CPU往外写高电平(1)时,此时引脚输出一个高电平 CPU往外写低电平(0)时,此时引脚输出一个低电平 b.输出开漏 (OD: open drain) 不输出电压 CPU往外写低电平(0)时 此时引脚接VSS(GND)相当于接地 CPU外外写高电平(1)时 此时引脚的电平状态由上下拉电阻决定
(3)复用功能 复用功能是指GPIO口用作其他的外设的功能口线 比如: I2C USART SPI等等 每个GPIO口都可以被配置成多达16中复用功能 具体哪个引脚可以被复用成哪种功能 需要看原理图 STM32F4xx共有144个GPIO引脚 分为九组 记为GPIOA , GPIOB ... GPIOI 简写PA PB ... PI 每组有16根引脚 编号从0~15 也就是说: 比如GPIOA这一组就有 GPIOA0 PA0 GPIOA1 PA1 GPIOA2 PA2 ... GPIOA15 PA15 而这些GPIO的功能 都有独立的寄存器组(不同的GPIO硬件控制器)来配置他们 也就是说我们如果要使用比如GPIO口的输入功能的话 我们首先需要把对应寄存器组配置好。 那么如果我们要去配置(访问)寄存器的话 就必须知道寄存器的地址 每组GPIO的地址分布如下: 参考:第 192 页的第 7.4.11 节:GPIO 寄存器映射 边界地址 外设 总线: 0x4002 2000 - 0x4002 23FF GPIOI 0x4002 1C00 - 0x4002 1FFF GPIOH 0x4002 1800 - 0x4002 1BFF GPIOG 0x4002 1400 - 0x4002 17FF GPIOF 0x4002 1000 - 0x4002 13FF GPIOE AHB1 0x4002 0C00 - 0x4002 0FFF GPIOD 0x4002 0800 - 0x4002 0BFF GPIOC 0x4002 0400 - 0x4002 07FF GPIOB 0x4002 0000 - 0x4002 03FF GPIOA 边界地址:指对应的寄存器组的起始地址(基址)和结束地址 外设: 该寄存器组对应的硬件控制器 总线: 该硬件控制器所处的系统时钟总线 请注意:任何一个硬件控制器想要去正常工作 都必须开启(使能)时钟 而总线 就是给硬件控制器提供时钟的 那么有哪些寄存器呢?分别有什么用呢? 三.STM32F4XX GPIO寄存器 每个通用 I/O 端口包括 4 个 32 位配置寄存器(GPIOx_MODER、GPIOx_OTYPER、GPIOx_OSPEEDR 和 GPIOx_PUPDR) 2 个 32 位数据寄存器(GPIOx_IDR 和GPIOx_ODR) 1 个 32 位置位/复位寄存器 (GPIOx_BSRR) 1 个 32 位锁定寄存器(GPIOx_LCKR) 2 个 32 位复用功能选择寄存器(GPIOx_AFRH 和 GPIOx_AFRL)。 (1)GPIOx_MODER :功能模式选择寄存器 偏移地址:0x00 (寄存器地址 = 基址 + 偏移地址) 比如 :GPIOA_MODER的地址 0x40020000 + 0x00 = 0x40020000 该寄存器用来控制GPIOx(x=A,B,C...I)组的16个引脚的模式(4种:输入、输出,模拟,复用) 一个寄存器是32bits 一组GPIOx共有16个引脚 每个GPIO引脚占2bits 2bits正好可以表示4种状态 编号为y(y=0,1...15)的GPIO引脚在寄存器中的比特位为GPIOx_MODER[2y+1,2y] 具体配置如下: GPIOx_MODER[2y,2y+1] 模式 00 输入模式 01 输出模式 10 复用模式 11 模拟模式 例子: 用c代码将PF9配置称为输出模式 分析: GPIOF组寄存器的起始地址(基址):0x4002 1400 GPIOx_MODER的偏移地址是0x00 so: GPIOF_MODER的寄存器地址:0x4002 1400 + 0x00 = 0x4002 1400 如果要将PF9设置为输出模式 就需要将 GPIOF_MODER[2*9+1:2*9] GPIOF_MODER[19:18] ==> 01 把地址为0x40021400的寄存器中的bit19置为0 bit18置为1 怎么做到这两点呢? 通过地址我们就可以将寄存器中的bit置位 在STM32中 用unsigned long来表示地址的值 unsigned long * p = (unsigned long *)0x4002 1400 但是一般情况下我们会在地址的前面加上volatile 变成如下: volatile unsigned long * p = (volatile unsigned long *)0x4002 1400 volatile的作用是作为指令关键字 禁止编译器优化 访问的就是实际地址 而不会被编译器优化成别的地址 一般用于多线程的全局变量 中断处理函数访问 的全局变量 状态寄存器。 那么我们就可以通过指针p将地址0x40021400的寄存器中的bit19置为0 bit18置为1 操作如下: xxxxxxxxxxxx yy xxxxxxxxxxxxxxxxxx & 111111111111 01 111111111111111111 xxxxxxxxxxxx 0y xxxxxxxxxxxxxxxxxx 1 PA0为高电平 } (6)GPIOx_ODR:Output Data Register 端口输出数据寄存器 偏移地址: 0x14 该寄存器保存了该组16个GPIO引脚的输出电平状态 高16bit保留的 低16个bit就是对于编号的引脚的输出电平状态 具体配置如下: GPIOx_ODR[y] 编号为y的引脚的输出电平状态 1 高电平 0 低电平 (7)GPIOx_BSRR:Bit Set Reset Register 端口置位/复位寄存器 偏移地址:0x18 置位:set 把bit位置为1 复位:reset 把bit位置为0 该寄存器用来表示GPIOx组的16个GPIO引脚的输出状态 其中: 高16bits为端口复位寄存器 低16bits为端口置位寄存器 这个寄存器有点特殊 写1有效 写0无效 将GPIOx_BSRR[31:16]置为1 表示将GPIOx15~GPIOx0设置为0 将GPIOx_BSRR[15:0]置为1 表示将GPIOx15~GPIOx0设置为1 实现效果跟GPIOx_ODR一样 用来设置GPIO引脚的输出状态 (8)GPIOx_LCKR :锁定寄存器 (9)GPIOx_AFRL:复用功能低位寄存器 偏移地址:0x20 (10)GPIOx_AFRH:复用功能高位寄存器 偏移地址:0x24 GPIOx_AFRL和GPIOx_AFRH这两个寄存器是放在一起使用的 AFR:Alternate Function Register 复用功能选择寄存器 因为一个GPIO引脚最多有16个复用功能 那么1个GPIO引脚需要4个bit 所以16个引脚就需要16*4 = 64bits 也就是2个寄存器的空间 GPIO引脚编号为0-7由GPIOx_AFRL进行配置 8-15由GPIOx_AFRH进行配置 具体的值表示哪个复用功能或者引脚有哪些复用功能 需要结合电路原理图和功能手册来看 四. STM32F4XX GPIO时钟使能
根据上述的寄存器 就可以去实现所有基于GPIO能够完成的功能配置了 比如: 点亮led灯 获取key按键的状态(按下/松开) 控制蜂鸣器等等 但是我们在之前就提到过 任何一个硬件控制器想要工作 都必须去实现时钟使能 (GPIO所有分组全部属于AHB1时钟总线) 那么时钟的相关配置 请参考RCC部分(数据手册的第六章) RCC: Reset Clock Control 复位时钟控制 基址:0x40023800 那么现在我们的目的是使能GPIO分组时钟: RCC AHB1外设时钟使能寄存器(RCC_AHB1ENR) 偏移地址:0x30 该寄存器的第0位到第8位分别控制GPIOA到GPIOI组时钟的使能: 1 使能对于GPIO分组的时钟 0 禁止对应GPIO分组的时钟 比如:使能GPIOF组时钟 ==》RCC_AHB1ENR[5] -> 1 C语言实现: volatile unsigned long * p = (volatile unsigned long *)(0x40023800 + 0x30); unsigned long r = 0; r = *p; r |= 1 |
CopyRight 2018-2019 实验室设备网 版权所有 |