用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量今天我们将使用几个基本的电子“构建模块”,移位寄存器。这些方便的设备可用于各种用途,如数据转换、缓冲和存储,但今天我们将看到它们也可用于扩展 Arduino 数字 I/O 端口的数量。本文原创: 加拿大DroneBotWorkshop.

大家好,欢迎来到IT知识分享网。

今天我们将使用几个基本的电子“构建模块”,移位寄存器。这些方便的设备可用于各种用途,如数据转换、缓冲和存储,但今天我们将看到它们也可用于扩展 Arduino 数字 I/O 端口的数量。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

本文原创: 加拿大DroneBotWorkshop.com 翻译整理:DIY百事

通过学习使用移位寄存器,您将为设计师的工具包添加另一个方便的工具。

目录

1简介
1.1扩展您的 Arduino

2 移位寄存器
2.1移位寄存器的类型
2.1.1串行输入-并行输出
2.1.2并行输入-串行输出
2.1.3并行输入-并行输出 & 串行输入-串行输出
2.2移位寄存器的工作原理
2.3级联移位寄存器

3 74HC575 & 74HC165 移位寄存器
3.1 74HC595——8位串行输入——并行输出
3.2 74HC165——8位并行输入——串行输出

4. 74HC595 的额外输出端口
4.1 Arduino & 74HC595 连接
4.2 Arduino shiftOut() 函数
4.3 Arduino & 74HC595 草图

5. 驱动 7 段显示器
5.1 7 段 LED 显示
5.2 74HC595 7 段显示器连接
5.3 74HC595 7段显示示意图

6. 74HC165 的额外输入端口
6.1 Arduino shiftIn() 函数
6.2 Arduino & 74HC165 连接
6.3 Arduino & 74HC165 代码

7. 74HC595 和 74HC165 一起使用
7.1 74HC595 和 74HC165 连接
7.2 74HC595 和 74HC165 代码 1
7.3 74HC595 和 74HC165 代码 2 – 令人兴奋!

8. 结论

———————————————————————————————————

扩展您的 Arduino

Arduino 已经有许多数字 I/O 端口,事实上,Arduino Mega 250 拥有 54 个数字 I/O 引脚和另外 16 个可以兼作数字 I/O 引脚的模拟输入。因此,对于 70 个潜在的 I/O 引脚,您通常不需要更多。但有时你确实需要更多。

以熟悉的“LED Cube”为例。一个 4x4x4 尺寸的立方体需要 64 个 LED,如果你“借用”几个模拟引脚,这在 Arduino Mega 2560 的能力范围内。但是你快到极限了。

如果你想扩展到一个 5x5x5 的立方体,那么你就不走运了,为此你需要 125 个 LED,而且你不能用一个 Arduino 单独控制它们。

即使是使用标准(即不可寻址)RGB LED 的 4x4x4 立方体也会超过限制。

有很多方法可以解决这些问题,包括在矩阵中运行 LED 或使用移位寄存器。移位寄存器将允许您仅使用几个 Arduino I/O 引脚来寻址大量 LED。

有时,您有很多传感器、显示器或其他 I/O 设备,无法为 LED 或开关留出大量引脚,但您需要一个多 LED 显示器或一个小键盘。移位寄存器可以再次派上用场。

让我们来看看这些设备的使用。

移位寄存器

移位寄存器是用于二进制数据的转换、存储或传输的时序逻辑电路。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

这些设备用于在串行和并行数据之间进行转换。它们可用于数据通信电路以及存储器和缓冲电路。许多复杂的电子电路,例如微处理器和微控制器,在内部使用移位寄存器。

移位寄存器的类型

移位寄存器处理其输入和输出上的串行和并行数据,并且它们可以在这些格式之间进行转换。

有四种基本类型的移位寄存器:

串行输入-并行输出

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

并行输入 – 串行输出

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

并行输入 – 串行输出 (PISO) 移位寄存器将并行数据转换为串行数据。它用于通信并将多个输入端口转换为串行数据。

并行输入 – 并行输出 & 串行输入 – 串行输出

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

你可能会觉得这两个很奇怪。为什么需要一个移位寄存器,以与输入的格式相同的格式输出数据?

答案是这可以用作缓冲区,以在特定数量的时钟周期内保存数据。我们今天使用的移位寄存器都使用类似的缓冲器来保存他们输入和输出上的数据,因此在寄存器移位时它不会改变。

