什么是GPIO?(详细介绍)

这篇具有很好参考价值的文章主要介绍了什么是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读取到的才是低电平

什么是GPIO?(详细介绍)
        b.带下拉的输入 
            默认接一个下拉电阻 
            此时就算IO引脚没有外部输入信号时 CPU也能读到一个低电平
            只有在外部电路输入高电平的时候 CPU读取到的才是高电平  

什么是GPIO?(详细介绍)         
        c.输入悬空
            既不接上拉电阻 也不接下拉电阻  
            这种情况下 IO引脚的电平状态完全由外部输入所绝对 此时CPU可以通过读取数据的
            操作来获取外部电路的工作状态

什么是GPIO?(详细介绍)
        d.模拟输入
            该引脚被设置为模拟输入的时候 能够获取到模拟信号 
            通过ADC转换为数字量

 

什么是GPIO?(详细介绍)
    
    (2)输出功能 
    
        CPU可以通过该GPIO口往外部输出一个电平状态(相当于可以控制外部电路工作)
        输出功能也可以分为以下两种模式 
        a.输出推挽 (PP: push-pull)
            CPU往外写高电平(1)时,此时引脚输出一个高电平 
            CPU往外写低电平(0)时,此时引脚输出一个低电平  

什么是GPIO?(详细介绍) 
            
        b.输出开漏  (OD: open drain)
            不输出电压 
            CPU往外写低电平(0)时  此时引脚接VSS(GND)相当于接地
            CPU外外写高电平(1)时  此时引脚的电平状态由上下拉电阻决定

