若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79758560
目录
前话
树莓派GPIO口硬件资源介绍
引脚分布和功能图
统计下硬件资源
模块化代码
关于wiringPi库
Demo1:GPIO口的输出
电路原理图
关键代码
模块代码
运行效果
Demo2:GPIO口的输入
电路原理图
关键代码
模块代码
运行效果
《树莓派开发笔记(一):入手树莓派3b,成功运行树莓派系统》
《树莓派开发笔记(二):树莓派Qt编译和宿主机Qt交叉编译》
《树莓派开发笔记(三):更便捷的开发,windows下和ubuntu下远程桌面至树莓派》
《树莓派开发笔记(四):更便捷的开发,qt远程运行(主机qt开发一键远程运行到目标机上) 》
《树莓派开发笔记(五):GPIO引脚介绍和GPIO的输入输出使用(驱动LED灯、检测按键输入)》
《树莓派开发笔记(六):GPIO口的UART的使用(串口通讯)》
《树莓派开发笔记(七):GPIO口的SPI使用(BME280三合一传感器:测量温度、湿度、气压、海拔高度) 》
《树莓派开发笔记(八):GPIO口的I2C使用(BME280三合一传感器:测量温度、湿度、气压、海拔高度) 》
《树莓派开发笔记(九):CSI口的摄像头拍照(同样适用USB摄像头)》
《树莓派开发笔记(十):Qt读取ADC模拟量电压(ADS1115读取电压模拟量)》
搭建好完整的Qt开发环境,对于开发Qt应用按照正常的开发即可,操作io口涉及到单片机硬件知识,本篇介绍树莓派类似于单片机的GPIO口使用(硬件+软件)。
我们模块化代码,写一个引脚输出的程序,以后需要类似直接修改引脚编号(或枚举)即可。
引入libwiringPi库。
在qt中控制GPIO主要是使用wiring,树莓派已自带,我们查询树莓派的物理引脚与wiringPi库的编号对应表,如下图:
如果我们要操作GPIO2,对应的物理引脚为3,如下图:
我们操作引脚的时候,引脚序号就为8(wPI),当前模式为输出,V代表的是当前的输入电压,1:3.3V,0:0V。
更详细的具体参照Demo1理解。
同时,我们在工程中要加入对应的头文件和库,如何调用wiringPi,请参照具体例程。
使用物理引脚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
#include
#include
#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 _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));
}
使用物理引脚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
#include
#include
#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 _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));
}
原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79758560