STM32学习笔记之一_GPIO
- 格式:doc
- 大小:41.50 KB
- 文档页数:4
stm32 汇编语言gpio读写在STM32微控制器上使用汇编语言进行GPIO(General Purpose Input/Output)的读写涉及到寄存器的操作。
以下是一个简单的例子,演示如何使用汇编语言在STM32上进行GPIO读写。
请注意,具体的寄存器和位定义可能会因不同的STM32型号而有所不同,下面的示例基于Cortex-M系列的STM32微控制器。
首先,假设我们要配置一个GPIO引脚为输出,并将其电平设置为高。
我们使用的是ARM汇编语言(GNU汇编语法),这是通用的语法,但具体的寄存器和位定义可能需要根据你的芯片手册进行调整。
```assembly.global _start.section .text_start:// 设置RCC_AHB1ENR 寄存器的GPIOA 位,使能GPIOA 时钟LDR R1, =0x40023830 // RCC_AHB1ENR 地址LDR R0, [R1] // 读取RCC_AHB1ENR 的当前值ORR R0, R0, #(1 << 0) // 设置GPIOA 位STR R0, [R1] // 将修改后的值写回RCC_AHB1ENR// 设置GPIOA_MODER 寄存器的MODER5 位,将GPIOA Pin 5 配置为输出LDR R1, =0x40020000 // GPIOA 地址LDR R0, [R1, #0x00] // 读取当前GPIOA_MODER 的值ORR R0, R0, #(1 << 10) // 设置MODER5 为01 (输出模式)STR R0, [R1, #0x00] // 将修改后的值写回GPIOA_MODER// 设置GPIOA_ODR 寄存器的ODR5 位,将GPIOA Pin 5 输出电平设置为高LDR R0, [R1, #0x14] // 读取当前GPIOA_ODR 的值ORR R0, R0, #(1 << 5) // 设置ODR5 为1 (高电平)STR R0, [R1, #0x14] // 将修改后的值写回GPIOA_ODR// 无限循环loop:B loop```上述代码的作用是配置GPIOA Pin 5 为输出,并将其电平设置为高。
STM32库函数功能详解STM32是一款广泛应用于嵌入式系统中的微控制器系列,由意法半导体(STMicroelectronics)开发。
它具有高性能、低功耗和丰富的外设功能,广泛应用于各种应用领域。
为了方便开发者进行快速开发和简化编程流程,STM32提供了一系列库函数,本文将对其功能进行详细解析。
1.GPIO库函数:GPIO库函数用于配置STM32的通用输入输出口(GPIO)功能,包括输入、输出模式的配置和读写操作。
通过GPIO库函数,开发者可以方便地读取外部输入信号、控制外部设备的输出。
例如,使用GPIO库函数可以简单地配置一个引脚为输入模式,并读取其电平状态,或者配置一个引脚为输出模式,并设置其输出电平。
2.EXTI库函数:EXTI库函数用于配置STM32的外部中断(EXTI)功能,可以实现对外部事件的中断响应功能。
通过EXTI库函数,开发者可以方便地配置外部中断的触发方式和优先级,以及处理中断事件。
例如,使用EXTI库函数可以配置一个引脚为上升沿触发模式,并在引脚触发中断时执行相应的中断服务函数。
3.RCC库函数:RCC库函数用于配置和控制STM32的时钟系统(RCC),包括各个外设模块和系统时钟的配置。
通过RCC库函数,开发者可以方便地配置STM32的时钟源、时钟分频和时钟使能。
例如,使用RCC库函数可以配置系统时钟为指定频率,以及使能和配置外设时钟。
4.NVIC库函数:NVIC库函数用于配置和控制STM32的中断控制器(NVIC)功能,包括中断向量表和中断优先级的配置。
通过NVIC库函数,开发者可以方便地配置中断向量表和中断优先级,以及控制中断的使能和屏蔽。
例如,使用NVIC库函数可以配置一个外部中断的优先级和使能状态,以及控制中断的屏蔽和释放。
5.ADC库函数:ADC库函数用于配置和控制STM32的模数转换器(ADC)功能,可以实现模拟信号的数字化转换。
通过ADC库函数,开发者可以方便地配置ADC的转换通道、采样速率和转换模式。
GPIO,即通用输入输出,是STM32芯片上的数字接口,具有灵活性和可编程性,能够被软件配置为输入或输出。
它是嵌入式设备中非常基础的一部分,允许嵌入式系统与外界环境交互,可以通过编程来控制它们进行各种操作。
例如,在输入模式下,GPIO可以读取来自传感器、开关等外部设备的信号;在输出模式下,它可以控制LED 灯、电机等外部设备。
特定于STM32F103ZET6芯片,它有GPIOA、GPIOB、GPIOC、GPIOD、GPIOE、GPIOF和GPIOG七组GPIO口,共有112个IO口可供编程使用,其中37个是普通输入/输出口,75个是复用输入/输出口。
对GPIO的参数进行配置时,会用到一个名为GPIO_InitTypeDef的结构体(用于配置CRL、CRH寄存器参数),这些参数包括具体的端口GPIO_Pin、端口速度GPIO_Speed、端口模式GPIO_Mode。
另外,当我们选择配置GPIO后,可以通过GPIO_Init指向引脚初始化类型GPIO_InitTypeDef 的结构体指针,该结构体包含指定引脚的配置参数。
学习笔记:STM32的外部中断(库函数)在为某引脚配置中断前,同样要先初始化该引脚的配置,用GPIO_Init()函数初始化,不同的是,由于是外部中断,所以输入模式要设置上拉输入。
假设外部中断引脚为PE.2,则该引脚初始化配置的程序为:IOIO口作为外部中断输入是复用功能,因此在此基础上还需要对另一个时钟信号进行初始化。
这是IO口作为复用功能时需要进行初始化的时钟,另外,要注意的是,做一般功能使用的IO口只需要调用第一个函数即可,而作为复用功能的IO口,两个函数都要调用,两者缺一不可,否则不能正常使用。
STM32的每个IO都可以作为外部中断的中断输入口,这点也是STM32的强大之处。
STM32F103的中断控制器支持19个外部中断/事件请求。
每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。
STM32F103的19个外部中断为:线0~15:对应外部IO口的输入中断。
线16:连接到PVD输出。
线17:连接到RTC闹钟事件。
线18:连接到USB唤醒事件。
从上面可以看出,STM32供IO口使用的中断线只有16个,但是STM32的IO口却远远不止16个,那么STM32是怎么把16个中断线和IO口一一对应起来的呢?于是STM32就这样设计,GPIO的管脚GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线0~15。
这样每个中断线对应了最多7个IO口,以线0为例:它对应了GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、GPIOE.0、GPIOF.0、GPIOG.0。
而中断线每次只能连接到1个IO口上,这样就需要通过配置来决定对应的中断线配置到哪个GPIO上了。
下面我们看看GPIO跟中断线的映射关系图:在库函数中,配置GPIO与中断线的映射关系是通过函数GPIO_EXTILineConfig()来实现的:void GPIO_EXTILineConfig(uint8_t GPIO_PortSource,uint8_t GPIO_PinSource)该函数将端口与中断线映射起来,使用示例是:GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);将中断线2与GPIOE映射起来,那么很显然是GPIOE.2与EXTI2中断线连接了。
标题:STM32 GPIO中断引脚电平状态分析与应用一、概述STM32是一款广泛应用于嵌入式系统的芯片,并且具有丰富的外设功能。
在实际应用中,GPIO中断引脚的电平状态对于系统的稳定性和可靠性至关重要。
本文将以STM32 GPIO中断引脚电平状态为主题,分析其原理和应用。
二、STM32 GPIO中断1. 概述STM32芯片具有丰富的GPIO外设,可以方便地实现对外部事件的响应。
其中,GPIO中断是一种常用的外部事件触发机制,通过配置GPIO中断引脚可以实现对外部信号的实时监测和响应。
2. 原理GPIO中断引脚与外部信号相连,当外部信号发生变化时,引脚的电平状态也会相应改变。
通过配置中断触发条件和中断处理函数,可以实现对外部信号的及时响应。
3. 应用在实际应用中,GPIO中断可以用于监测外部开关、传感器等设备的状态变化,以及实现对设备的控制和调度。
通过合理配置中断引脚和中断处理函数,可以提高系统的稳定性和可靠性。
三、GPIO中断引脚的电平状态1. 低电平触发当GPIO中断引脚的电平由高变低时,触发中断。
这种触发方式适用于外部信号为低电平有效的场景,例如按键开关、传感器触发等。
2. 高电平触发当GPIO中断引脚的电平由低变高时,触发中断。
这种触发方式适用于外部信号为高电平有效的场景,例如光电传感器、红外遥控器等。
3. 双边沿触发当GPIO中断引脚的电平由低变高或由高变低时,均触发中断。
这种触发方式适用于外部信号为双边沿触发的场景,例如旋转编码器、电机霍尔传感器等。
四、GPIO中断引脚电平状态的配置与实现1. 配置在STM32芯片中,通过配置GPIO中断引脚的模式、触发条件和中断优先级等参数,可以实现对中断的灵活控制。
具体配置方法可以参考STM32的冠方文档和相关资料。
2. 实现在实际应用中,可以通过编写中断处理函数,实现对中断事件的响应和处理。
在中断处理函数中,可以根据中断引脚的电平状态进行相应的逻辑判断和操作,实现对外部信号的实时监测和控制。
stm32 gpio中断引脚电平状态-回复STM32是一款广泛使用的32位单片机系列,具备强大的性能和丰富的外设功能,其中GPIO(General Purpose Input/Output)引脚是其最基本的输入输出接口之一。
在STM32中,GPIO引脚可以通过中断机制来实现对电平状态的检测和响应。
本文将一步一步介绍STM32 GPIO中断引脚的原理、配置和应用场景。
一、引脚中断基本原理在STM32的GPIO引脚中,每个引脚都有自己的控制寄存器和状态寄存器。
通过设置相关的寄存器值,可以控制引脚的输入输出模式以及电平状态的检测。
当引脚的电平状态发生变化时,会触发GPIO中断并执行相应的中断服务程序。
1.1 引脚控制寄存器引脚控制寄存器用于配置引脚的输入输出模式、上拉/下拉电阻以及引脚输出的初始电平状态。
通过设置寄存器的位值,可以控制引脚的多种状态。
1.2 引脚状态寄存器引脚状态寄存器用于读取引脚的电平状态。
当引脚的电平状态发生变化时,状态寄存器的相应位会被置位,表示引脚中断发生。
1.3 外部中断控制器外部中断控制器用于管理GPIO引脚中断的触发条件和优先级。
可以通过设置相应的寄存器值,来配置引脚的触发模式(上升沿、下降沿、边沿等)以及中断的优先级。
二、引脚中断配置步骤为了使用GPIO引脚中断,需要按照以下步骤进行配置:2.1 GPIO引脚初始化首先,需要初始化GPIO引脚的功能和模式。
可以通过设置引脚控制寄存器的位值,来配置引脚的输入输出模式和上拉/下拉电阻。
例如,可以将引脚设置为输入模式,并启用上拉电阻,以便检测外部信号引脚的电平状态。
2.2 外部中断配置接下来,需要配置外部中断控制器,以确定引脚中断的触发条件和优先级。
可以通过设置中断控制寄存器的位值,来配置引脚的触发模式。
例如,可以将引脚设置为上升沿触发模式,表示仅在引脚电平上升沿触发中断。
2.3 中断服务程序编写当引脚的电平状态发生变化并触发中断时,系统会自动跳转到相应的中断服务程序执行相应的操作。
STM32GPIO输⼊输出模式的理解
四种输出模式:
1、推挽输出
所谓推挽输出模式是根据两个MOS管的⼯作⽅式命名的。
功能:推挽输出可输出⾼电平,可输出低电平。
应⽤:⼀般应⽤在输出电平为VSS和VDD,⽽且需要⾼速切换开关状态的场合。
在STM32的应⽤中,除必须使⽤开漏模式的场合,我们都使⽤推挽输出模式。
2、推挽复⽤模式
应⽤于内容来⾃STM32⽚上外设。
即GPIO被⽤作复⽤功能时使⽤。
3、开漏输出
功能:只能输出低电平,如需输出⾼⾼电平,需外接电路(单⽚机输出3.3V时,外接电路为3,3V时,输出3.3V.外接5V时,可输出5V)。
应⽤:⼀般应⽤在输出电平在IIC、SMBUS通信等需要"线与"功能的总线中。
除此之外,还⽤在电平不匹配的场合,如需输出5伏的⾼电平,就可以外部接⼀上拉电阻,上拉电源为5伏。
并且把GPIO设置为开漏模式,当输出⾼阻态时,由上拉电阻和电源向外输出5伏的电平。
4、开漏复⽤
四种输⼊模式:
1、上拉输⼊
在没有输⼊信号的时候,输⼊端默认输⼊⾼电平(由上拉决定)。
2、下拉输⼊
如上拉输⼊
3、浮空输⼊
浮空输⼊的电平是不确定的,完全由外部的输⼊决定。
应⽤:⼀般⽤于接按键。
4、模拟输⼊
⽤于ADC采集。
1.使能GPIO的AHB时钟,使用函数:RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);2.配置GPIO工作模式用GPIO_Init()函数数据类型说明typedef struct{uint32_t GPIO_Pin; //引脚配置GPIOMode_TypeDef GPIO_Mode; //GPIO_Mode_IN(输入),GPIO_Mode_OUT(输出),GPIO_Mode_AF (备用),GPIO_Mode_AN(模拟)GPIOSpeed_TypeDef GPIO_Speed;// GPIO_Speed_2MHz,GPIO_Speed_25MHz,GPIO_Speed_50MHz,GPIO_Speed_100MHzGPIOOType_TypeDef GPIO_OType; // GPIO_OType_PP(推挽),GPIO_OType_OD(开漏)GPIOPuPd_TypeDef GPIO_PuPd; GPIO_PuPd_NOPULL(无),GPIO_PuPd_UP(上拉),GPIO_PuPd_DOWN(下拉)}GPIO_InitTypeDef;3.备用功能配置(除ADC和DAC外的所有非GPIO功能),使用函数void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)* This GPIO_AF can be one of the following values:* @arg GPIO_AF_RTC_50Hz: Connect RTC_50Hz pin to AF0 (default after reset)* @arg GPIO_AF_MCO: Connect MCO pin (MCO1 and MCO2) to AF0 (default after reset)* @arg GPIO_AF_TAMPER: Connect TAMPER pins (TAMPER_1 and TAMPER_2) to AF0 (default after reset)* @arg GPIO_AF_SWJ: Connect SWJ pins (SWD and JTAG)to AF0 (default after reset)* @arg GPIO_AF_TRACE: Connect TRACE pins to AF0 (default after reset)* @arg GPIO_AF_TIM1: Connect TIM1 pins to AF1* @arg GPIO_AF_TIM2: Connect TIM2 pins to AF1* @arg GPIO_AF_TIM3: Connect TIM3 pins to AF2* @arg GPIO_AF_TIM4: Connect TIM4 pins to AF2* @arg GPIO_AF_TIM5: Connect TIM5 pins to AF2* @arg GPIO_AF_TIM8: Connect TIM8 pins to AF3* @arg GPIO_AF_TIM9: Connect TIM9 pins to AF3* @arg GPIO_AF_TIM10: Connect TIM10 pins to AF3* @arg GPIO_AF_TIM11: Connect TIM11 pins to AF3* @arg GPIO_AF_I2C1: Connect I2C1 pins to AF4* @arg GPIO_AF_I2C2: Connect I2C2 pins to AF4* @arg GPIO_AF_I2C3: Connect I2C3 pins to AF4* @arg GPIO_AF_SPI1: Connect SPI1 pins to AF5* @arg GPIO_AF_SPI2: Connect SPI2/I2S2 pins to AF5* @arg GPIO_AF_SPI3: Connect SPI3/I2S3 pins to AF6* @arg GPIO_AF_I2S3ext: Connect I2S3ext pins to AF7* @arg GPIO_AF_USART1: Connect USART1 pins to AF7* @arg GPIO_AF_USART2: Connect USART2 pins to AF7* @arg GPIO_AF_USART3: Connect USART3 pins to AF7* @arg GPIO_AF_UART4: Connect UART4 pins to AF8* @arg GPIO_AF_UART5: Connect UART5 pins to AF8* @arg GPIO_AF_USART6: Connect USART6 pins to AF8* @arg GPIO_AF_CAN1: Connect CAN1 pins to AF9* @arg GPIO_AF_CAN2: Connect CAN2 pins to AF9* @arg GPIO_AF_TIM12: Connect TIM12 pins to AF9* @arg GPIO_AF_TIM13: Connect TIM13 pins to AF9* @arg GPIO_AF_TIM14: Connect TIM14 pins to AF9* @arg GPIO_AF_OTG_FS: Connect OTG_FS pins to AF10* @arg GPIO_AF_OTG_HS: Connect OTG_HS pins to AF10* @arg GPIO_AF_ETH: Connect ETHERNET pins to AF11* @arg GPIO_AF_FSMC: Connect FSMC pins to AF12* @arg GPIO_AF_OTG_HS_FS: Connect OTG HS (configured in FS) pins to AF12* @arg GPIO_AF_SDIO: Connect SDIO pins to AF12* @arg GPIO_AF_DCMI: Connect DCMI pins to AF13* @arg GPIO_AF_EVENTOUT: Connect EVENTOUT pins to AF154.使用GPIO_ReadInputData(GPIO_TypeDef* GPIOx)和GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)读输入信号5.使用GPIO_SetBits()/GPIO_ResetBits()设置输出引脚6.上电或复位后,引脚备用功能都没启用(JTAG引脚除外),为悬浮输入状态7.LSE引脚OSC32_IN 和OSC32_OUT(PC14 and PC15)的优先级高于GPIO8.HSE引脚OSC_IN/OSC_OUT (PH0 / PH1)的优先级高于GPIO例程:int main(void){GPIO_InitTypeDef GPIO_InitStructure;/* GPIOG Periph clock enable */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(GPIOD, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_SetBits(GPIOD, GPIO_Pin_12);GPIO_ResetBits(GPIOD, GPIO_Pin_13);while (1){if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0){GPIO_SetBits(GPIOD, GPIO_Pin_13);GPIO_ResetBits(GPIOD, GPIO_Pin_12);}else{GPIO_SetBits(GPIOD, GPIO_Pin_12); GPIO_ResetBits(GPIOD, GPIO_Pin_13);}}}。
stm32 gpio引脚电容范围-回复Stm32 GPIO引脚电容范围在嵌入式系统中,STM32是一款非常流行的微控制器系列,由意法半导体公司(STMicroelectronics)开发。
它广泛用于各种应用领域,如工业控制、自动化、医疗设备和消费电子等。
在STM32中,GPIO引脚(General Purpose Input/Output,通用输入/输出引脚)是其中的一个重要组成部分。
GPIO引脚允许我们以数字方式读取和控制外部设备,如传感器、LED 灯等等。
然而,在使用GPIO引脚时,我们需要注意其电容范围,以确保系统的正常运行和稳定性。
首先,我们需要了解什么是电容。
电容是一种储存电荷的能力的物理属性。
在电路中,当电容器两端施加电压时,电容器会存储电荷并保持电荷分离。
换句话说,电容是一种可以储存电荷的设备,并且能够在需要时释放电荷。
在嵌入式系统中,电容主要用于电源滤波、信号耦合和稳定性控制等方面。
接下来,我们将讨论STM32 GPIO引脚的电容范围。
在STM32中,每个GPIO引脚都有一个电容限制,即可以接受或驱动的电容的最大值。
通常情况下,GPIO引脚的电容范围是以pF(皮法)为单位进行度量。
pF是电容的单位,表示皮法。
对于STM32F4系列微控制器,每个GPIO引脚的电容范围通常为25pF。
这意味着每个GPIO引脚可以驱动或接受的电容最大为25pF。
如果我们连接的外部设备的电容超过了这个范围,可能会导致信号衰减、传输错误或电路不稳定等问题。
然而,需要注意的是,这个电容范围并不是固定不变的。
它取决于多种因素,包括工作频率、驱动能力和电路设计等。
在使用GPIO引脚时,我们应该根据具体的系统要求和外部设备的电容值来选择合适的引脚和电路设计。
为了更好地应对高电容负载,STM32还提供了一些增强的GPIO引脚,称为高驱动能力(GPIO High Drive)引脚。
这些引脚具有更高的电容范围,并能够驱动更高电容负载的外部设备。
STM32 GPIO 相关寄存器每个GPIO端口有两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH)分别控制每个端口的高八位和低八位,如果IO口是0-7号的话,则写CRL寄存器,如果IO口是8-15号的话,则写CRH寄存器,两个32位数据寄存器(GPIOx_IDR,GPIOx_ODR)一个是只读作输入数据寄存器,一个是只写作输出寄存器,一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。
常用的IO端口寄存器只有四个:CRH,CRL,IDR,ODR.数据手册中列出的每个I/O端口的特定硬件特征, GPIO端口的每个位可以由软件分别配置成多种模式。
每个I/O端口位可以自由编程,然而I/0端口寄存器必须按32位字被访问(不允许半字或字节访问)。
另外,STM32的每个端口使用前都要将其时钟使能,STM32的GPIO的时钟统一挂接在APB2上,具体的使能寄存器为RCC_APB2ENR,该寄存器的第2位到第8位分别控制GPIOx(x=A,B,C,D,E,F,G)端口的时钟使能,当外设时钟没有启用时,程序不能读出外设寄存器的数值,如打开PORTA 时钟:RCC—>APB2ENR|=1〈<2; //使能PORTA时钟使能外设时钟后,GPIOA的十六位就可以按照设定的状态工作了,之后就是具体设置哪一位了以第八位为例即高位的首位,在GPIOx_CRH寄存器中进行设置,GPIOA的每一位都有该寄存器的四位来设定相应的参数,这四位中的高两位(CNF0,CNF1)设置GPIO的输入输出模式,低两位(MODE0,MODE1)是设置GPIO的输出频率,具体可以参考STM32参考手册。
GPIOA->CRH&=0XFFFFFFF0; //清掉PA8原来的设置,同时屏蔽其它端口,不影响其它端口的设置GPIOA—〉CRH|=0X00000003;//PA8 推挽输出十六进制中的3 换成二进制 00 11 前两位00表示推挽输出,11代表输出频率50Mhz,若CRH|=0x4,表示模拟输入模式(ADC用),0x3表示推挽输出模式(作输出口用,50M速率),0x8表示上/下拉输入模式(做输入口用),0xB表示复用输出(使用IO口的第二功能,50M速率). 这是对一位的操作,当然也可以多位操作,因为STM32对GPIO操作必须是32位全字操作,设置完成后GPIOA的第8位就可以使用了之后给GPIOA—>ODR=0x xxxx xxxx送数据就行了。
STM32中GPIO的理解
一、什么是GPIO
GPIO,英文全称为General-Purpose IO ports,也就是通用IO口。
嵌入式系统中常常有数量众多,但是结构却比较简单的外部设备/电路,对这些设备/电路有的需要CPU为之提供控制手段,有的则需要被CPU用作输入信号。
而且,许多这样的设备/电路只要求一位,即只要有开/关两种状态就够了,比如灯亮与灭。
对这些设备/电路的控制,使用传统的串行口或并行口都不合适。
所以在微控制器芯片上一般都会提供一个“通用可编程IO接口”,即GPIO。
接口至少有两个寄存器,即“通用IO控制寄存器”与“通用IO数据寄存器”。
数据寄存器的各位都直接引到芯片外部,而对这种寄存器中每一位的作用,即每一位的信号流通方向,则可以通过控制寄存器中对应位独立的加以设置。
这样,有无GPIO接口也就成为微控制器区别于微处理器的一个特征。
二、STM32中GPIO的结构
STM32的DGPIO口最多可以有7组(GPIOA~GPIOG),而每一组GPIO口均有16个双向IO端口位组成。
每个GPIO端口有:
(1)两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH)
分别控制每个端口的高八位和低八位,如果IO口是0-7号的话,则写CRL寄存器,如果IO口是8-15号的话,则写CRH寄存器。
(2)两个32位数据寄存器(GPIOx_IDR,GPIOx_ODR)
端口输入数据寄存器(GPIOX_IDR):其中高16位是保留的,低十六位对应着16个IO 口的数据位。
端口输出数据寄存器(GPIOX_ODR):其中高16位是保留的,低十六位对应着16个IO 口的数据位。
(3)一个32位置位/复位寄存器(GPIOx_BSRR)(置位/复位寄存器:Set/Reset Register)(4)一个16位复位寄存器(GPIOx_BRR)(复位寄存器:Reset Register)
(5)一个32位锁定寄存器(GPIOx_LCKR)。
常用的IO端口寄存器只有四个:CRH,CRL,IDR,ODR。
三、STM32中GPIO的工作方式
(1)GPIO端口的每个位可以由软件分别配置成多种模式。
每个I/O端口位可以自由编程,然而I/0端口寄存器必须按32位字被访问(不允许半字或字节访问)。
(2)STM32的每个端口使用前都要将其时钟使能
STM32的GPIO的时钟统一挂接在APB2上,具体的使能寄存器为RCC_APB2ENR,该寄存器的第2位到第8位分别控制GPIOx(x=A,B,C,D,E,F,G)端口的时钟使能,当外设时钟没有启用时,程序不能读出外设寄存器的数值,如打开PORTA时钟:
RCC->APB2ENR|=1<<2; //使能PORTA时钟
使能寄存器RCC_APB2ENR(32为寄存器)
RCC_APB2ENR的0~15位(06~32位保留)
第2~8分别是使能GPIOA~GPIOG时钟的,只要将其置“1”即可。
(3)对相应的IO模式进行配置,使其按设定的模式进行工作
低8位由GPIOx_CRL配置,高8位由GPIOx_CRH配置。
以PA8为例来进行说明。
PA8即为高位的首位,应在GPIOx_CRH寄存器中进行设置,GPIOA 的每一位都有该寄存器的四位来设定相应的参数,这四位中的高两位(CNF0,CNF1)设置GPIO的输入输出模式,低两位(MODE0,MODE1)是设置GPIO的输出频率,具体可以参考STM32参考手册。
GPIOA->CRH&=0XFFFFFFF0; //清掉PA8原来的设置,但不影响其它端口的设置
GPIOA->CRH|=0X00000003;//PA8 推挽输出
十六进制中的3 换成二进制 00 11 前两位00表示推挽输出,11代表输出频率50Mhz,若CRH|=0x4,表示模拟输入模式(ADC用),0x3表示推挽输出模式(作输出口用,50M速率),0x8表示上/下拉输入模式(做输入口用),0xB表示复用输出(使用IO口的第二功能,50M 速率)。
(4)端口的输入和输出电平配置
该寄存器配置IO口的0~15位的输入初始状态,例如:GPIOA->ODR|=1<<13;//PA13上拉输入。
设置完成后GPIOA的第8位就可以使用了。
之后给GPIOA->ODR=0x xxxx xxxx送数据就
行了。
三、STM32中GPIO的模式
(1)模拟输入(GPIO_Mode_AIN)
模拟输入最重要的一点就是,输入信号不经过输入数据寄存器,所以我们无法通过读取输入数据寄存器来获取模拟输入的值,我觉得这一点也是很好理解的,因为输入数据寄存器中存放的不是0就是1,而模拟输入信号不符合这一要求,所以自然不能放进输入数据寄存器。
该输入模式,使我们可以获得外部的模拟信号。
ADC当然配置为模拟输入。
(2)浮空输入(GPIO_Mode_IN_FLOATING)
该输入状态,我的理解是,它的输入完全由外部决定,我觉得在数据通信中应该可以使用该模式。
应为在数据通信中,我们直观的理解就是线路两端连接着发送端和接收断,他们都需要准确获取对方的信号电平,不需要外界的干预。
所以我觉得这种情况适合浮空输入。
比如我们熟悉的I2C通信。
由于浮空输入一般多用于外部按键输入,结合图上的输入部分电路,我理解为浮空输入状态下,IO的电平状态是不确定的,完全由外部输入决定,如果在该引脚悬空的情况下,读取该端口的电平是不确定的。
读取GPIO,一般配置为浮空输入(比如读取是否有键按下)。
(3)上拉输入(GPIO_Mode_IPU)
上拉输入就是在输入电路上使用了上拉电阻。
这种模式的好处在于我们什么都不输入时,由于内部上拉电阻的原因,我们的处理器会觉得我们输入了高电平,这就避免了不确定的输入。
这在要求输入电平只要高低两种电平的情况下是很有用的。
按键输入时,在没有按键时(没有输入信号的时候)默认输入高电平,有按键时为低电平。
(4)下拉输入(GPIO_Mode_IPD)
和上拉输入类似,不过下拉输入时,在外部没有输入时,我们的处理器会觉得我们输入了低电平。
按键输入时,在没有按键时(没有输入信号的时候)默认输入低电平,有按键时为高电平。
(5)开漏输出(GPIO_Mode_Out_OD)
开漏输出,输出端相当于三极管的集电极,所以适合与做电流驱动的应用。
要得到高电平,需要上拉电阻才可以。
(6)推挽输出(GPIO_Mode_Out_PP)
推挽输出使用了推挽电路,结合推挽电路的特性,它是由两个MOSFET组成,一个导通的同时,另外一个截至,两个MOSFET分别连接高低电平,所以哪一个导通就会输出相应的电平。
推挽电路速度快,输出能力强,直接输出高电平或者低电平。
写GPIO,一般配置为推挽输出(比如去驱动LED)。
(7)复用开漏(GPIO_Mode_AF_OD)和复用推挽(GPIO_Mode_AF_PP)
我们知道这只是对GPIO的复用而已。
使普通的GPIO具有了别的功能。
可以理解为GPIO口被用作第二功能时的配置情况(即并非作为通用IO口使用)。