什么是GPIO?(详细介绍) 

 

 

 

 

    (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
                    
                    <----12---->    <------  18 ------>
                    
                &    111111111111 01 111111111111111111        <=先把bit19置为0    
            
            ===>    xxxxxxxxxxxx 0y xxxxxxxxxxxxxxxxxx
            
            
            1<<19    000000000000 10 000000000000000000
    
          ~(1<<19)    111111111111 01 111111111111111111
    
    
                    *p = *p & ~(1<<19)
    
    
            再把bit18置为1 
                
                类似与上面操作 为: 
                    
                    *p = *p | (1<< 18)
            
            所以我们分两步完成这个操作: 
                
                *p = *p & ~(1<<19)    
                *p = *p | (1<< 18)
    
            但是实际上面的操作对寄存器进行了两次操作 效率太低 
            有点耗费硬件资源  我们对寄存器的修改必须一步到位 
            
            所以我们会先定义一个中间变量 用来记录寄存器的值 
            然后再通过中间变量 一步到位去修改寄存器的值 如下操作 
            
                unsigned long r = 0 ;
                r = *p ;  //先用r保存寄存器中的值 并按照需求修改r值 
                
                r &= ~(1<<19);
                r |= (1<<18);
                
                *p = r; //通过中间变量 一步到位修改寄存器的值
    
    
        例子: 将PA0配置为输入模式 
               用C语言配置一次  用汇编配置一次
    
                C语言: 
                
                volatile unsigned long * p = (volatile unsigned long * )0x40020000 
                unsigned long r = 0 ;
                r = *p;
                
                r &= ~3 ; //把bit1和bit0都设置为0   00表示输入模式 
                
                *p = r;
                
                汇编: 
                
                LDR R0,=0X40020000 
                LDR    ,R1,[R0]         ;R1就相当于r     此指令相当于r = *p
                BIC    R1,R1,#0X03        ; r &= ~3  
                STR R1,[R0]
                
                
    (2)GPIOx_OTYPER    :Output Type Register 输出类型选择寄存器

        偏移地址:0x04
        该寄存器用来选择GPIOx(x=A,B...I)这组的16个GPIO引脚的输出类型 
        寄存器有32bits 
        低16个bit用于保存对于编号引脚的输出类型 高16bit保留
        一个bit保存一个引脚 
        一个bit有两种状态 分别对应开漏输出和推挽输出
        
        每个GPIO引脚占1bit 编号为y(y=0,1,2...15)的引脚在该寄存器中对于的bit为GPIOx_OTYPER[y]
        具体配置如下: 
            
            GPIOx_OTYPER[y]            输出类型 
                1                    输出开漏(OD)
                0                    输出推挽(PP)
                
        
                
    (3)GPIOx_OSPEEDR:Output Speed Register 输出速率寄存器 

        偏移地址:0x08
        用于控制GPIOx组的16个GPIO引脚的输出速率 
        每个引脚占2bit 
        编号为y的引脚在该寄存器中的bit位是GPIOx_OSPEEDR[2y+1:2y]
        具体配置如下: 
        
            GPIOx_OSPEEDR                速率 
            
                00                        2MHZ 
                01                        25MHZ 
                10                        50MHZ 
                11                        30pf则为100MHZ 
                                        15pf则为80MHZ
        
                
                
    (4)GPIOx_PUPDR:Pull Up Pull Down Register 端口上拉/下拉寄存器
    
        偏移地址:0x0c 
        该寄存器用来控制GPIOx组的16个引脚的上拉/下拉选择
        每个GPIO引脚占2bits 
        编号为y的GPIO引脚在该寄存器中所在的bit为GPIOx_PUPDR[2y+1:2y]
        具体配置如下: 
        
            GPIOx_PUPDR                上下拉选择 
                00                    无上拉、无下拉 
                01                    上拉 
                10                    下拉 
                11                    保留
        
                
    (5)GPIOx_IDR: Input Data Register 输入数据寄存器 

        偏移地址:0x10 
        该寄存器用来表示GPIOx这组的16个GPIO引脚的输入的电平状态值 
        每个GPIO引脚占1bits  该寄存器中高16bit保留没有使用 
        低16bit表示x组的16个引脚的电平状态
        比如:GPIOx_IDR[0] ==>表示的就是该组的第0个引脚GPIOx0的输入电平状态
        具体配置如下: 
        
            GPIOx_IDR[y]            编号为y的引脚的输入电平状态 
                1                        高电平 
                0                        低电平
        
        比如: 
            CPU想要知道GPIOA0这个引脚输入的是高电平还是低电平? 
            思路: 
                    if(GPIOA_IDR & 0X01  == 0X01)
                    {
                        PA0为高电平
                    }
                    else 
                    {
                        PA0为低电平
                    }
            
            ===> 
                    
                volatile unsigned long * p =(volatile unsigned long *)(0x40020000+0x10)
                if(*p & 0x01)
                {
                    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进行配置
        
        
        具体的值表示哪个复用功能或者引脚有哪些复用功能 
        需要结合电路原理图和功能手册来看
        
        什么是GPIO?(详细介绍)
        
四. 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<<5; 
        *p = r;
        
        
    GPIOF组的时钟使能后 就可以去配置GPIOF组的GPIO引脚了 
    配置后这些GPIO引脚可以与连接硬件电路正常工作了
    
    
    总结: 
        利用寄存器来实现GPIO功能配置的步骤 
        
        1)配置GPIO分组时钟(RCC_AHB1ENR)
        2)配置GPIO功能模式(GPIOx_MODER)
        3)配置输出类型(输出功能)
        4)配置输出速率 
        5)配置上拉/下拉
        6)如果是输入模式 则通过GPIOx_IDR可以获取外部电路工作状态 
          如果是输出模式 则通过GPIOx_ODR或这GPIOx_BSRR来向外部输出一个电平信息 
          如果是复用模式 则后面再讲

什么是GPIO?(详细介绍)
          
        
 
 

 

    文章来源地址https://www.toymoban.com/news/detail-461605.html

