一板网电子技术论坛

风筝
发表于: 2022-7-25 14:58:00 | 显示全部楼层

您是否曾经发现自己想要控制大量LED灯?或者需要更多的I/O引脚来同时控制按钮、传感器、伺服系统?好吧,您可以将几个传感器连接到Arduino引脚,但很快就会用完Arduino上的引脚。


解决方案是使用移位寄存器。移位寄存器(Shift Register)允许您扩展您可以从Arduino(或任何微控制器)使用的I/O引脚的数量。而74HC595移位寄存器是其中最著名的一个型号。


595基本上控制八个独立的输出引脚,只使用三个输入引脚。如果您需要超过8条额外的I/O线,您可以轻松地以菊花链方式连接任意数量的移位寄存器并创建大量I/O线。所有这些都是通过所谓的位移来完成的。如果您想了解有关位移的更多信息,可以查看Wikipedia的链接


何时使用移位寄存器?

移位寄存器通常用于节省微控制器上的引脚,因为每个微控制器都有有限数量的I/O引脚 (GPIO)。


如果您的项目需要控制16个独立的LED,通常需要Arduino的16个引脚。如果您没有16个I/O引脚可用,这时可以使用移位寄存器。通过串联两个移位寄存器,我们只需使用3个I/O引脚就可以完成控制16个LED的任务。不仅如此;您链接在一起的移位寄存器越多,您就可以节省更多的引脚。


使用移位寄存器的实例是“任天堂控制器”。任天堂娱乐系统的主控制器需要连续按下所有按钮,它使用移位寄存器来完成这项任务。

Nintendo-Entertainment-System-NES-Controller-FL.jpg


74HC595移位寄存器如何工作?

74HC595有两个寄存器(可以认为是“内存容器”),每个寄存器只有8位数据。第一个称为移位寄存器。移位寄存器位于IC电路的深处,安静地接受输入。


每当我们向595施加时钟脉冲时,都会发生两件事:

●    移位寄存器中的位向左移动一步。例如,位7接受之前位6中的值,位6获取位5的值等。

●    移位寄存器中的位0接受DATA引脚上的当前值。在脉冲的上升沿,如果数据引脚为高电平,则将1推入移位寄存器。否则为0。


在启用锁存器引脚时,移位寄存器的内容被复制到第二个寄存器,称为存储/锁存器寄存器。存储寄存器的每一位都连接到IC的输出引脚 QA-QH 之一,因此通常情况下,当存储寄存器中的值发生变化时,输出也会发生变化。


您可以通过下图更好地理解这一点。

74HC595-Shift-Register-Working.gif


74HC595移位寄存器引脚

595有多种厂商品牌和型号。在这里,我们将使用德州仪器的SN74HC595N。如果您使用不同厂家的型号,请仔细阅读其数据表并记下差异。


让我们来看看它的引脚排列。请注意,两个引脚的名称上有一条线;这意味着它们以“负逻辑”运行。

Pinout-74HC595-Shift-Register.jpg


GND 应连接到Arduino的地。

VCC 是74HC595移位寄存器的电源引脚,我们连接到Arduino上的5V引脚。

SER(Serial Input,串行输入)引脚用于一次将数据输入移位寄存器。

SRCLK(移位寄存器时钟)是移位寄存器的时钟。 595在上升沿由时钟驱动。这意味着为了将位移入移位寄存器,时钟必须为高电平。并且位在时钟的上升沿被传输。

RCLK(寄存器时钟/锁存器)是一个非常重要的引脚。当驱动为高电平时,移位寄存器的内容被复制到存储/锁存寄存器中;最终出现在输出中。因此,可以将锁存引脚视为在输出端查看我们的结果的过程中的最后一步。

SRCLR(移位寄存器清除)引脚允许我们一次复位整个移位寄存器,使其所有位为0。这是一个负逻辑引脚,因此要执行此复位;我们需要将SRCLR引脚设置为低电平。当不需要复位时,该引脚应为高电平。

