关于stm32的GPIO的操作

发布者:wmghyu最新更新时间:2019-01-30 来源: eefocus关键字:stm32  GPIO 手机看文章 扫描二维码
随时随地手机看文章

首先先了解一下输出的模式


比较常用的是 推挽输出


1)GPIO_Mode_AIN 模拟输入 


(2)GPIO_Mode_IN_FLOATING 浮空输入


(3)GPIO_Mode_IPD 下拉输入


(4)GPIO_Mode_IPU 上拉输入


(5)GPIO_Mode_Out_OD 开漏输出


(6)GPIO_Mode_Out_PP 推挽输出


(7)GPIO_Mode_AF_OD 复用开漏输出


(8)GPIO_Mode_AF_PP 复用推挽输出

 


首先简述一下stm3的gpio


接口(interface):主机(CPU)与外部设备(指MCU片上外设)之间缓冲电路。它用于完成主机与外部设备设间速度匹配、信号转换,并完成某些控制功能。按数据的传输方式可分为并行接口和串行接口,并行接口指一般I/O接口或通用I/O接口,而串行接口有I2C/SPI/UART等等。


端口(port):I/O接口电路中已经编址并能进行读写操作的寄存器。端口分为数据端口、状态端口及控制端口,普遍存在于各个接口电路中。每个接口电路中都包含一组寄存器,CPU与外部设备进行信息交换时,各类信息在接口中存入不同的寄存器,这些寄存器就是I/O端口,简称I/O口,也称为I/O端口寄存器。


引脚(pin):集成电路与外围电路连接的管脚。


接口(端口)概念是对并行接口和串行接口(I2C/SPI/UART等片上外设)而言的,MCU中大多数的功能模块都有接口电路。狭义上,端口概念往往特指I/O并行接口电路中的寄存器。此外,通常我们所说的“I/O口”指的就是“I/O端口”。


一、GPIO的模式选择


通过GPIO模式寄存器GPIOx_MODER(x是端口名称,x=A…I/J/K)来设置GPIO端口位的方向: 

1、输入模式(复位状态) 

2、GPIO输出模式 

3、复用功能模式 

4、模拟功能模式 

GPIOx_MODER的设置方法,详见技术参考手册TRM。


二、GPIO端口寄存器


每个I/O端口均有下列寄存器,每个端口位均可自由编程,但I/O端口寄存器必须按32位字、半字或字节被访问。其中,GPIOx_BSRR寄存器旨在实现对GPIOx_ODR寄存器进行原子读取/修改访问,具有对GPIOx_ODR按位写权限。


1、4个32位配置寄存器:GPIOx_MODER、GPIOx_OTYPER、GPIOx_OSPEEDR、GPIOx_PUPDR,这些寄存器位可通过软件写入。其中,输出类型寄存器GPIOx_OTYPER是用1个寄存器位设置1个I/O位,其他配置寄存器均是用2个寄存器位设置1个I/O位。


GPIOx_MODER:选择I/O端口方向为 输入/通用输出/AF/模拟,复位状态为输入。


GPIOx_OTYPER:选择输出类型为 推挽/开漏,复位状态为推挽输出。


GPIOx_OSPEEDR:选择I/O输出驱动电路的响应速度为 低速/中速/快速/高速,用于噪声控制。(由下面Table 22. Port bit configuration table 可知,这个速度寄存器只对输出模式和AF起作用)。 

注意:GPIO的引脚速度是指I/O口驱动电路的响应速度而不是输出信号的速度,输出信号的速度与程序有关。此外,如果较高频率的信号经过较低频率的驱动电路输出,那么输出的信号就会产生失真,所以驱动电路的频率和信号的频率之间满足采样定理的要求。驱动电路的频率应该适当不能过大(建议10~20倍于信号的频率),以便降低噪声、功耗和电磁辐射。


GPIOx_PUPDR:选择I/O端口为 无上拉或下拉/上拉/下拉/保留(与IO端口方向无关)。


2、2个32位数据寄存器:GPIOx_IDR、GPIOx_ODR


GPIOx_IDR:这些寄存器位为只读 形式,并且只能在字模式下访问。


GPIOx_ODR:这些寄存器位可通过软件读取和写入。


3、1个32位置位复位寄存器:GPIOx_BSRR


GPIOx_BSRR低半字用来置位GPIOx_ODR,即写入“1”,而高半字用来复位GPIOx_ODR,即写入“0”。GPIOx_BSRR旨在对GPIOx_ODR寄存器进行原子读写操作,它只能在字、半字、字节模式下被访问对GPIOx_ODR进行原子操作。