到了这里,关于什么是GPIO?(详细介绍)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32F4系列单片机库函数模板工程创建

    目录 一、工程配置 1、新建工程 2、芯片选择 3、工程子文件夹创建 (1)FWLIB文件夹添加文件 (2)CORE文件夹添加文件 (3)USER文件夹添加文件 4、工程设置 (1)工程中添加文件夹 (2)工程文件夹中添加配置文件 ①FWLIB文件夹添加文件 ②CORE文件夹添加文件 ③USER文件夹添加

    2024年01月25日
    浏览(41)
  • STM32单片机(三)第二节:GPIO输出练习3(蜂鸣器)

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月11日
    浏览(43)
  • 单片机:STM32F4x HAL库软硬SPI驱动ST7735s 1.8寸LCD屏幕

    说明:此篇为学习记录。可能存在错误或者不足。如有问题请指出。 主控芯片:STM32F411CEU6 主控开发板:WeAct STM32F411CEU6最小系统板 TFT-LCD屏幕:合宙1.8寸TFT-LCD,驱动为ST7735s MDK版本:5,32 HAL库版本:1.27.1 STM32CubeMX版本:6.7.0 ST7735s支持8080并口,3线和4线串行接口,模块的驱动方

    2024年02月03日
    浏览(55)
  • (第48-59讲)STM32F4单片机,FreeRTOS【事件标志、任务通知、软件定时器、Tickless低功耗】【纯文字讲解】【】

    【吐血总结】FreeRTOS难点、Systick中断-滴答定时器、PendSV中断-任务切换、SVC中断-系统底层、时间片调度-时钟节拍【已完结】 (第1-8讲)STM32F4单片机,FreeRTOS基础知识总结【视频笔记、代码讲解】【正点原子】【原创】 (第9-10讲)STM32F4单片机,FreeRTOS任务创建和删除(动态方

    2024年02月01日
    浏览(60)
  • 【STM32】GPIO详细介绍

    目录 GPIO概述 GPIO功能及特性 GPIO的电路结构 GPIO的工作模式 GPIO是通用输入输出接口(general purpose input/output)的简称主要用于数字量的输入和输出,是微控制器中使用频率最高的外设。它包括以下功能: 1 、输出功能 :输出高/低电平 通过输出高/低电平,控制继电器、指示灯和蜂鸣

    2024年02月08日
    浏览(32)
  • 【STM32】STM32F4 GPIO详解与配置

    GPIO是通用输入输出端口的简称,为STM32可控制的引脚,STM32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。STM32芯片的GPIO被分成很多组,每组有16个引脚,所有的GPIO引脚都有基本的输入输出功能。 其中保护二极管使GPIO能够5V电压容忍。在

    2024年02月07日
    浏览(50)
  • 【STM32】STM32F4 GPIO口映射与复用

    STM32F4 有很多的内置外设,这些外设的外部引脚都是与 GPIO 复用的。也就是说,一个 GPIO 如果可以复用为内置外设的功能引脚,那么当这个 GPIO 作为内置外设使用的时候,就叫做复用。 这部分知识在《STM32F4 中文参考手册》第七章和芯片数据手册有详细的讲解哪些 GPIO 管脚是

    2024年02月15日
    浏览(37)
  • STM32单片机开发-01 STM32介绍

    通过野火开发板学习单片机 从内核上分有Cortex-M0、M3、M4 和M7 F1 代表了基础型,基于Cortex-M3 内核,主频为72MHZ F4 代表了高性能,基于Cortex-M4 内核,主频180M。 数据手册:用于芯片选型和设计原理图 参考手册:用于编程时查阅 Icode总线 – 该总线讲M3内核的指令总线与闪存指令

    2024年01月21日
    浏览(55)
  • 单片机简介(STM32介绍)

        单片机是 单片微型计算机 的简称,Mcu是Microcontroller的简称,也就是嵌入式微控制器。采用集成电路技术将具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、定时器/计时器、多种I/O口和中断系统等功能集成到一块硅片上。可以说单片机就是一个小而完善

    2024年02月16日
    浏览(36)
  • STM32单片机IAP介绍

    1、什么是IAP? 首先区分下两个概念:ISP和IAP:         ISP:In System Programming (在系统中编程),通过芯片专用的串行编程接口对其内部的程序存储器进行擦写。         IAP:In Application Programming( 在应用中编程),通过调用特定的bootloader程序,对程序存储器的指定段

    2024年02月16日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包