移位寄存器的工作原理

内部移位寄存器由许多基本逻辑门组成,其中许多被安排为“触发器”。

如果您不熟悉触发器,它是一种基本的电子电路,可以用来保存来自其输入的数据值。它是一个基本的构建块,无处不在,包括在许多形式的存储器电路中。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

串行输入-并行输出或 SIPO 寄存器使用一系列触发器,并行输出上的每个位对应一个触发器。此处的插图显示的是 4 位设备。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

当串行数据的第一位被计时,它存储在触发器中并出现在其输出上。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

下一位数据将原始位推送到下一个触发器。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

随着串行数据的输入,该过程继续进行。请注意,触发器仅在输入时更新输入值。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

最后,当并行输出中的所有数据都被计时时,就可以读取了。在大多数移位寄存器中,一个额外的缓冲区保存并行数据,并且在所有数据输入时钟之前不会更改它。

PISO 或并行输入 – 串行输出移位寄存器的构造如下

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

该图的“MUX”部分实际上由许多分立的逻辑门组成,它们用于在正确的时间将数据馈入相关的触发器。

这很重要,因为 PISO 移位寄存器需要单独计时并行数据的每一位。这意味着并行输入上的数据在读取时不能更改,同样,大多数实际设计采用缓冲区来保存并行数据。

级联移位寄存器

移位寄存器按其处理的位数进行分类,前面插图中显示的那些是 4 位寄存器,而我们今天将使用的两个移位寄存器都是 8 位设备。

如果您需要增加可以使用移位寄存器处理的并行数据量,您可以将其与另一个移位寄存器级联。所以两个 8 位移位寄存器可以支持 16 位,再加一个支持 24 位,等等。

您不需要额外连接到微控制器来级联移位寄存器,因此这是驱动大量 LED 或读取大量开关而不使用大量端口的好方法。

74HC575 & 74HC165 移位寄存器

今天我们将使用两个非常常见且容易获得的移位寄存器,即 74HC595 SIPO 和 74HC165 PISO。让我们仔细看看这些芯片。

74HC595——8位串行输入——并行输出

该74HC575是一个8级串行移位寄存器,它也具有一个内部存储寄存器。存储寄存器缓冲输出数据并且可以独立于移位寄存器计时。这可以防止数据在加载时发生变化。

74HC595 具有“三态”输出。这意味着并行数据输出上的引脚可以处于三种不同的状态。

OFF 状态是高阻态,有效断开芯片的输出。这种技术允许多个三态芯片驱动同一条总线,在任何给定时间只有其中一个处于活动状态。

DIP 封装中 74HC575 的引脚排列如下所示:

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

串行数据在 DS 引脚(引脚 14)上输入。您可以使用 Q7′ 引脚来级联这些设备,以增加您可以控制的并行输出数量。

输出使能(引脚 13)控制三态总线,如果它为低电平,则输出总线被使能。

74HC165 – 8 位并行输入 – 串行输出

该74HC165是具有串行输出的8位并行负载移位寄存器。它具有互补输出,其中一个可以连接到另一个 74HC165 以将它们级联。

该器件用于并行到串行数据转换,具有以下引脚排列:

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

与 74HC595 一样,这是一种非常常见的集成电路,您几乎可以从任何电子供应商处获得它。

74HC595 的额外输出端口

我们将从 74HC595 SIPO(串行输入-并行输出)移位寄存器开始我们的实验。

74HC595 允许我们扩展 Arduino 上的数字 I/O 端口的数量。在这些实验中,我们将使用它来驱动一些 LED,我们将使用 Arduino 控制这些 LED。

Arduino & 74HC595 连接

以下是我们将 74HC595 连接到 Arduino 和八个 LED 的方法。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

请注意在电源两端添加了一个去耦电容器,当使用 74HC595 等 TTL 芯片时,这是一个好主意。我使用了一个 100uf 的电容器,但 10uf 以上的任何值都可以正常工作。确保您观察电容器的极性。

在我的面包板上,我用一个 8×2220 欧姆的电阻阵列替换了八个降压电阻。当您需要大量相同的电阻器时,这是一个方便的组件。当然,如果您没有阵列,您可以使用分立电阻器。

这里有很多电线,所以请仔细检查您的接线。您可以先连接 LED 降压电阻器组合,然后向电阻器施加 5 伏电压,如果接线正确,您将点亮 LED。对所有八个电阻-LED 对重复测试。在连接 74HC595 和 Arduino 之前执行此操作。