OE(输出使能)也是负逻辑:当其上的电压为高时,输出引脚被禁用/设置为高阻抗状态并且不允许电流流动。当OE低电压时,输出引脚正常工作。

QA–QH(输出使能)是输出引脚,应连接到某种类型的输出,如LED、7段数码管等。

QH' 引脚输出移位寄存器的第7位。在那里,我们可以菊花链式连接595:如果您将此QH'连接到另一个595的SER引脚,并为两个IC提供相同的时钟信号,它们将像具有16个输出的单个IC一样工作。当然,这种技术并不仅限于两个IC - 如果你有足够的电源,你可以菊花链任意多的IC。


将74HC595移位寄存器连接到Arduino UNO开发板

现在我们对74HC595的工作原理有了基本的了解,我们可以开始将它连接到Arduino!


首先将移位寄存器放在面包板上,确保IC的每一侧都位于面包板的单独一侧。小U形槽口朝上,引脚从上到下在左侧向下1-8,从上到下在右侧向下16-9,如下图所示。


首先让我们将引脚16 (VCC) 和 10 (SRCLR) 连接到Arduino上的 5v 引脚,并将引脚 8 (GND) 和13 (OE) 连接到Arduino上的Gnd引脚。这应该使IC保持正常工作模式。


接下来,我们需要连接我们将控制移位寄存器的三个引脚:

●    移位寄存器的引脚 11 (SRCLK) 连接到Arduino上的引脚6

●    移位寄存器的引脚 12 (RCLK) 连接到Arduino上的引脚5

●    移位寄存器的引脚 14 (SER) 连接到Arduino上的引脚4


现在,我们只需将所有输出引脚连接到LED灯,确保在LED之前放置一个220Ω电阻以减少电流,并确保LED的阴极返回到地。


放置LED时,请确保它们按顺序连接,以便QA连接到第一个LED,而QH连接到最后一个LED,否则我们的代码不会以正确的顺序点亮LED!


完成后,您应该会看到类似于下图所示的内容。

Arduino-Wiring-Fritzing-Connections-with-74HC595-Shift-Register.jpg


Arduino代码

硬件准备好后,现在我们可以测试一些代码!将Arduino开发板插入计算机并尝试草图;

  1. int latchPin = 5;        // Latch pin of 74HC595 is connected to Digital pin 5
  2. int clockPin = 6;        // Clock pin of 74HC595 is connected to Digital pin 6
  3. int dataPin = 4;        // Data pin of 74HC595 is connected to Digital pin 4

  4. byte leds = 0;                // Variable to hold the pattern of which LEDs are currently turned on or off

  5. /*
  6. * setup() - this function runs once when you turn your Arduino on
  7. * We initialize the serial connection with the computer
  8. */
  9. void setup()
  10. {
  11.   // Set all the pins of 74HC595 as OUTPUT
  12.   pinMode(latchPin, OUTPUT);
  13.   pinMode(dataPin, OUTPUT);  
  14.   pinMode(clockPin, OUTPUT);
  15. }

  16. /*
  17. * loop() - this function runs over and over again
  18. */
  19. void loop()
  20. {
  21.   leds = 0;        // Initially turns all the LEDs off, by giving the variable 'leds' the value 0
  22.   updateShiftRegister();
  23.   delay(500);
  24.   for (int i = 0; i < 8; i++)        // Turn all the LEDs ON one by one.
  25.   {
  26.     bitSet(leds, i);                // Set the bit that controls that LED in the variable 'leds'
  27.     updateShiftRegister();
  28.     delay(500);
  29.   }
  30. }

  31. /*
  32. * updateShiftRegister() - This function sets the latchPin to low, then calls the Arduino function 'shiftOut' to shift out contents of variable 'leds' in the shift register before putting the 'latchPin' high again.
  33. */
  34. void updateShiftRegister()
  35. {
  36.    digitalWrite(latchPin, LOW);
  37.    shiftOut(dataPin, clockPin, LSBFIRST, leds);
  38.    digitalWrite(latchPin, HIGH);
  39. }
