当前位置:   article > 正文

一起玩儿物联网人工智能小车(ESP32)——42. 利用PCF8574芯片扩充你的GPIO_esp32 8574

esp32 8574

摘要:本文介绍如何使用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库通常有以下几个步骤:

  1. 引入头文件

#include <Adafruit_PCF8574.h>

  1. 实例化对象

Adafruit_PCF8574 pcf;

  1. 初始化IIC

pcf.begin(0x20, &Wire)

  1. 利用pinMode()函数,设置引脚的工作模式
  2. digitalRead()用来读取引脚的状态
  3. digitalWrite()用来控制引脚的输出状态

实现后的代码如下所示:

#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的亮灭的时候,需要取反,否则显示的状态就是反着的。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/190092
推荐阅读
相关标签
  

闽ICP备14008679号