一旦全部连接好,您就可以继续前进并编写一些代码以使其全部工作。

Arduino shiftOut() 函数

有几种方法可以使用 Arduino 与移位寄存器“对话”。一种方法是使用 SPI 总线,它允许您利用现有库来简化代码编写。

另一种方法是使用 Arduino 上的任何标准 I/O 引脚来创建时钟并交换串行数据。这是我们将用于处理 74HC595 移位寄存器的方法。

Arduino 提供了一个shiftOut()函数来简化串行连接上的数据移动。它可以获取一个字节值并以串行格式与另一个引脚上的时钟脉冲同步输出。可以选择两个方向输出数据。

  • MSB First– 最高位在前。所以二进制数 将以“101”开始,或者从左到右,一次输出一位。
  • LSB First – 最低有效位在前。在这种情况下,二进制数 将以“010”开始,或从右到左,一次输出一位。

我们将在我们的代码中使用这个功能。

Arduino 和 74HC595 代码

我们的代码非常简单。该SHIFTOUT函数能将我们的数据发送到移位寄存器和创建时钟信号。

/*   74HC595 Shift Register Demonstration 1   74hc595-demo.ino   Count in Binary and display on 8 LEDs     Modified from "Hello World" example by Carlyn Maw,Tom Igoe and David A. Mellis     DroneBot Workshop 2020   https://dronebotworkshop.com */   // Define Connections to 74HC595   // ST_CP pin 12 const int latchPin = 10; // SH_CP pin 11 const int clockPin = 11; // DS pin 14 const int dataPin = 12;   void setup () {   // Setup pins as Outputs   pinMode(latchPin, OUTPUT);   pinMode(clockPin, OUTPUT);   pinMode(dataPin, OUTPUT); }   void loop() {   // Count from 0 to 255 and display in binary     for (int numberToDisplay = 0; numberToDisplay < 256; numberToDisplay++) {       // ST_CP LOW to keep LEDs from changing while reading serial data     digitalWrite(latchPin, LOW);       // Shift out the bits     shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay);       // ST_CP HIGH change LEDs     digitalWrite(latchPin, HIGH);       delay(500);   } }

我们首先为连接到 74HC595 的引脚分配变量名称。然后将所有这些引脚设置为输出。然后我们进入循环。

我们使用 for-next 循环从 0 到 255 计数,递增 1。在每次增量时,我们将计数器值写入移位寄存器。锁存引脚用于在我们准备好之前保存数据,以便在加载移位寄存器时显示不会闪烁。

半秒延迟后,下一个数字被加载。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

结果是 LED 显示从 0 到 255 的二进制计数。

您可以试验代码并操纵一些值并观察对 LED 的影响。尝试将shiftOut 语句中的MSBFIRST参数更改为LSBFIRST,看看会发生什么。

这是理解基本移位寄存器操作的简单方法。

驱动 7 段显示器

74HC575 的另一个用途是驱动 7 段 LED 显示屏。您可以使用它来显示连接到一台显示器的数量,或者您可以级联多个 74HC595 来驱动多台显示器。

7 段 LED 显示屏

典型的 7 段 LED 显示布局如下所示:

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

请注意,“7 段”显示器中实际上有八个 LED 元件,第八个 LED 用作小数点。在某些显示中,这可以用冒号代替。

LED 显示屏有两种配置:

  • 共阳极– 所有 LED 都使用共阳极(正极)连接。
  • 共阴极– 所有 LED 都与一个共阴极(负极)连接相连。

两种显示类型都使用相同的引脚排列,因此了解您的类型非常重要。一个很好的判断方法(除了参考显示器部件号)是在“二极管测试”功能上使用万用表。当以正确的极性连接时,它可用于点亮 LED 元件。

共阴极显示器更常见,是我们将用于实验的类型。

74HC595 7 段显示器连接

由于共阴极 7 段 LED 显示屏实际上只是将八个 LED 连接到一个公共阴极(负极)端子,因此与我们在第一个实验中使用的八个 LED 没有什么不同。所以我们可以使用完全相同的电路来接线。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

使用连接图中的图表将显示引脚连接到降压电阻。COM 引脚(公共阴极)连接到 Arduino 的地。请注意,显示器将有两个 COM 引脚,您只需连接一个。

