赞
踩
摘要:本文介绍如何使用PCF8574模块扩充GPIO
随着外接传感器的增多,有些小伙伴可能已经发现GPIO接口马上就要不够用了,已经没法接入更多的传感器了。接下来就来讲一下如何利用PCF8574芯片扩展GPIO接口。
PCF8574是一种常见的I/O扩展芯片,它采用I2C总线(串行通信协议)与微处理器进行通信,用于扩展更多的GPIO接口。
PCF8574是CMOS电路,具有8个并行准双向输入/输出引脚(即I/O口),可以根据需要配置为输入或输出模式。PCF8574每个I/O口可以提供高电平或低电平的逻辑状态,用于控制外部设备或接口。PCF8574的电流消耗很低,并且输出锁存,具有大电流驱动能力,可直接驱动LED。另外,它还带有中断接线可与MCU的中断引脚相连。这样,PCF8574可以通过发送中断信号,将I/O口的状态变化发送给MCU,而不需要经过总线通信。
在这里需要注意的是,使用PCF8574模块只能扩展输出高低电平的开关量的IO接口,扩展出的I/O是没有办法输出模拟量或者精确的PWM波的,不能用来进行电动机的速度控制。
下图就是今天要介绍的扩展GPIO接口要使用的PCF8574模块:
我所选用的是上边的蓝色PCF8574模块,这个模块的好处就是左右两侧都有对外的接口,一侧是针,一侧是母座。这样当需要使用多个PCF8574模块的时候,只要将这些PCF8574模块首尾插接到一起就可以了,更方便一些。那么,处理器芯片该怎么区分多个PCF8574芯片呢?答案是每个PCF8574模块都有一个唯一的地址,可以通过这个地址来进行区分。在前面介绍IIC通信协议的时候,就已经介绍过了,每个从机IIC设备,要有一个唯一的地址。这个地址是由7位2进制数组成,因此一个IIC总线,最多可以挂接127个从机IIC设备。
PCF8574模块是怎么确定自己的IIC设备地址的呢?可以看到,在PCF8574模块上,蓝色板子有三个黄色的跳线帽,而红色板子上有3个拨码开关,就是通过这3个跳线帽或者拨码开关来设置PCF8574模块的地址的。每个跳线帽或者拨码开关代表一位二进制数,那么3个就是3位二进制,对应的地址就是8个,所以,一定要记住,最多可以将8个PCF8574模块挂到同一个IIC总线上,因此就是利用一个IIC总线,使用PCF8574模块,最多可以扩展出64个GPIO来。
还有一点要知晓的是,这三个条线帽或者拨码开关设置后的PCF8574模块的地址并不是1~8,而是0x20~0x27。那么怎么区分哪个位置的跳线或者拨码对应哪个地址呢?我的经验是不用去记住这个东西,当条线或者拨码都在一边的时候,PCF8574的地址不是0x20就是0x27,然后两个地址都试一下就行了。
这里,还有一个更好的快速得到IIC从机地址的好办法,就是这里有一个小程序,这个程序会帮我们把所有的地址都尝试一边,看看哪些地址有应答,哪些地址就有对应的模块。这样就可以快速的找出模块的地址了。程序代码如下所示。
#include <Wire.h> void setup() { // put your setup code here, to run once: Wire.begin(); Serial.begin(115200); Serial.println("IIC设备扫描"); byte error, address; int nDevices; Serial.println("开始扫描......"); nDevices = 0; for(address = 1; address < 127; address++ ) { Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("发现IIC设备,地址是:0x"); if (address<16) { Serial.print("0"); } Serial.println(address,HEX); nDevices++; } else if (error==4) { Serial.print("未知错误,地址是:0x"); if (address<16) { Serial.print("0"); } Serial.println(address,HEX); } } if (nDevices == 0) { Serial.println("没有找到IIC从机设备!"); } else { Serial.println("扫描完成"); } delay(5000); Serial.print("共发现IIC设备数目:"); Serial.println(nDevices); } void loop() { // put your main code here, to run repeatedly: delay(1000); } |
这个程序的核心就是循环从地址1到127,给每个地址都调用beginTransmission()和endTransmission()方法,然后看有没有从机设备响应,有响应就说明该地址有从机设备存在。
接下来就做个实验,看看如何使用PCF8574进行I/O的输入和输出操作。对于输入功能的测试,就使用之前红外避障模块了,而输出则要使用一个简单的LED模块,通过LED的亮灭来判断PCF8574模块引脚输出电平的高低,LED模块如下所示。
这是一个三色LED模块,除了GND引脚外,当R、G、B引脚为高电平时,LED分别呈现红色、绿色和蓝色,也可以不同颜色同时点亮,那将呈现组合后的颜色。在这里,就使用一个引脚显示电平高低就可以了。
具体接线方法如下表所示:
PCF8574模块 | ESP32开发板 | 三色LED模块 | 红外避障模块 |
VCC | +5V | VCC | |
GND | GND | GND | GND |
SDA | P21 | ||
SCL | P22 | ||
P0 | R | ||
P1 | OUT |
下面来看一下PCF8574模块的基本组成结构。其扩展IO接口的引脚信息,位于模块的背面,如下图所示:
下面就来开发测试程序,测试程序要实现的功能很简单,就是用三色LED指示一下红外避障模块是否检测到了障碍物,当有障碍物的时候,三色LED点亮,否则熄灭。
接下来打开“Arduino IDE”开发工具,首先安装一下Adafruit PCF8574库,如下所示:
虽然,自己用前面介绍的Wire类来实现这个功能也不复杂,但借助前人的力量还是要更省力一些,在这里还是使用这个成熟的PCF8574库来帮助我们实现这个功能。使用PCF8574库通常有以下几个步骤:
#include <Adafruit_PCF8574.h>
Adafruit_PCF8574 pcf;
pcf.begin(0x20, &Wire)
实现后的代码如下所示:
#include <Adafruit_PCF8574.h> Adafruit_PCF8574 pcf; #define PCF_LED 0 // on the GPIO expander! #define PCF_INFRARED 1 // on the GPIO expander! void setup() { Serial.begin(115200); if (!pcf.begin(0x20, &Wire)) { Serial.println("Couldn't find PCF8574"); while (1); } pcf.pinMode(PCF_INFRARED, INPUT); pcf.pinMode(PCF_LED, OUTPUT); } void loop() { bool val = pcf.digitalRead(PCF_INFRARED); pcf.digitalWrite(PCF_LED, !val); delay(100); // we do nothing here! } |
这个程序就不过多的解释了,有一个需要提醒的就是读入红外避障模块的状态是低电平有障碍物,高电平没有障碍物,那么在输出控制LED的亮灭的时候,需要取反,否则显示的状态就是反着的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。