4、1个32位锁定寄存器:GPIOx_LCKR


锁定寄存器GPIOx_LCKR的每个锁定位用于锁定端口位的配置。冻结的寄存器包括:GPIOx_MODER、GPIOx_OTYPER、GPIOx_OSPEEDR、GPIOx_PUPDR、GPIOx_AFRH、GPIOx_AFRL,它只能以字的方式被访问。锁定寄存器锁定配置后,就会避免因意外改写端口寄存器配置造成大电流损坏芯片的故障或其他故障。


5、2个32位复用功能选择寄存器:GPIOx_AFRH、GPIOx_AFRL


GPIOx_AFRL:用四位寄存器位选择一个对应的复用功能。该寄存器用于选择AF0~AF7。


GPIOx_AFRH:用四位寄存器位选择一个对应的复用功能。该寄存器用于选择AF8~AF15。


复用功能选择寄存器只能通过字被访问。


三、GPIO的工作模式


通过对4种端口配置寄存器进行编程,可将GPIO口的各个端口位配置成以下8种工作模式:


输入+悬空 

输入+上拉 

输入+下拉 

模拟(用作ADC输入、DAC输出或者捕获输入情况下) 

输出+开漏+上拉/下拉(输出模式时GPIO的输出速度是可配置的) 

输出+推挽+上拉/下拉(输出模式时GPIO的输出速度是可配置的) 

复用功能+推挽+上拉/下拉(复用功能时速度是可配置的) 

复用功能+开漏+上拉/下拉(复用功能时速度是可配置的)



● I/O输入通道有个TTL施密特触发器,它用于将变化缓慢的输入信号整形成边沿陡峭的矩形脉冲。同时,施密特触发器利用其回差电压提高了电路的抗干扰能力; 

● 所有的I/O口均兼容TTL电平和CMOS电平; 

● 大多数I/O是5V电压容限(FT 结构的I/O是5V容限,其他结构的I/O不是。详细情况请参见相应的STM32F4数据手册); 

● 当GPIO被配置为模拟功能时,I/O不再是5V电压容限,这时以VDDA为电压容限; 

● 除了端口A和B(主要是PA13/PA14/PA15/PB3/PB4这5个端口位复位后专门用于片上调试模块,不受4个GPIO控制寄存器控制),其他端口的所有端口位复位期间或者复位后都是悬空输入状态; 

● 输出通道中,输出数据寄存器和复用功能输出接到多路复用器,再经过输出控制连接到推挽电路的门极。值得注意的是输出控制会将输出数据寄存器和复用功能输出的电平进行反转(即’1’变’0’,’0’变’1’)。仔细观察会发现P-MOS管的门极有个小圈“。”,它表示P-MOS的门极为低电平’0’时,P-MOS导通。反之,N-MOS是门极为高电平’1’时导通; 

● 推挽输出的驱动能力强,并且推挽输出时,若P-MOS导通,引脚上的电压不会因为外部器件或设备(即引脚带负载)而有所降低; 

● I/O端口位的最大状态切换频率为90MHZ。

● 输出缓冲器被禁止; 

● 施密特触发输入被激活; 

● 根据寄存器GPIOx_PUPDR中的值选择引脚为弱上拉或弱下拉或悬空输入; 

● I/O引脚上的数据在每个AHB1时钟周期被采样到输入数据寄存器; 

● 对输入数据寄存器的读访问可获得I/O状态。



● 输出缓冲器被激活 

─ 开漏模式:输出寄存器上的 ‘0’ 激活N-MOS,而输出寄存器上的 ‘1’ 将端口置于高阻状态(PMOS从不被激活); 

─ 推挽模式:输出寄存器上的 ‘0’ 激活N-MOS,而输出寄存器上的 ‘1’ 将激活P-MOS; 

● 施密特触发器输入被激活; 

● 选择引脚为弱上拉或弱下拉输出或悬空; 

● I/O脚上的数据在每个AHB1时钟周期被采样到输入数据寄存器; 

● 对输入数据寄存器的读访问可得到I/O状态; 

● 对输出数据寄存器的读访问得到最后一次写的值。


由图4可以看出,当I/O端口被配置为复用功能AF(Alternate Function)时: 

● 输出缓冲器可以被配置成开漏或推挽; 

● 输出缓冲器被片上外设信号驱动; 

● 施密特触发器输入被激活; 