完成所有连接后,您可以通过运行上一个代码来测试它,该代码应该测试所有 LED 段,包括小数点。

但要真正显示连贯的东西,我们需要不同的代码。

74HC595 7段显示代码

这是我们将用来测试我们的 7 段显示器的代码。

/*   74HC595 Shift Register with 7-segment LED display   74hc595-7segdisplay.ino   Count in hex from 0-F and display on 7-segment Common Cathode LED display     DroneBot Workshop 2020   https://dronebotworkshop.com */   // Define Connections to 74HC595   // ST_CP pin 12 const int latchPin = 10; // SH_CP pin 11 const int clockPin = 11; // DS pin 14 const int dataPin = 12;   // Patterns for characters 0,1,2,3,4,5,6,7,8,9,A,b,C,d,E,F int datArray[16] = {B, B0, B, B, B0, B, B, B, B, B, B, B00, B, B0, B, B};   void setup () {   // Setup pins as Outputs   pinMode(latchPin, OUTPUT);   pinMode(clockPin, OUTPUT);   pinMode(dataPin, OUTPUT); } void loop() {   // Count from 0 to 15   for (int num = 0; num < 16; num++)   {     // ST_CP LOW to keep LEDs from changing while reading serial data     digitalWrite(latchPin, LOW);       // Shift out the bits     shiftOut(dataPin, clockPin, MSBFIRST, datArray[num]);       // ST_CP HIGH change LEDs     digitalWrite(latchPin, HIGH);       delay(1000);   } }

此代码与前一个代码有许多相似之处,当您认为它在同一件事上做得很好时,这并不奇怪。

我们通过定义与 74HC595 的连接重新开始。

然后我们创建一个包含 16 个元素的数组,每个元素代表要在 7 段 LED 上显示的字符模式。

这些元素以二进制形式编写,因此很容易理解它们的工作原理。在二进制字节中,每一位代表一个 LED 段。从 MSB 到 LSB(从左到右),它们代表显示屏中的以下段:

a – b – c – d – e – f – g – DP

当该位设置为“1”时,LED 各段点亮,“0”表示熄灭。

数组是有序的,所以元素 0 是“0”的字符。元素1是“1”等的字符。它是十六进制的,所以元素15是“F”。

查看数组元素,您将看到排列。

再次在设置中,我们将连接设置为输出,然后进入循环。

我们再次使用计数器,只是这次 介于 0 和 15 之间。我们将在 LED 显示屏上以十六进制格式显示这些值。

我们一次遍历数组一个元素,使用shiftOut将数组中的数据发送到移位寄存器。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

加载代码并观察显示。如果一切都正确连接,您会看到它从 0 到 F 计数,然后重复。

74HC165 的额外输入端口

现在我们已经了解了如何使用移位寄存器添加输出端口,现在是时候做相反的事情并添加一些输入了。对于这项工作,我们将使用 74HC165。

我们将使用 74HC165 移位寄存器和八个轻触式按钮开关。移位寄存器将从开关中获取 8 个输入,并将它们作为串行数据发送到 Arduino。

Arduino shiftIn() 函数

Arduino 再次具有用于接收串行数据的专用功能。

所述SHIFTIN()函数中的一个字节在一个时间移位串行数据。可以设置为先取 MSB 或 LSB。它通常与 74HC165 或CD4021BE等移位寄存器一起使用。

与其表亲shiftOut函数一样,shiftIn函数也提供时钟信号来同步数据传输。

Arduino & 74HC165 连接

74HC165 的输入需要拉低以防止错误读数,因此除了我们的八个按钮开关之外,我们还需要八个下拉电阻。我使用了 10k 电阻,但从 4.7k 到 27k 的任何值都可以正常工作。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

我再次使用了一个 100uf 的去耦电容,确保在连接时注意极性。

一旦你把它全部连接起来,我们就可以专注于我们将用来完成这项工作的代码。

Arduino & 74HC165 代码

我们的代码非常简单,因为它所做的只是读取按钮的状态并在串行监视器上显示结果。但这就是了解如何从按钮和 74HC165 获取数据所需要做的全部工作。