复制代码

将代码上传到Arduino后,您应该会看到如下输出:

74HC595-Shift-Register-Sketch-Output.gif


如果您想熄灭而不是点亮其中一个 LED,您可以在“leds”变量上调用类似的Arduino函数 bitClear()。这会将“leds”的特定位设置为0,然后您只需要调用 updateShiftRegister() 来更新实际的LED。


代码说明

我们要做的第一件事是定义3个控制引脚,即74HC595的锁存器、时钟和数据引脚,我们将分别连接到Arduino的数字引脚#5、#6和#4。

  1. int latchPin = 5;
  2. int clockPin = 6;
  3. int dataPin = 4;
复制代码

接下来,定义了一个名为“leds”的变量。这将用于保存当前熄灭或点亮LED灯的模式。 字节类型的数据使用八位表示数字。每个位都可以打开或关闭,因此非常适合跟踪我们的八个LED中的哪个是打开或关闭的。

  1. // Variable to hold the pattern of which LEDs are currently turned on or off
  2. byte leds = 0;
复制代码

setup()函数中,我们只需将这三个引脚初始化为数字输出。

  1. void setup()
  2. {
  3.   pinMode(latchPin, OUTPUT);
  4.   pinMode(dataPin, OUTPUT);  
  5.   pinMode(clockPin, OUTPUT);
  6. }
复制代码

loop()函数中,首先通过将变量“leds”的所有位设置为0来熄灭所有LED。然后调用名为updateShiftRegister() 的自定义函数,该函数将“leds”模式发送到移位寄存器,以便所有LED熄灭。稍后我们将讨论updateShiftRegister() 的工作方式。


程序暂停半秒,然后使用“for”循环和变量“i”开始从 0 计数到 7。每次,它使用Arduino函数bitSet()来设置变量“leds”中控制特定LED的位。然后它还调用 updateShiftRegister() 以便LED的状态根据变量“leds”中的内容而变化。


然后在“i”递增和下一个LED点亮之前有半秒的延迟。

  1. void loop()
  2. {
  3.   leds = 0;
  4.   updateShiftRegister();
  5.   delay(500);
  6.   for (int i = 0; i < 8; i++)
  7.   {
  8.     bitSet(leds, i);
  9.     updateShiftRegister();
  10.     delay(500);
  11.   }
  12. }
复制代码

函数updateShiftRegister() ,首先将锁存器引脚设置为低电平,然后调用Arduino函数shiftOut() ,然后再次将锁存器引脚设置为高电平。


值得庆幸的是,Arduino提供了一个专门用于移位寄存器的辅助函数shiftOut() ,它允许我们在一次调用中简单地移位。您可以在Arduino的官方网站上探索有关该库的更多信息


shiftOut() 函数有四个参数;前两个是分别用于数据和时钟的引脚。第三个参数指定要从数据的哪一端开始。我们将从最右边的位开始,它被称为“最低有效位”(LSB)。最后一个参数是要移入移位寄存器的实际数据,在本例中为“leds”。

  1. void updateShiftRegister()
  2. {
  3.    digitalWrite(latchPin, LOW);
  4.    shiftOut(dataPin, clockPin, LSBFIRST, leds);
  5.    digitalWrite(latchPin, HIGH);
  6. }
复制代码


跳转到指定楼层
风筝
发表于: 2022-7-25 15:07:32 | 显示全部楼层

使用PWM控制LED的亮度

这是另一个项目,作为移位寄存器的补充,基于相同的设置但略有不同,我们在其中操纵IC上的一个控制引脚,即OE - 通过这样做,我们可以控制输出LED的亮度!


我们已经了解到OE(输出使能)引脚用作开关。当此引脚设置为高电平时,输出引脚被禁用(它与负逻辑一起使用,记得吗?)。并且当OE是低电压时,输出引脚正常工作。