● 根据寄存器GPIOx_PUPDR中的值选择引脚为弱上拉或弱下拉或悬空输出; 

● I/O脚上的数据在每个AHB1时钟周期被采样到输入数据寄存器; 

● 对输出数据寄存器的读访问得到最后一次写的值。


 



● 输出缓冲器被禁止; 

● 施密特触发器输入被暂停,0功耗,并且输出一直维持在0值状态; 

● 管脚的弱上拉和下拉被禁止; 

● 访问输入数据寄存器得到的数值为0;


五、GPIO引脚作为一般IO输入时,引脚的状态和端口输入寄存器GPIOx_IDR的状态是否一致?


在学习51核单片机时,由于51单片机I/O接口电路结构的原因,I/O输入时,I/O的引脚状态会出现与锁存器不一样的情况。所以,往往在I/O上拉输入前,提前向锁存器写入“1”,指令上也分为读引脚和读锁存器指令。


那么,基于Cortex-M内核的MCU的I/O引脚输入时是否也有与51单片机同样的问题呢??


答案是否定的!因为Cortex-M内核的MCU的GPIO引脚在被配置为I/O输入时,其输出电路是断开的。这样,输出电路就不会影响到引脚的状态。所以,引脚上的状态和输入寄存器GPIOx_IDR中的数据始终一致。

 


 


为什么要配置端口?

因为GPIO中端口的作用很多,没有固定的一种模式,因此需要配置.

每个GPI/O端口有两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR,GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。


本文引用地址:http://www.eepw.com.cn/article/201611/318989.htm


GPIO端口的每个位可以由软件分别配置成多种模式。每个I/O端口位可以自由编程,然而I/0端口寄存器必须按32位字被访问(不允许半字或字节访问)。GPIOx_BSRR和GPIOx_BRR寄存器允许对任何GPIO寄存器的读/更改的独立访问;这样,在读和更改访问之间产生IRQ时不会发生危险。


配置为输出模式 , 驱动led , 配置思路是什么样的?


使能端口时钟;

选定需要配置的管脚;

配置端口的模式;

初始化端口; 

代码如下:


#include "led.h"

#include "sys.h"

void LED_Init(void)

{

    GPIO_InitTypeDef  GPIO_InitStructure;//结构体变量定义


  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF时钟


  GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_9|GPIO_Pin_10); //LED0=PF9,LED1=PF10

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//输出模式

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50M

  GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化GPIOF

}

以下是配置按键的接口


程序如下:


/按键初始化函数

void KEY_Init(void) //IO初始化

     GPIO_InitTypeDef GPIO_InitStructure;

 

     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//使能PORTA,PORTE时钟


    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//KEY0-KEY2

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入

     GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4


    //初始化 WK_UP-->GPIOA.0      下拉输入

    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉      

    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0


}


 


以下是配置ds18b20的接口


//IO方向设置

#define DS18B20_IO_IN()  {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}

#define DS18B20_IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}

////IO操作函数                                               

#define    DS18B20_DQ_OUT PGout(11) //数据端口    PA0 

#define    DS18B20_DQ_IN  PGin(11)  //数据端口    PA0 



//////IO方向设置  gpio13  每4个位控制1个IO。

//#define DS18B20_IO_IN()  {GPIOG->CRH&=0XFFF0FFFFF;GPIOG->CRH|=8<<20;}

//#define DS18B20_IO_OUT() {GPIOG->CRH&=0XFFF0FFFFF;GPIOG->CRH|=3<<20;}

//////IO操作函数                                               

//#define    DS18B20_DQ_OUT PGout(13) //数据端口    PA0 

//#define    DS18B20_DQ_IN  PGin(13)  //数据端口    PA0 

 


 


 


再看GPIO功能很强大:


1.通用I/O(GPIO):最最基本的功能,可以驱动LED、可以产生PWM、可以驱动蜂鸣器等等;


2.单独的位设置或位清除:方便软体作业,程序简单。端口配置好以后只需GPIO_SetBits(GPIOx, GPIO_Pin_x)就可以实现对GPIOx的pinx位为高电平;


3.外部中断/唤醒线:端口必须配置成输入模式时,所有端口都有外部中断能力;


4.复用功能(AF):复用功能的端口兼有IO功能等。复位期间和刚复位后,复用功能未开启,I/O端口被配置成浮空输入模式:(CNFx[1:0]=01b,MODEx[1:0]=00b)。