/*   74HC165 Shift Register Demonstration 1   74hc165-demo.ino   Read from 8 switches and display values on serial monitor     DroneBot Workshop 2020   https://dronebotworkshop.com */   // Define Connections to 74HC165   // PL pin 1 int load = 7; // CE pin 15 int clockEnablePin = 4; // Q7 pin 7 int dataIn = 5; // CP pin 2 int clockIn = 6;   void setup() {     // Setup Serial Monitor   Serial.begin(9600);     // Setup 74HC165 connections   pinMode(load, OUTPUT);   pinMode(clockEnablePin, OUTPUT);   pinMode(clockIn, OUTPUT);   pinMode(dataIn, INPUT); }   void loop() {     // Write pulse to load pin   digitalWrite(load, LOW);   delayMicroseconds(5);   digitalWrite(load, HIGH);   delayMicroseconds(5);     // Get data from 74HC165   digitalWrite(clockIn, HIGH);   digitalWrite(clockEnablePin, LOW);   byte incoming = shiftIn(dataIn, clockIn, LSBFIRST);   digitalWrite(clockEnablePin, HIGH);     // Print to serial monitor   Serial.print("Pin States:\r\n");   Serial.println(incoming, BIN);   delay(200); }

代码与我们之前的所有代码一样,定义了到 IC 的四个连接。

在设置中,我们初始化串行监视器,然后根据需要设置连接。

在循环中,我们首先向加载引脚写入一个脉冲,这将使其将并行输入中的数据加载到要处理的缓冲区中。

接下来,我们设置 74HC165 准备发送数据,然后使用shiftIn函数获取该数据,首先是 LSB(最低有效位)。我们通过将时钟引脚拉高来完成,这表示我们已经完成了。

最后,我们将结果打印到串行监视器。

加载代码,打开串行监视器并观察输出。马上你就会注意到一些事情。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

数据在输出端全部保持高电平,与板上接线相反。按下按钮将使其读数为低,即使这与实际发生的情况相反。

这是因为我们使用的是 74HC165 的取反输出。我们的数据是相反的。

我将在稍后的代码中向您展示如何以正确的方式将其转回来。继续阅读!

我们刚刚使用的示例有许多实际应用,其中一个明显的应用是作为小键盘(尽管有更好的方法来制作大键盘)。对于需要大量开关的项目来说,这是一种有用的设计技巧。

该电路的一个重要应用是将它与 DIP 开关或跳线一起使用,这些开关或跳线只是偶尔设置。您可以使用 74NC165 来减少读取 8 位 DIP 开关所需的连接数量,只需在设置程序中读取它,以便仅在设备通电或复位时读取。

74HC595 和 74HC165 一起使用

当然,将所有这些 LED 和开关连接起来而不采取额外的步骤将它们连接在一起将是一种浪费!所以让我们这样做。

74HC595 和 74HC165 连接

如果您像我一样在自己的无焊面包板上构建每个演示,那么将它们连接在一起非常简单。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

在其中一个演示中将 Arduino 与其面包板断开连接,哪个并不重要。将连接留在面包板上,以便您可以将它们重新连接到另一个 Arduino。您可以将 5 伏和接地连接连接到其他面包板电源轨。

完成后尝试在 Arduino 上运行之前的代码,一切都应该仍然有效。如果某些东西不起作用,请检查您的接线,当您加入项目时,某些东西可能已断开连接 – 这里有很多电线!

测试完所有内容后,就可以查看代码以同时使用 74HC165 和 74HC595。

74HC595 和 74HC165 代码 1

由于我们的演示本质上是将两个演示融合在一起,因此我们的代码完全相同。你会看到这个代码和之前的代码有很多相似之处,这并非偶然——其中一些是字面上的剪切和粘贴!

代码的目的是简单地使用 LED 来显示按钮的状态。作为演示,它运行良好。我保证在这之后我们会继续做一些更令人兴奋的事情!