在我们之前的示例中,我们已将此引脚永久连接到地,从而始终启用输出。如果我们将此引脚连接到Arduino的任何数字引脚并编程为切换其状态,我们可以得到如下图所示的内容。

74HC595-Shift-Register-Output-Enable-Toggle-Output.gif


但是,我们可以不这样做,而是使用该引脚和analogWrite() 函数,使用PWM控制LED的亮度。因此,我们可以得到如下所示的结果。

74HC595-Shift-Register-Output-Enable-PWM-Output.gif


实际上,PWM信号的高电平部分仍会导致OE引脚暂时禁用所有IC输出。但是,这当然会比我们的眼睛直接感知的速度更快,但我们肯定会感觉到整体亮度的变化。


为此,您需要做的就是更改与74HC595引脚13的连接。因此,您无需将其连接到地,而是将其连接到Arduino的引脚3。

Arduino-PWM-Brightness-Control-Wiring-Fritzing-Connections-with-74HC595-Shift-Register.jpg


下面的草图将在所有LED点亮后逐渐将它们淡化回熄灭状态。

  1. int latchPin = 5;                // Latch pin of 74HC595 is connected to Digital pin 5
  2. int clockPin = 6;                // Clock pin of 74HC595 is connected to Digital pin 6
  3. int dataPin = 4;                // Data pin of 74HC595 is connected to Digital pin 4
  4. int outputEnablePin = 3;        // OE pin of 74HC595 is connected to PWM pin 3

  5. byte leds = 0;                // Variable to hold the pattern of which LEDs are currently turned on or off

  6. /*
  7. * setup() - this function runs once when you turn your Arduino on
  8. * We initialize the serial connection with the computer
  9. */
  10. void setup()
  11. {
  12.   // Set all the pins of 74HC595 as OUTPUT
  13.   pinMode(latchPin, OUTPUT);
  14.   pinMode(dataPin, OUTPUT);  
  15.   pinMode(clockPin, OUTPUT);
  16.   pinMode(outputEnablePin, OUTPUT);
  17. }

  18. /*
  19. * loop() - this function runs over and over again
  20. */
  21. void loop()
  22. {
  23.   setBrightness(255);
  24.   leds = 0;                // Initially turns all the LEDs off, by giving the variable 'leds' the value 0
  25.   updateShiftRegister();
  26.   delay(500);
  27.   for (int i = 0; i < 8; i++)        // Turn all the LEDs ON one by one.
  28.   {
  29.     bitSet(leds, i);                // Set the bit that controls that LED in the variable 'leds'
  30.     updateShiftRegister();
  31.     delay(500);
  32.   }
  33.   for (byte b = 255; b > 0; b--)        // Gradually fade all the LEDs back to off
  34.   {
  35.     setBrightness(b);
  36.     delay(50);
  37.   }
  38. }

  39. /*
  40. * updateShiftRegister() - This function sets the latchPin to low, then calls the Arduino function 'shiftOut' to shift out contents of variable 'leds' in the shift register before putting the 'latchPin' high again.
  41. */
  42. void updateShiftRegister()
  43. {
  44.    digitalWrite(latchPin, LOW);
  45.    shiftOut(dataPin, clockPin, LSBFIRST, leds);
  46.    digitalWrite(latchPin, HIGH);
  47. }

  48. /*
  49. * setBrightness() - Generates PWM signal and writes it to OE pin.
  50. */
  51. void setBrightness(byte brightness) // 0 to 255
  52. {
  53.   analogWrite(outputEnablePin, 255-brightness);
  54. }
复制代码

将代码上传到Arduino后,您应该会看到如下输出:

74HC595-Shift-Register-PWM-Brightness-Control-Sketch-Output.gif


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 671 | 回复: 1388



手机版|

GMT+8, 2022-8-14 03:38 , Processed in 0.036273 second(s), 7 queries , Gzip On, MemCache On. Powered by Discuz! X3.4

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表