5.软件重新映射I/O复用功能:为了使不同器件封装的外设I/O功能的数量达到最优,可以把一些复用功能重新映射到其他一些脚上。这可以通过软件配置相应的寄存器来完成。这时,复用功能就不再映射到它们的原始引脚上了;


6.GPIO锁定机制:主要针对复位设定的,当某端口位lock后,复位后将不改变的此端口的位配置。


GPIO基本设置


GPIOMode_TypeDef GPIO mode定义及偏移地址


GPIO_Mode_AIN = 0x0,//模拟输入


GPIO_Mode_IN_FLOATING = 0x04, //悬空输入


GPIO_Mode_IPD = 0x28,//下拉输入


GPIO_Mode_IPU = 0x48,//上拉输入


GPIO_Mode_Out_OD = 0x14, //开漏输出


GPIO_Mode_Out_PP = 0x10,//推挽输出


GPIO_Mode_AF_OD = 0x1C,//开漏复用


GPIO_Mode_AF_PP = 0x18//推挽复用


GPIO输入输出速度选择:


typedef enum


{


GPIO_Speed_10MHz = 1,


GPIO_Speed_2MHz,


GPIO_Speed_50MHz


}


GPIOSpeed_TypeDef;


#define IS_GPIO_SPEED(SPEED) ((SPEED == GPIO_Speed_10MHz) || (SPEED == GPIO_Speed_2MHz) ||(SPEED == GPIO_Speed_50MHz))


做一个GPIO输出的试验


当I/O端口被配置为推挽模式输出时:输出寄存器上的0激活N-MOS,而输出寄存器上的1将激活P-MOS。


用这段程序实现:GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;


int main(void)


{


#ifdef DEBUG


debug();


#endif


RCC_Configuration();


NVIC_Configuration();


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;


GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;


GPIO_Init(GPIOC, &GPIO_InitStructure);


while (1)


{


GPIO_SetBits(GPIOC, GPIO_Pin_4); //设置PC.04 pin为高电平,点亮LED1


Delay();


GPIO_ResetBits(GPIOC, GPIO_Pin_4); //设置PC.04 pin为低电平,熄灭LED1


Delay();


}


}

关键字:stm32  GPIO 引用地址:关于stm32的GPIO的操作

上一篇:STM32时钟基础知识
下一篇:基于STM32系列的模拟串口(非阻塞式)

推荐阅读最新更新时间:2024-03-16 16:23