/*   74HC595 & 74HC165 Shift Register Demonstration   74hc595-to-74ch165.ino   Input for 8 pushbuttons using 74HC165   Output to 0 LEDs using 74HC595     DroneBot Workshop 2020   https://dronebotworkshop.com */   // Define Connections to 74HC165   // PL pin 1 int load = 7; // CE pin 15 int clockEnablePin = 4; // Q7 pin 7 int dataIn = 5; // CP pin 2 int clockIn = 6;   // Define Connections to 74HC595   // ST_CP pin 12 const int latchPin = 10; // SH_CP pin 11 const int clockPin = 11; // DS pin 14 const int dataPin = 12;   void setup () {     // Setup Serial Monitor   Serial.begin(9600);     // 74HC165 pins   pinMode(load, OUTPUT);   pinMode(clockEnablePin, OUTPUT);   pinMode(clockIn, OUTPUT);   pinMode(dataIn, INPUT);     // 74HC595 pins   pinMode(latchPin, OUTPUT);   pinMode(clockPin, OUTPUT);   pinMode(dataPin, OUTPUT);   }     void loop() {     // Read Switches     // Write pulse to load pin   digitalWrite(load, LOW);   delayMicroseconds(5);   digitalWrite(load, HIGH);   delayMicroseconds(5);     // Get data from 74HC165   digitalWrite(clockIn, HIGH);   digitalWrite(clockEnablePin, LOW);   byte incoming = shiftIn(dataIn, clockIn, LSBFIRST);   digitalWrite(clockEnablePin, HIGH);     // Print to serial monitor   Serial.print("Pin States:\r\n");   Serial.println(incoming, BIN);       // Write to LEDs     // ST_CP LOW to keep LEDs from changing while reading serial data   digitalWrite(latchPin, LOW);     // Shift out the bits   shiftOut(dataPin, clockPin, LSBFIRST, ~incoming);     // ST_CP HIGH change LEDs   digitalWrite(latchPin, HIGH);     delay(500);   }

我们再次定义两个集成电路的引脚连接。在设置中,我们初始化串行监视器并根据需要设置连接。

循环以我们之前用于从 74HC165 读取按钮值的相同例程开始。我们再次将数据插入一个称为“传入”的 8 位字节中,并在串行监视器上显示其值。

接下来,我们使用之前使用的相同代码将数据写入 74HC595。但是我们对发送到移位寄存器上的数据进行了一项更改。

请记住,我们来自交换机的数据是反转的。如果我们将它发送到 74HC595 它将工作,但 LED 将全部亮起,除非我们按下了按钮。

为了反转数据,当我们在shiftOut函数中使用它时,我们在“传入”变量前面使用“~”符号。波浪号(波浪线)符号反转二进制数据,将每个零变成一,反之亦然。正是我们需要做的。

您还会注意到我们与早期 74HC595 代码不同的一件事是我们首先发送数据 LSB。这与我们从按钮接收它的方式相匹配。首先发送 MSB 会起作用,但 LED 显示会反转。

加载它并尝试一下。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

很有趣,不是吗?

好吧,它确实不是,但它确实展示了如何获取并行数据(开关输入),使用移位寄存器将其转换为串行,将其发送到 Arduino,将其发送回第二个移位寄存器并进行转换它再次回到并联状态(LED 输出)。这有点令人兴奋。

如果您不是很兴奋,请不要担心,现在我们有 8 个开关和 8 个 LED,我们可以做其他事情。

74HC595 和 74HC165 代码 2 – 令人兴奋!

为了给我们的演示增添一些料,让我们使用八个开关来选择 LED 灯闪烁模式。因为我们有八个开关,所以我们可以选择八个模式。

这是我们如何做到的代码:

/*   74HC595 & 74HC165 Shift Register Demonstration 2   74hc595-to-74ch165-pattern.ino   Input from 8 pushbuttons using 74HC165   Output to 8 LEDs using 74HC595      Select LED pattern using pushbuttons      DroneBot Workshop 2020   https://dronebotworkshop.com */ // Define Connections to 74HC165   // PL pin 1 int load = 7;   // CE pin 15       int clockEnablePin = 4;   // Q7 pin 7   int dataIn = 5;   // CP pin 2   int clockIn = 6;       // Define Connections to 74HC595   // ST_CP pin 12 const int latchPin = 10; // SH_CP pin 11 const int clockPin = 11; // DS pin 14 const int dataPin = 12;   // Define data array int datArray[8];   void setup () {    // Setup Serial Monitor Serial.begin(9600);    // 74HC165 pins pinMode(load, OUTPUT); pinMode(clockEnablePin, OUTPUT); pinMode(clockIn, OUTPUT); pinMode(dataIn, INPUT);   // 74HC595 pins pinMode(latchPin,OUTPUT); pinMode(clockPin,OUTPUT); pinMode(dataPin,OUTPUT);   }     void loop() {   // Read Switches         // Write pulse to load pin digitalWrite(load,LOW); delayMicroseconds(5); digitalWrite(load,HIGH); delayMicroseconds(5);   // Get data from 74HC165 digitalWrite(clockIn,HIGH); digitalWrite(clockEnablePin,LOW); byte incoming = shiftIn(dataIn, clockIn, LSBFIRST); digitalWrite(clockEnablePin,HIGH);   // Print to serial monitor Serial.print("Pin States:\r\n"); Serial.println(incoming, BIN);   // Setup array for LED pattern   switch (incoming) {     case B:        datArray[0] = B;     datArray[1] = B0;     datArray[2] = B;     datArray[3] = B;     datArray[4] = B;     datArray[5] = B;     datArray[6] = B;     datArray[7] = B0;        break;      case B:        datArray[0] = B00000001;     datArray[1] = B00000010;     datArray[2] = B00000100;     datArray[3] = B00001000;     datArray[4] = B00010000;     datArray[5] = B00;     datArray[6] = B0;     datArray[7] = B;        break;      case B:        datArray[0] = B;     datArray[1] = B0;     datArray[2] = B00;     datArray[3] = B00011000;     datArray[4] = B00000000;     datArray[5] = B00;     datArray[6] = B0;     datArray[7] = B;        break;     case B:        datArray[0] = B;     datArray[1] = B0;     datArray[2] = B;     datArray[3] = B0;     datArray[4] = B;     datArray[5] = B0;     datArray[6] = B;     datArray[7] = B0;        break;     case B:        datArray[0] = B;     datArray[1] = B00000001;     datArray[2] = B0;     datArray[3] = B00000010;     datArray[4] = B00;     datArray[5] = B00000100;     datArray[6] = B00010000;     datArray[7] = B00001000;        break;     case B:        datArray[0] = B;     datArray[1] = B0;     datArray[2] = B00;     datArray[3] = B00011000;     datArray[4] = B00001100;     datArray[5] = B00000110;     datArray[6] = B00000011;     datArray[7] = B;        break;   case B:        datArray[0] = B;     datArray[1] = B0;     datArray[2] = B00;     datArray[3] = B00011100;     datArray[4] = B00001110;     datArray[5] = B00000111;     datArray[6] = B;     datArray[7] = B;        break;   case B0:        datArray[0] = B;     datArray[1] = B0;     datArray[2] = B00;     datArray[3] = B00010001;     datArray[4] = B;     datArray[5] = B0;     datArray[6] = B00;     datArray[7] = B00010001;        break;        default:       break;     }   // Write to LEDs   // Count from 0 to 7   for(int num = 0; num < 8; num++)   {     // ST_CP LOW to keep LEDs from changing while reading serial data     digitalWrite(latchPin, LOW);          // Shift out the bits     shiftOut(dataPin,clockPin,MSBFIRST,datArray[num]);       // ST_CP HIGH change LEDs     digitalWrite(latchPin, HIGH);          delay(200);   }   }

正如你所看到的,我再次从之前的所有演示中借用了编码。事实上,这个代码只有一件事不同,那就是允许您选择 LED 模式的 switch-case 语句。

我们使用保存开关值的“传入”字节作为语句的开关。然后我们有八个情况,每个开关按下一个。如果您想允许同时按下两个按钮,您可能可以添加更多按钮,但八个对我来说已经足够了!

在每个情况下,我们用 LED 图案填充datArray阵列,以二进制编写,以便于查看。在每个字节中,“1”表示 LED 点亮,而“0”表示 LED 熄灭。

我在数组中使用了八个元素以使其更容易,但您可以将其增加到您喜欢的任何数字。只需更改数组定义和循环遍历数组元素的 for-next 循环中的数字即可。

我将模式更改之间的延迟设置为 200 毫秒,但您可以更改它。更好的是,尝试将延迟作为每个案例评估中的变量,这样您就可以使模式以不同的速度运行。

用移位寄存器来扩展 Arduino 数字 I/O 端口的数量

代码按照预想的方式运行,实际上观看起来很有趣。

您可以通过级联 74HC595 以添加更多 LED 来改进代码。您还可以通过将电位计添加到模拟输入之一并使用它来设置延迟时间来使速度可变。74HC595 上的使能输入可以用 PWM 驱动来改变 LED 强度,你可以用第二个电位器来控制。

您甚至可以添加一些 MOSFET 来驱动更大的 LED 并制作您自己的特效!

一个有很多潜力的简单演示。

结论

移位寄存器可能是基本构建块,如果您需要为项目添加额外的输入或输出,它们会非常有用,它们既便宜又易于使用。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/88710.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信