
- 外文名
- GPIO
- 功 耗
- 大约1μA
- 特殊功能
- GPxDAT 寄存器
- 分 类
- 硬件/嵌入开发驱动开发/核心开发
- 中文名
- 通用输入/输出口
- 全 称
- General Purpose Input Output
- 优 点
- 小封装
-
GPIO
2015-06-28 22:42:431. GPIO 1.1. 原理图 GPIO:General Purpose Input Output GPIO输入例图 GPIO输出例图 GPIO中断例图 1.2. 程序要做的 GPIO输入: GPIO输出: GPIO中断: 1.3. 程序程序示例 GPIO输入: GPIO输出: GPIO...1. GPIO
1.1. 原理图
GPIO:General Purpose Input Output
GPIO输入例图
GPIO输出例图GPIO中断例图
和输入的图是一样的。
1.2. 程序要做的GPIO输入:
1、 配置此GPIO端口的引脚功能,将此GPIO端口配置为输入,实质还是写值到此GPIO端口对应的配置寄存器。
2、 输出数据,写值到此GPIO对口对应的数据寄存器。
GPIO输出:
1、 配置此GPIO端口的引脚功能,将此GPIO端口配置为输出,实质还是写值到此GPIO端口对应的配置寄存器。
2、 输入数据,从此GPIO对口对应的数据寄存器读出数据寄存器的值,并判断出此GPIO端口对应位的值。
GPIO中断:
1、 配置此GPIO端口的引脚功能,将此GPIO端口配置为中断,实质还是写值到此GPIO端口对应的配置寄存器。
2、
1.3. 程序程序示例
GPIO输入:
GPIO输出:
GPIO中断: -
树莓派开发笔记(五):GPIO引脚介绍和GPIO的输入输出使用(驱动LED灯、检测按键)
2018-03-30 15:40:06若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.csdn.net/qq21497936 本文章博客地址:... 目录 前话 树莓派GPIO口硬件资源介绍 引脚分布和功能图 ...Demo1:GPIO口...若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79758560
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)
树莓派开发专栏(点击传送门)
上一篇:《树莓派开发笔记(四):更便捷的开发,qt远程运行(主机qt开发一键远程运行到目标机上) 》
下一篇:《树莓派开发笔记(六):GPIO口的UART的使用(串口通讯)》
前话
搭建好完整的Qt开发环境,对于开发Qt应用按照正常的开发即可,操作io口涉及到单片机硬件知识,本篇介绍树莓派类似于单片机的GPIO口使用(硬件+软件)。
树莓派GPIO口硬件资源介绍
引脚分布和功能图
统计下硬件资源
- GPIO引脚 x 26
- UART总线 x 1
- SPI总线 x 1
- I2C总线 x 1
- 5V x 2
- 3.3V x 2
- GND x 8
模块化代码
我们模块化代码,写一个引脚输出的程序,以后需要类似直接修改引脚编号(或枚举)即可。
引入libwiringPi库。
关于wiringPi库
在qt中控制GPIO主要是使用wiring,树莓派已自带,我们查询树莓派的物理引脚与wiringPi库的编号对应表,如下图:
如果我们要操作GPIO2,对应的物理引脚为3,如下图:
我们操作引脚的时候,引脚序号就为8(wPI),当前模式为输出,V代表的是当前的输入电压,1:3.3V,0:0V。
更详细的具体参照Demo1理解。
同时,我们在工程中要加入对应的头文件和库,如何调用wiringPi,请参照具体例程。
Demo1:GPIO口的输出
使用物理引脚3,默认功能为GPIO2,我们使用GPIO2驱动LED,此时涉及到硬件知识,树莓派的GPIO口的输出电压为3.3V,所以先设置GPIO为输出高低电平,间隔1s,因为是测试,不使用限流电阻。
限流电阻解释下:电路VCC--->电阻R--->LED--->GND,LED分压为固定的,VCC减去LED压降后得到的电压除以电阻R则是该条电路的电流,所以电阻决定了电流大小,故称之为限流电阻,一般的GPIO口都对电流有要求,例如stm32的单个GPIO口不超过25mA,总的电流也有限制,所以在开发的过程中,需要根据实际情况设计电路原理图。
电路原理图
跳线的电路原理图如下:
关键代码
初始化
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); _gpioOut.init(GpioOut::GPIO2, false); ui->label_gpio2->setStyleSheet(QString("background-color: %1").arg("green")); startTimer(1000); }
每1s钟切换
void MainWindow::timerEvent(QTimerEvent *event) { if(_gpioOut.readOutput(GpioOut::GPIO2)) { _gpioOut.setOutput(GpioOut::GPIO2, false); ui->label_gpio2->setStyleSheet(QString("background-color: %1").arg("green")); }else{ _gpioOut.setOutput(GpioOut::GPIO2, true); ui->label_gpio2->setStyleSheet(QString("background-color: %1").arg("red")); } }
模块代码
gpiocout.h
#ifndef GPIOOUT_H #define GPIOOUT_H #include <QObject> #include <QMap> #include <QDebug> #include "wiringPi.h" class GpioOut : public QObject { Q_OBJECT public: enum GPIO{ GPIO2 = 3, }; public: explicit GpioOut(QObject *parent = 0); public slots: void init(GPIO pin, bool output = false); void setOutput(GpioOut::GPIO pin, bool output); bool readOutput(GpioOut::GPIO pin); private: QMap<GPIO, int> _mapPhysical2Wiring; }; #endif // GPIOOUT_H gpioout.cpp #include "gpioout.h" GpioOut::GpioOut(QObject *parent) : QObject(parent) { wiringPiSetup(); _mapPhysical2Wiring.insert(GPIO2, 8); } void GpioOut::init(GpioOut::GPIO pin, bool output) { pinMode(_mapPhysical2Wiring.value(pin), OUTPUT); digitalWrite(_mapPhysical2Wiring.value(pin), output?HIGH:LOW); } void GpioOut::setOutput(GpioOut::GPIO pin, bool output) { digitalWrite(_mapPhysical2Wiring.value(pin), output?HIGH:LOW); } bool GpioOut::readOutput(GpioOut::GPIO pin) { return digitalRead(_mapPhysical2Wiring.value(pin)); }
运行效果
Demo2:GPIO口的输入
使用物理引脚3,默认功能为GPIO2,我们使用GPIO2接受输入,此时涉及到硬件知识,让树莓派的GPIO口的输入电压为3.3V/0V即为输入1还是输入0,也涉及到限流电阻,一般使用1K或者10K的,因为是测试,此处不使用限流电阻,在开发的过程中,需要根据实际情况设计电路原理图。
电路原理图
关键代码
初始化
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); _gpioIn.init(GpioIn::GPIO2); bool in = _gpioIn.readOutput(GpioIn::GPIO2); ui->label_gpio2->setStyleSheet(QString("background-color: %1").arg(in?"red":"green")); startTimer(1000); }
每一秒钟检测一次
void MainWindow::timerEvent(QTimerEvent *event) { bool in = _gpioIn.readOutput(GpioIn::GPIO2); ui->label_gpio2->setStyleSheet(QString("background-color: %1").arg(in?"red":"green")); }
模块代码
gpioin.h
#ifndef GPIOIN_H #define GPIOIN_H #include <QObject> #include <QMap> #include <QDebug> #include "wiringPi.h" class GpioIn : public QObject { Q_OBJECT public: enum GPIO{ GPIO2 = 3, }; public: explicit GpioIn(QObject *parent = 0); public slots: void init(GPIO pin); bool readOutput(GpioIn::GPIO pin); private: QMap<GPIO, int> _mapPhysical2Wiring; }; #endif // GPIOIN_H gpioin.h #include "gpioin.h" GpioIn::GpioIn(QObject *parent) : QObject(parent) { wiringPiSetup(); _mapPhysical2Wiring.insert(GPIO2, 8); } void GpioIn::init(GpioIn::GPIO pin) { pinMode(_mapPhysical2Wiring.value(pin), OUTPUT); } bool GpioIn::readOutput(GpioIn::GPIO pin) { return digitalRead(_mapPhysical2Wiring.value(pin)); }
运行效果
上一篇:《树莓派开发笔记(四):更便捷的开发,qt远程运行(主机qt开发一键远程运行到目标机上) 》
下一篇:《树莓派开发笔记(六):GPIO口的UART的使用(串口通讯)》
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79758560 -
STM32 GPIO详解
2020-07-10 13:52:57下文将根据STM32F207参考手的中GPIO框图讲解GPIO功能。 01、I/O接口电路 带FT的是说明可以容忍5V电压的,I/O电路框图 1.1、普通输入 普通输入模式下,上拉和下拉电阻(微弱)的存在,共分3种模式 浮空输入...目录
下文将根据STM32F207参考手的中GPIO框图讲解GPIO功能。
01、I/O接口电路
带FT的是说明可以容忍5V电压的,I/O电路框图
1.1、普通输入
普通输入模式下,上拉和下拉电阻(微弱)的存在,共分3种模式
-
浮空输入,不使能上拉电阻,不使能下拉电阻
-
上拉输入,使能上拉电阻
-
下拉输入,使能下拉电阻
从上面框图得知,输出缓存是被禁止的
1.2、普通输出
普通输入模式下,上拉和下拉电阻(微弱)的存在。主要是由于P-MOS和N-MOS的存在分为下列两种模式
-
开漏模式:输出寄存器是 0 时,激活 N-MOS, 而输出寄存器是 1 时,端口保持高阻态(P-MOS 不会被使能)
-
推挽输出: 输出寄存器是 0 时,激活 N-MOS, 而输出寄存器是 1 时,激活 P-MOS
从上面的框图得知,
1、在普通输出模式中,TTL施密特触发器是打开的,所以读输入数据寄存器,可以得到 I/O 的状态。
2、驱动GPIO输出,我们可以采用输出寄存器也可以使用位段
1.3、模拟输入
模拟输入上拉电阻和下拉电阻是没有用的
高阻态下模拟输入
从上面框图得知
-
弱上拉和下拉电阻禁止
-
施密特触发器停用,施密特触发器输出值强制为0
-
输出缓存被禁止
-
读输入数据期存器, 读到的值为0
注意:IO配置成模拟输入时,不能容忍5V电压
1.4、复用输出
复用输出框图
从上图框图中可以得到5条信息
-
输出缓存被来自外设的信号驱动(发送数据器使能和数据),也即是位设置/清除寄存器和输出数据寄存器在这里是无用的
-
由于P-MOS和N-MOS使能,仍然可以配置成推挽输出和开漏输出
-
上拉电阻和下拉电阻使能,可以进行配置
-
TTL施密特触发器使能
-
可以通过读输入数据寄存器, 可以得到 I/O 的状态
02、管脚复用和重映射
管脚复用和重映射(其实是一回事),STMF10X系列叫重映射,STMF20X系列叫管脚复用,也就是复用功能
2.1、STMF10X系列
STM32上有很多I/O口,也有很多的内置外设想I2C,ADC,ISP,USART等,为了节省引出管脚,这些内置外设基本上是与I/O口共用管脚的,也就是I/O管脚的复用功能。但是STM32还有一特别之处就是:很多复用内置的外设的I/O引脚可以通过重映射功能,从不同的I/O管脚引出,即复用功能的引脚是可通过程序改变的。
三个红框交汇处.STM32F103VCT6这个CPU的USART1接的是PB6/PB7但是上电初始化后默认功能并非是USART1.所以想要用串口功能.必须用端口重映射。
STM32的单片机每个功能模块有自己的时钟系统,所以要想要调用STM32单片机的功能模块时必须先配置对应时钟,然后才能去操作相应的功能模块.端口重映射也一样.如图示:
重映射步骤为:
1.打开重映射时钟和USART重映射后的I/O口引脚时钟,
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_AFIO,ENABLE);
2.I/O口重映射开启.
GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
3.配制重映射引脚, 这里只需配置重映射后的I/O,原来的不需要去配置.
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin =GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB,&GPIO_InitStructure);
2.1、STMF20X系列
STMF20X系列(包括之后的40系列)是没有重映射的说法,只有统一的称为复用功能。
从上图看出F10X系列会有专门的普通IO寄存器,会有复用寄存器,使用库函数如下:
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalStateNewState)
从上图F20X系列使用了复用功能寄存器,然不是像F10系列存在专门的复用寄存器,F20X系列GPIO复用的功能更广。
备注:要先配置GPIO为复用功能,再调用复用的库函数
03、相关名词解释
GPIO模式名字解释
GPIO_Mode
全拼
描述
GPIO_Mode_AIN
Analogue In
模拟输入
GPIO_Mode_IN_FLOATING
Float In
浮空输入
GPIO_Mode_IPD
In Pull Down
下拉输入
GPIO_Mode_IPU
In Pull Up
上拉输入
GPIO_Mode_Out_OD
Out Drain
开漏输出
GPIO_Mode_Out_PP
Push Pull
推挽输出
GPIO_Mode_AF_OD
Alternate Function
复用开漏输出
GPIO_Mode_AF_PP
Alternate Function
复用推挽输出
F20系列:GPIO共有四种功能
typedef enum { GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */ GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */ GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */ GPIO_Mode_AN = 0x03 /*!< GPIO Analog Mode */ }GPIOMode_TypeDef;
GPIO状态
推挽输出
可以输出强高低电平,连接数字器件。
开漏输出
只可以输出强低电平,高电平需要外部电阻拉高,输出端相当于三极管的集电极,要得到高电平,需要上拉电阻,适合做电流型的驱动,其吸收电流negligence相对强(一般20ma以内)
高阻态
高阻态是一个数字电路里常见的术语,指的是电路的一种输出状态,既不是高电平也不是低电平,如果高阻态再输入下一级电路的话,对下级电路无任何影响,和没接一样,如果用万用表测的话有可能是高电平也有可能是低电平,随它后面接的东西定的。如果设置为浮空输入,也就是既没有上拉电阻,没有下拉电阻。可以认为是高阻态。
点击查看本文所在的专辑,STM32F207教程
关注公众号,第一时间收到文章更新。评论区不能及时看到,需要交流可以到公众号沟通
-
-
STM32开发 -- GPIO详解
2018-06-13 16:41:59之前有简单讲过GPIO工作模式和寄存器,还是有点没搞明白。这次需要全方位的看一下了。 一、数据手册 1、STM32F105RC引脚说明 可知:STM32F105RC 一共有4组IO口 一共16X3+3=51个IO GPIOA0~A15...如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/80681244
之前有简单讲过GPIO工作模式和寄存器,还是有点没搞明白。这次需要全方位的看一下了。
一、数据手册
1、STM32F105RC引脚说明
可知:STM32F105RC
一共有4组IO口
一共16X3+3=51个IO
GPIOA0~A15
GPIOB0~B15
GPIOC0~C15
GPIOD0~D22、程序定义
GPIO端口号
STM32F105RC使用GPIO端口号为:GPIOA、GPIOB、GPIOC、GPIOD
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)GPIO I/O口(gpio_init.GPIO_Pin)
#define GPIO_Pin_0 ((uint16_t)0x0001) /!< Pin 0 selected /
#define GPIO_Pin_1 ((uint16_t)0x0002) /!< Pin 1 selected /
#define GPIO_Pin_2 ((uint16_t)0x0004) /!< Pin 2 selected /
#define GPIO_Pin_3 ((uint16_t)0x0008) /!< Pin 3 selected /
#define GPIO_Pin_4 ((uint16_t)0x0010) /!< Pin 4 selected /
#define GPIO_Pin_5 ((uint16_t)0x0020) /!< Pin 5 selected /
#define GPIO_Pin_6 ((uint16_t)0x0040) /!< Pin 6 selected /
#define GPIO_Pin_7 ((uint16_t)0x0080) /!< Pin 7 selected /
#define GPIO_Pin_8 ((uint16_t)0x0100) /!< Pin 8 selected /
#define GPIO_Pin_9 ((uint16_t)0x0200) /!< Pin 9 selected /
#define GPIO_Pin_10 ((uint16_t)0x0400) /!< Pin 10 selected /
#define GPIO_Pin_11 ((uint16_t)0x0800) /!< Pin 11 selected /
#define GPIO_Pin_12 ((uint16_t)0x1000) /!< Pin 12 selected /
#define GPIO_Pin_13 ((uint16_t)0x2000) /!< Pin 13 selected /
#define GPIO_Pin_14 ((uint16_t)0x4000) /!< Pin 14 selected /
#define GPIO_Pin_15 ((uint16_t)0x8000) /!< Pin 15 selected /
#define GPIO_Pin_All ((uint16_t)0xFFFF) /!< All pins selected /二、GPIO工作方式
这里的输入、输出是相对于MCU来说的。
举个栗子:
GSM状态引脚,连接MCU PC8引脚。
STATUS 输出高电平开机、低电平关机。
相对于MCU来说,就是输入高电平开机、低电平关机。
1、GPIO 8种工作模式(gpio_init.GPIO_Mode)
(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 复用推挽输出2、程序定义
/**
- @brief Configuration Mode enumeration
/
typedef enum
{
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 / 推挽式复用 输出 */
}GPIOMode_TypeDef;
3、详解
什么是推挽和开漏,
参看:S5PV210开发 – I2C 你知道多少?(三)GPIO_Mode_AIN 模拟输入
施密特触发器是关闭的,信号直接到ADC输入;
STM32的模拟输入通道的配置则更加简单,信号从左边编号1的端口进入,从右边编号2的一端直接进入ADC模块。
这里我们看到所有的上拉、下拉电阻和施密特触发器,均处于断开状态,因此输入数据寄存器将不能反映端口上的电平状态,也就是说,模拟输入配置下,CPU不能在输入数据寄存器上读到有效的数据。GPIO_Mode_IN_FLOATING 浮空输入
图中施密特触发器是开启的,IO口的状态可以直接送到输入寄存器中,CPU可以直接读取输入寄存器;
在上图中,阴影的部分处于不工作状态,尤其是下半部分的输出电路,实际上是与端口处于隔离状态。
黄色的高亮部分显示了数据传输通道,外部的电平信号通过左边编号1的IO端口进入STM32,经过编号2的施密特触发器的整形送入编号3的输入数据寄存器,在输入数据寄存器的另一端编号4,CPU可以随时读出IO端口的电平状态。GPIO_Mode_IPD 下拉输入
GPIO_Mode_IPU 上拉输入
上图是STM32的GPIO带上拉输入模式的配置。与前面的浮空输入模式相比,仅仅是在数据通道上部,接入了一个上拉电阻,根据STM32的数据手册,这个上拉电阻阻值介于30K~50K。
同样,CPU可以随时在输入数据寄存器的另一端,读出IO端口的电平状态。GPIO_Mode_Out_OD 开漏输出
当CPU在编号1端通过“位设置/清楚寄存器”或“输出数据寄存器”写入数据后,该数据位通过编号2的输出控制电路传送到编号4的IO端口。
如果CPU写入的是逻辑1,则编号3的N-MOS管将处于关闭状态,此时IO端口的电平将由外部的上拉电阻决定,如果CPU写入的是逻辑0,则编号3的N-MOS管将处于开启状态,此时IO端口的电平被编号3的N-MOS管拉到了VSS的零电位。
在上图的上半部,施密特触发器处于开启状态,这意味着CPU可以在“输入数据寄存器”的另一端,随时监控IO端口的状态;通过这个特性,还实现了虚拟的IO端口双向通信,只要CPU输出逻辑1,由于编号3的N-MOS管处于关闭状态,IO端口的电平将完全由外部电路决定,因此,CPU可以在“输入数据寄存器”读到外部电路的信号,而不是它自己输出的逻辑1。
GPIO口的输出模式下,有3种输出速度可选(2MHz、10MHz和50MHz),这个速度是指GPIO口驱动电路的响应速度,而不是输出信号的速度,输出信号的速度与程序有关(芯片内部在IO口的输出部分安排了多个响应速度不同的输出驱动电路,用户可以根据自己的需要选择合适的驱动电路)。通过选择速度来选择不同的输出驱动模块,达到最佳的噪声控制和降低功耗的目的。高频的驱动电路,噪声也高,当不需要高的输出频率时,请选用低频驱动电路,这样非常有利于提高系统的EMI性能。当然如果要输出较高的频率的信号,但却选用了较低频率的驱动模块,很可能会得到失真的输出信号。GPIO_Mode_Out_PP 推挽输出
GPIO_Mode_AF_OD 复用开漏输出
GPIO_Mode_AF_PP 复用推挽输出
GPIO推挽复用输出模式,编号2的输出控制电路的输入,与复用功能的输出端相连,此时输出数据寄存器被从输出通道断开了,并和片上外设的输出信号连接。我们将GPIO配置成复用输出功能后,如果外设没有被激活,那么它的输出将不确定,其它部分与前述模式一致,包括对“输入数据寄存器”的读取。
4、应用场合
①上拉输入、下拉输入可以用来检测外部信号;例如,按键等;
②浮空输入模式,由于输入阻抗较大,一般把这种模式用于标准通信协议的I2C、USART的接收端;
③普通推挽输出模式一般应用在输出电平为0和3.3V的场合。而普通开漏输出模式一般应用在电平不匹配的场合,如需要输出5V的高电平,就需要在外部一个上拉电阻,电源为5V,把GPIO设置为开漏模式,当输出高阻态时,由上拉电阻和电源向外输出5V电平。
④对于相应的复用模式(复用输出来源片上外设),则是根据GPIO的复用功能来选择,如GPIO的引脚用作串口的输出(USART/SPI/CAN),则使用复用推挽输出模式。如果用在I2C、SMBUS这些需要线与功能的复用场合,就使用复用开漏模式。
⑤在使用任何一种开漏模式时,都需要接上拉电阻。三、GPIO 寄存器
1、GPIO 寄存器
每组IO口含下面7个寄存器。也就是7个寄存器,一共可以控制一组GPIO的16个IO口。
GPIOx->CRL :端口配置低寄存器
GPIOx->CRH:端口配置高寄存器
GPIOx->IDR:端口输入寄存器
GPIOx->ODR:端口输出寄存器
GPIOx->BSRR:端口位设置/清除寄存器
GPIOx->BRR :端口位清除寄存器
GPIOx->LCKR:端口配置锁存寄存器2、程序定义
下面有个volatile 被宏定义为 __IO,volatile 起到什么作用?
参看:C语言再学习 – 关键字volatile#define __IO volatile /*!< defines ‘read / write’ permissions */
typedef struct
{
__IO uint32_t CRL; //端口配置低寄存器
__IO uint32_t CRH; //端口配置高寄存器
__IO uint32_t IDR; //端口输入寄存器
__IO uint32_t ODR; //端口输出寄存器
__IO uint32_t BSRR; //端口位设置/清除寄存器
__IO uint32_t BRR; //端口位清除寄存器
__IO uint32_t LCKR; //端口配置锁存寄存器
} GPIO_TypeDef;3、详解各个寄存器
参看:STM32F103学习记录-----GPIO篇
这些寄存器有集成到各个函数里的。
比如:
GPIO_SetBits 置高
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));GPIOx->BSRR = GPIO_Pin;
}参看:C语言再学习 – 位操作
当然也可以这么用:
//使用寄存器结构体指针点亮LED
int main(void)
{
#if 0 //直接通过操作内存来控制寄存器
RCC_APB2ENR |= (1<<3);// 开启 GPIOB 端口时钟
GPIOB_CRL &= ~( 0x0F<< (40));//清空控制 PB0 的端口位
GPIOB_CRL |= (1<<40);// 配置 PB0 为通用推挽输出,速度为 10M
GPIOB_ODR |= (0<<0);// PB0 输出 低电平
while (1);
#else// 通过寄存器结构体指针来控制寄存器
RCC->APB2ENR |= (1<<3);// 开启 GPIOB 端口时钟
GPIOB->CRL &= ~( 0x0F<< (40));//清空控制 PB0 的端口位
GPIOB->CRL |= (1<<40);// 配置 PB0 为通用推挽输出,速度为 10M
GPIOB->ODR |= (0<<0);// PB0 输出 低电平
while (1);
#endif
}端口配置低寄存器(GPIOx->CRL)
端口配置高寄存器(GPIOx->CRH)
端口输入数据寄存器(GPIOx->IDR)
端口输出数据寄存器(GPIOx->ODR)
端口位设置/清除寄存器(GPIOx->BSRR)
端口位清除寄存器(GPIOx->BRR)
四、大同小异的初始化
有很多外设的初始化,但是基本上大同小异吧。我们以最简单的点亮LED来看一下。
1、初始化程序
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能 PB,PE 端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0–>PB.5 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1–>PE.5 推挽输出
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_SetBits(GPIOE,GPIO_Pin_5); /PE.5 输出高2、解析
GPIO_InitTypeDef GPIO_InitStructure;
定义一个 GPIO_InitTypeDef 类型的结构体
typedef struct
{
uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured.
This parameter can be any value of @ref GPIO_pins_define */GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins.
This parameter can be a value of @ref GPIOSpeed_TypeDef */GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins.
This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);
使能 GPIOB,GPIOE 端口时钟
启用或禁用高速APB(APB2)外设时钟。
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->APB2ENR |= RCC_APB2Periph;
}
else
{
RCC->APB2ENR &= ~RCC_APB2Periph;
}
}启用或禁用低速APB(APB1)外设时钟。
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->APB1ENR |= RCC_APB1Periph;
}
else
{
RCC->APB1ENR &= ~RCC_APB1Periph;
}
}这里思考一个问题?哪些该用APB1(低速)、哪些该用APB2(高速)呢?
APB2负责 AD,I/O,高级TIM,串口1。
APB1负责 DA,USB,SPI,I2C,CAN,串口2345,普通TIM,PWR
高低速时钟频率多大呢?
这个后续讲时钟时再看!!!GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
选择待设置的GPIO管脚,上面有提到GPIO有16个I/O口。多个I/O中间加位操作符 “|”
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
设置选中GPIO管脚的模式,上面有提到GPIO共有8种工作模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
设置选中GPIO管脚的速率
typedef enum
{
GPIO_Speed_10MHz = 1, //最高输出速率10MHz
GPIO_Speed_2MHz, //最高输出速率2MHz
GPIO_Speed_50MHz //最高输出速率50MHz
}GPIOSpeed_TypeDef;思考,GPIO_Speed GPIO的速度该如何选择呢?
参看:stm32引脚速度GPIO_Speed的区别
I/O口的输出模式下,有3种输出速度可选(2MHz、10MHz和50MHz),这个速度是指I/O口驱动电路的响应速度而不是输出信号的速度,输出信号的速度与程序有关(芯片内部在I/O口 的输出部分安排了多个响应速度不同的输出驱动电路,用户可以根据自己的需要选择合适的驱动电路)。通过选择速度来选择不同的输出驱动模块,达到最佳的噪声 控制和降低功耗的目的。高频的驱动电路,噪声也高,当不需要高的输出频率时,请选用低频驱动电路,这样非常有利于提高系统的EMI性能。当然如果要输出较高频率的信号,但却选用了较低频率的驱动模块,很可能会得到失真的输出信号。举个栗子:
① USART串口,若最大波特率只需115.2k,那用2M的速度就够了,既省电也噪声小。
② I2C接口,若使用400k波特率,若想把余量留大些,可以选用10M的GPIO引脚速度。
③ SPI接口,若使用18M或9M波特率,需要选用50M的GPIO的引脚速度。GPIO_Init(GPIOB, &GPIO_InitStructure);
根据GPIO_InitStructure中指定的参数初始化外设GPIOX
GPIO_SetBits(GPIOB,GPIO_Pin_5);
将端口GPIOB的第5引脚置1(高电平), 多个I/O中间加位操作符 “|”
五、GPIO常用函数
打开 stm32f10x_gpio.c,可以看到 GPIO 相关函数。我们简单看一下这些函数的功能
参看:STM32中使用GPIO的总结(超强)
下面出现的Bit_RESET = 0,Bit_SET = 1
typedef enum
{ Bit_RESET = 0,
Bit_SET
}BitAction;1、GPIO_ReadInputDataBit
功能描述:读取指定端口管脚的输入
例:
u8 ReadValue;
ReadValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7);
返回值为:0(低电平)、1(高电平)函数解析
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint8_t bitstatus = 0x00;/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GET_GPIO_PIN(GPIO_Pin));if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
// GPIOx->IDR:端口输入寄存器
{
bitstatus = (uint8_t)Bit_SET;
}
else
{
bitstatus = (uint8_t)Bit_RESET;
}
return bitstatus;
}2、GPIO_ReadInputData
功能描述:读取指定的GPIO端口输入
例:
u16 ReadValue;
ReadValue = GPIO_ReadInputData(GPIOC);函数解析
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));return ((uint16_t)GPIOx->IDR);
}3、GPIO_ReadOutputDataBit
功能描述:读取指定端口管脚的输出
例:
u8 ReadValue;
ReadValue = GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_7);函数解析
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint8_t bitstatus = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GET_GPIO_PIN(GPIO_Pin));if ((GPIOx->ODR & GPIO_Pin) != (uint32_t)Bit_RESET)
{
bitstatus = (uint8_t)Bit_SET;
}
else
{
bitstatus = (uint8_t)Bit_RESET;
}
return bitstatus;
}4、GPIO_ReadOutputData
功能描述:读取指定的GPIO端口输出
例:
u16 ReadValue;
ReadValue = GPIO_ReadOutputData(GPIOC);函数解析
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));return ((uint16_t)GPIOx->ODR);
}5、GPIO_SetBits
功能描述:置位指定的数据端口位
例: 将端口GPIOA的第10、15脚置1(高电平)
GPIO_SetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_15);函数解析
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));GPIOx->BSRR = GPIO_Pin;
}6、GPIO_ResetBits
功能描述:清除指定的数据端口位
例:将端口GPIOA的第10、15脚置0(低电平)
GPIO_ResetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_15);函数解析
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));GPIOx->BRR = GPIO_Pin;
}7、GPIO_WriteBit
功能描述:设置或者清除指定的数据端口位
例:
GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_SET);函数解析
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
assert_param(IS_GPIO_BIT_ACTION(BitVal));if (BitVal != Bit_RESET)
{
GPIOx->BSRR = GPIO_Pin;
}
else
{
GPIOx->BRR = GPIO_Pin;
}
}8、GPIO_Write
功能描述:向指定GPIO数据端口写入数据
例:
GPIO_Write(GPIOA, 0x1101);函数解析
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));GPIOx->ODR = PortVal;
}9、GPIO_PinLockConfig
功能描述:锁定GPIO管脚设置寄存器
例:
GPIO_PinLockConfig(GPIOA, GPIO_Pin_0 | GPIO_Pin_1);函数解析
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint32_t tmp = 0x00010000;/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));tmp |= GPIO_Pin;
/* Set LCKK bit /
GPIOx->LCKR = tmp;
/ Reset LCKK bit /
GPIOx->LCKR = GPIO_Pin;
/ Set LCKK bit /
GPIOx->LCKR = tmp;
/ Read LCKK bit*/
tmp = GPIOx->LCKR;
/* Read LCKK bit*/
tmp = GPIOx->LCKR;
}10、GPIO_EventOutputConfig
功能描述:选择GPIO管脚用作事件输出
例:
GPIO_EventOutputConfig(GPIO_PortSourceGPIOE, GPIO_PinSource5);GPIO_PortSource
GPIO_PortSource用以选择用作事件输出的GPIO端口。函数解析
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
{
uint32_t tmpreg = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_EVENTOUT_PORT_SOURCE(GPIO_PortSource));
assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));tmpreg = AFIO->EVCR;
/* Clear the PORT[6:4] and PIN[3:0] bits */
tmpreg &= EVCR_PORTPINCONFIG_MASK;
tmpreg |= (uint32_t)GPIO_PortSource << 0x04;
tmpreg |= GPIO_PinSource;
AFIO->EVCR = tmpreg;
}11、GPIO_EventOutputCmd
功能描述:使能或者失能事件输出
例:
GPIO_EventOutputConfig(GPIO_PortSourceGPIOC, GPIO_PinSource6);
GPIO_EventOutputCmd(ENABLE);函数解析
void GPIO_EventOutputCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));*(__IO uint32_t *) EVCR_EVOE_BB = (uint32_t)NewState;
}12、GPIO_PinRemapConfig
功能描述:改变指定管脚的映射
例:
GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/80681244
- @brief Configuration Mode enumeration
-
树莓派学习笔记——GPIO功能学习
2013-10-13 20:34:37树莓派现在越来越火,网上树莓派的资料也越来越多。树莓派源自英国,国外嵌入式开源领域具有良好的分享精神,树莓派各种集成库也层出不穷,下面推荐几个。 -
【STM32】GPIO工作原理(八种工作方式超详细分析,附电路图)
2018-04-10 10:20:05《STM32中文参考手册V10》-第8章通用和复用功能IO(GPIO和AFIO ) 芯片数据手册(datasheet) STM32的GPIO介绍 STM32引脚说明 GPIO是通用输入/输出端口的简称,是STM32可控制的引脚。GPIO的引脚与外部硬件... -
树莓派GPIO控制
2018-07-15 12:21:35树莓派GPIO控制 陈拓chentuo@ms.xab.ac.cn 2018.06.09/2018.06.10 0. 概述 本文介绍树莓派 Zero W的GPIO控制,并用LED看效果。也适宜于树莓派3B+。 0.1 树莓派GPIO编号方式 功能物理引脚 从左到右,从上到下:... -
GPIO介绍
2018-08-09 11:52:58GPIO的一些函数说明:...库函数GPIO中定义GPIO引脚名称,传输速率,引脚模式设置相应的结构体 @brief This file contains all the functions prototypes for the GPIO * firmwa... -
STM32 GPIO之 GPIO_Init() 函数
2015-12-06 21:39:39今天,我们来分析一下GPIO_Init() 函数的实现,看看ST的工程师是如何实现初始化端口的(不对地方,请大家多多指正)。每个GPIO端口有16个Pin, 每个端口的配置 有两个寄存器,高位和低位寄存器配置。 来看看,两个... -
树莓派GPIO RPi.GPIO
2016-04-03 08:50:54树莓派 raspberry pi GPIO python树莓派 raspberry pi GPIO python RPiGPIO模块基本使用 导入模块 引脚编号方式 设置一个通道 输入 输出 设置多个通道的输出 清空 GPIO 输入 上拉或者下拉电阻 测试输入轮询 中断与... -
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) 理解
2019-09-25 02:13:08void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) 功能描述:根据GPIO_InitStruct中指定的参数初始化外设GPIOx寄存器 输入参数1:GPIOx:x可以是A,B,C,D或者E,选择GPIO外设 输入参数... -
原理图初识之GPIO
2015-12-02 22:57:35GPIO -
LinuxGPIO操作和MTK平台GPIO
2020-04-25 13:03:26GPIO口配置是一个历史性的问题,不管我们使用什么MCU,单片机也好,ARM也好,都离不开驱动GPIO口。Linux下有一个宏,GPIO_GPIO_SYSFS,打开这个宏后,编译烧录到设... -
GPIO_ReadOutputDataBit及GPIO_ReadInputDataBit
2019-09-28 03:43:29GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)读的是GPIOx_IDR,读的是当IO口设置为输入状态时候的IO口值 GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)读的是GPIOx_ODR,读... -
STM32 (3) GPIO口功能讲解 GPIO 口输入输出 寄存器配置
2018-08-09 17:16:32讲解GPIO操作原理,使用各种型号的STM32 打开官方的《STM32中文参考手册》8.1 8.2小节 GPIO功能描述 我们今天重点要分析的是下图 上图是100脚的STM32单片机 1. GPIO是包含引脚的 2. 如何找GPIO功能: 看... -
GPIO设置
2020-02-03 17:46:28STM32F4学习随笔-IO口如何定义 1.第一步使能相应IO的时钟 void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState) 函数参数设置: RCC_AHB1Periph—为具体哪...void GPIO_Init(GPIO_T... -
Linux 内核设备驱动之GPIO驱动之GPIO GPIO描述符到GPIO号
2017-03-10 09:27:08* Convert a GPIO descriptor to the integer namespace. * This should disappear in the future but is needed since we still * use GPIO numbers for error messages and sysfs nodes */ int desc_ -
GPIO库函数
2018-08-01 20:27:061.void GPIO_DeInit(GPIO_TypeDef* GPIOx) 功能:将GPIOx外设寄存器初始化为默认值 注释:判断GPIOx具体为哪个端口,再通过操作RCC_APB2RSTR(APB2外设复位寄存器)对其寄存器进行复位 例如:GPIO_DeInit(GPIOA);... -
gpio总结
2016-07-06 16:53:44gpio 高通 -
GPIO简介
2016-12-01 15:21:30目录 [隐藏] 1 简介2 使用 2.1 输入输出2.2 复用 ...GPIO, 全称 General-Purpose Input/Output(通用输入输出),...RK3288 有 9 组 GPIO bank: GPIO0,GPIO1, ..., GPIO8。每组又以 A0~A7, B0~B7, C0~C7 -
Raspberry PI上操作GPIO(GPIO编程,远程控制GPIO)
2017-08-08 16:47:51一 Raspberry PI的GPIO 1. 什么是GPIO 2. Raspberry上的GPIO介绍 二Raspberry PI上编程操作GPIO 1. Python操作 (1) 安装环境 a.下载控制GPIO的python库:... -
GPIO_Mode--GPIO配置
2019-04-23 11:04:58【注:学习STM32总结做的笔记,大神勿喷。有不足之处还望不吝赐教。 -----本篇由转载而来,有侵权请联系作者,谢谢。】 ... 一、GPIO配置 (1)GPIO_Mode_AIN 模拟输入 (2)GPIO_Mode_IN_FLOATING ...(3)GPIO_Mod... -
Linux 内核设备驱动之GPIO驱动之GPIO 获取GPIO描述符
2017-03-10 09:26:29/** * Convert a GPIO number to its descriptor ...struct gpio_desc *gpio_to_desc(unsigned gpio) { struct gpio_device *gdev; unsigned long flags; spin_lock_irqsave(&gpio_lock, flags); list_for
-
【数据分析-随到随学】数据可视化
-
【数据分析-随到随学】SPSS调查问卷统计分析
-
开启MySQL binlog日志
-
PHP 字符串排序
-
【数据分析-随到随学】Mysql数据库
-
目标检测(Object Detection)
-
JavaScript基本语法
-
Laya 2.0 开发3D小游戏 入门教学
-
2021年高压电工考试内容及高压电工免费试题
-
转行做IT-第6章 IDEA、方法
-
【2021】UI自动化测试框架(Selenium3)
-
排序算法
-
nginx-http-flv.zip
-
CF补题计划
-
MariaDB [Warning] Could not increase number of max_open_files to more than 1024
-
flutter技术入门与实战!Android架构组件Room功能详解,内含福利
-
产品设计与研发 国产数据库在金融行业的应用创新和挑战应对 PDF分享版
-
LVM扩展分区教程
-
美图M6维修原理图PCB位置图(PDF格式)
-
【数据分析-随到随学】数据分析建模和预测