stm32 蜂鸣器
蜂鸣器分为两种型号:有源蜂鸣器和无源蜂鸣器 区别:有源的只用提供一个驱动电压就可以工作,但是无源的蜂鸣器需要提供规定赫兹的脉冲信号才能发出声音,声音的大小可以根据占空比进行调节。 #include system.h /*蜂鸣器时钟端口、引脚定义*/ #define BEEP_PORT GPIOB #define BEEP_PIN GPIO_Pin_5 #define BEEP_PORT_RCC RCC_APB2Periph_GPIOB #define beepPBout(5) void BEEP_Init(void); #endif void BEEP_Init() //端口初始化 { GPIO_InitT
[单片机]
STM32 SPI接口读写SPI flash实验
STM32 SPI flash读写测试实验报告 一、实验目的 1.学习SPI的基本工作原理 2.通过实验加深对STM32SPI的理解 3. 利用STM32的SPI11和SPI接口的flash芯片进行通信,读写测试,并将测试结果用串口打印出来 二、实验原理 1.SPI基础知识 SPI特征 ● 3线全双工同步传输 ● 带或不带第三根双向数据线的双线单工同步传输 ● 8或16位传输帧格式选择 ● 主或从操作 ● 支持多主模式 ● 8个主模式波特率预分频系数(最大为fPCLK/2) ● 从模式频率(最大为fPCLK/2) ● 主模式和从模式的快速通信 ● 主模式和从模式下均可以由软件或硬件进行NSS管理:主/从操作模式的动态改变 ● 可编
[单片机]
<font color='red'>STM32</font> SPI接口读写SPI flash实验
STM32 USB 之从0开始移植笔记
-----------------------------------动机----------------------------------- 写在前面的话:最近逛淘宝无意间发现RC522居然只要10元左右就可以包邮买到,真是太便宜了,就忍不住买了个回来玩玩。到货移植到我的板子上OK 后突然发现我的USB口紧张了,一个用来给板子供电一个插jlink 一个插入usb转串口给RC522下命令。就想着将板子供电和RC522传输用一个USB接口来实现。这就是这次折腾USB的来由~-~ ----------------------------------开始折腾USB----------------------------- 首
[单片机]
<font color='red'>STM32</font> USB 之从0开始移植笔记
STM32之独立看门狗的那些事
为什么MCU会具有看门狗呢?带着这个疑问,来了解看门狗的那些事。就连51单片机都带有看门狗,说明这条狗对我们来说有着 不一般的意义。看门狗的目的一句话说:防止程序乱跑。MCU在不同的环境下程序的运行会受到干扰,比如陷入死循环怎么办? 这就是养狗的好处呀,就算你没养过狗,你也看过猪跑吧。 先看固件库的几个函数 void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess); void IWDG_SetPrescaler(uint8_t IWDG_Prescaler); void IWDG_SetReload(uint16_t Reload); void IWDG_ReloadCounter(
[单片机]
STM32硬件i2c的EV卡死问题的终极解决(已通过老化测试40h)
鉴于各位对于stm32的硬件i2c均存在质疑且在此处下载的所有硬件i2c程序均基于一个模板 大家对于硬件i2c的说法均在初始化上而对于发送接收程序并没有多少改动 所以我个人对这一段进行了优化,加上了超时自动跳出和标志位的动作,完美解决了硬件i2c的卡死问题 这里就是一个初始化的程序,应注意,clockspeed不应该高于100k 这是一个初始化的顺序,应注意,i2c的初始化应在RCC和GPIO之后进行 上面这一段就是新增的程序模块,为的是对于易卡死的while循环做出限制,防止死循环。 只需将已有的程序中所有的关于硬件i2c的while循环均加上这一条就可以使用了。 此处如果在I2C1_hardware_wait_ci
[单片机]
<font color='red'>STM32</font>硬件i2c的EV卡死问题的终极解决(已通过老化测试40h)
STM32再学习——实时时钟(RTC)
RTC,是RealTimeCounter的缩写。在MCU中,其实是一组连续计数的计数器,各个产品及系列各不相同。因此,在相应的软件配置下,可提供时钟日历的功能。当然,修改这个计数器的值也就重新设置了系统当前的时间和日期。 本文引用地址:http://www.eepw.com.cn/article/182407.htm RTC只是一个时钟,但与RTC相连的有两个系统时钟,一个是APB1接口的PCLK1另一个是RTC时钟 。这样,RTC功能也就分为两个部分:第一部分,APB1接口部分,与APB1总线相连,MCU也就是通过这条总线对其进行读写操作。另一部,RTC核,由一系列可编程计数器组成,这部分又再细分为两个组件:预分频模块与
[单片机]
<font color='red'>STM32</font>再学习——实时时钟(RTC)
采用STM32的心电采集系统电路设计
心血管类疾病已经成为威胁人类身体健康的重要疾病之一,而清晰有效的心电图为诊断这类疾病提供了依据,心电采集电路是心电采集仪的 关键部分,心电信号属于微弱信号,其频率范围在0.03~100 Hz之间,幅度在0~5 mV之间,同时心电信号还掺杂有大量的干扰信号,因此,设计良好的滤波电路和选择合适的控制器是得到有效心电信号的关键。基于此,本文设计了以STM32 为控制核心,AD620和OP07为模拟前端的心电采集仪,本设计简单实用,噪声干扰得到了有效抑制。 主控模块电路设计 主控模块的STM32F103VET单片机是控制器的核心,该单片机是ST意法半导体公司生产的32位高性能、低成本和低功耗的增强型单片机,其内核采用 ARM公司最
[单片机]
采用<font color='red'>STM32</font>的心电采集系统电路设计
SD NAND在STM32应用上的保姆级教程
SD NAND与正点原子精英板的连接 由于正点原子精英板没有SD NAND接口,只有TF卡接口,所以SD NAND需要用到转接板来连接。 SD NAND正常运行现象 本次实验的程序是正点原子的SD卡实验例程,先用读卡器把SD NAND接到电脑上,并复制一个文件进去,再插到开发板上; 用送的数据线连接USB UART接口,下载好程序,打开电脑上的串口助手,按下KEY0,即可读取到数据, 具体实验步骤和现象可以看例程文件夹中的readme, 另外LED-DS0闪烁也表示SD NAND芯片在正常运行, SD NAND芯片用的是MK-米客方德的工业级芯片MKDV1GIL-AS;MK-米客方德家还有其他各种型号的SD NAN
[单片机]
SD NAND在<font color='red'>STM32</font>应用上的保姆级教程
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved