尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

74HC595驱动数码管:串入并出原理、动态扫描与Arduino实战

74HC595驱动数码管:串入并出原理、动态扫描与Arduino实战
📅 发布时间:2026/7/31 5:48:38

1. 项目概述:从“点灯”到“高效显示”的跨越

玩过单片机的朋友,对“点灯”这个入门仪式肯定不陌生。但当你需要控制8个、16个甚至更多的LED时,GPIO口很快就会被耗尽,更别提那些动辄需要7段、8段甚至带小数点的数码管了。直接驱动一个一位数码管就需要8个IO口(7段+小数点),如果是四位数码管,那就是32个IO口,这对大多数微控制器来说都是难以承受之重。这就是我们今天要拆解的核心模块——基于74HC595驱动的数码管显示模块——所要解决的根本问题。它不是一个简单的显示部件,而是一套经典的“串入并出”IO扩展解决方案在显示领域的完美实践。

简单来说,这个模块的核心价值在于,它允许你仅用微控制器的3个通用IO引脚(数据、时钟、锁存),就能控制理论上无限多个数码管段(实际受限于芯片级联数量和扫描刷新率)。无论是Arduino Uno、STM32还是ESP8266这类IO资源紧张但需要丰富显示的场景,它都是性价比极高的选择。我最初接触它是在一个需要显示温度和时间的项目上,当时手头只有一块Arduino Nano,既要接传感器,又要驱动一个四位数码管,74HC595模块成了我的救命稻草。它不仅解决了IO口危机,其稳定的串行通信和硬件锁存机制,也让程序编写变得清晰,避免了动态扫描时常见的“鬼影”问题。

接下来,我将结合自己多次使用的经验,从芯片原理、模块电路、驱动代码到调试技巧,为你完整梳理如何玩转这个“显示利器”。

2. 核心芯片74HC595深度解析:不止是移位寄存器

要用好这个模块,必须吃透74HC595这颗芯片。很多人把它简单理解为一个串行转并行的移位寄存器,这没错,但不够全面。实际上,它是由一个8位串入并出移位寄存器和一个8位三态输出锁存器共同构成的。这个“双缓冲”结构,正是其驱动数码管时显示稳定无闪烁的关键。

2.1 引脚功能与内部逻辑剖析

我们先把目光聚焦到芯片的16个引脚上,理解每个引脚的角色是正确接线和编程的基础。

  • 数据输入与移位核心(DS, SHCP, STCP):

    • DS(串行数据输入):你要发送的每一位数据(0或1)就是从这里一位一位地“喂”给芯片的。数据在时钟上升沿被采样。
    • SHCP(移位寄存器时钟输入):你可以把它想象成工厂流水线的节拍器。每给一个上升沿脉冲,流水线(移位寄存器)就向前移动一格,DS引脚上的当前数据就被移入寄存器的第一位(Q0‘),同时原来每一位的数据都向后顺移一位。
    • STCP(存储寄存器时钟输入/锁存信号):这是整个过程的“快门键”。当8位数据通过SHCP时钟一位位地移入移位寄存器后,它们只是暂存在那里,并没有输出到引脚上影响数码管。此时,你给STCP一个上升沿脉冲,就像按下快门,瞬间将移位寄存器里的8位数据,并行地、同时地锁存到输出锁存器中,并立即反映在输出引脚Q0-Q7上。这个“瞬间更新”的特性,彻底避免了在数据移位过程中,输出引脚上出现杂乱中间状态而导致数码管显示乱码或鬼影。
  • 输出与控制引脚(Q0-Q7, OE, MR):

    • Q0-Q7(并行输出):8位锁存后的数据从这里输出,高电平有效。通常直接连接到数码管各段的限流电阻上。
    • OE(输出使能):低电平有效。当OE为高电平时,所有输出Q0-Q7处于高阻态(相当于断开),数码管熄灭。这个引脚常用于全局亮度调节(通过PWM控制)或显示开关。很多模块为了简化,会直接将OE接地(始终使能)。
    • MR(主复位):低电平有效。当MR为低时,移位寄存器被清零(全部置0),但不影响已锁存到输出锁存器中的数据。通常接高电平(VCC)或通过一个上拉电阻处理。
  • 级联接口(Q7‘):

    • Q7‘(串行数据输出):这是实现多芯片级联的关键。当数据在移位寄存器中移动时,被移出最后一位(Q7)的数据会出现在Q7‘引脚上。你可以将第一片595的Q7‘连接到第二片595的DS引脚,如此类推。这样,发送16位数据时,先发送的8位会穿过第一片芯片进入第二片,后发送的8位留在第一片,最后用一个STCP信号同时更新所有芯片的输出。

2.2 关键参数与选型考量

74HC595是“HC”系列,工作电压通常在2V到6V,与3.3V和5V系统兼容性好。其最大时钟频率可达几十MHz,对于数码管扫描(通常几百Hz到几KHz)绰绰有余。需要关注的是输出电流能力:每个输出引脚最大可吸入或输出约35mA,但整个芯片的总电流有限制(约70mA)。这意味着,如果你直接驱动8个LED,每个LED电流控制在10mA以内是安全的。但在驱动数码管时,由于我们采用动态扫描,同一时刻通常只有一段或一位点亮,瞬间电流可能较大,但平均电流在安全范围内。稳妥起见,务必为每段数码管串联一个限流电阻(常用220Ω-1kΩ),模块上通常已经集成。

注意:市面上还有74HC164、74HC595D等型号。164没有输出锁存器,不适合直接驱动数码管,否则会有严重的闪烁。595D中的“D”通常指SOIC-16封装,功能与直插的595完全相同。

3. 数码管显示模块电路设计与连接要点

市面上常见的74HC595数码管模块,通常集成了1-4位数码管、1-2片595芯片以及必要的限流电阻和驱动三极管。理解其电路连接方式,是排查故障和进行二次开发的基础。

3.1 常见模块电路拓扑分析

最常见的是“2片595驱动4位共阴数码管”模块。其电路设计非常经典:

  1. 位选控制:第一片74HC595(我们称为U1)的8个输出口(Q0-Q7),通过8个NPN三极管(如8550)或专用驱动芯片(如ULN2003),分别控制4位数码管的公共阴极(COM端)。Q0-Q3分别控制第1-4位数码管的COM端,采用低电平有效驱动(因为三极管是低电平导通,将COM端拉低接地)。这样,U1就负责“选择”哪一位数码管被点亮。
  2. 段选控制:第二片74HC595(U2)的8个输出口,直接通过限流电阻连接到所有4位数码管对应的段(a, b, c, d, e, f, g, dp)引脚上。所有数码管的a段连在一起接到U2的Q0,b段连到Q1,以此类推。U2负责提供要显示的数字或字符的“笔画图案”。
  3. 芯片级联:U1的Q7‘引脚连接到U2的DS引脚。U1和U2的SHCP和STCP引脚分别并联,共同由单片机的两个IO口控制。U1的DS引脚则连接到单片机的数据IO口。
  4. 工作流程:当需要显示“1234”时,程序先通过DS和SHCP,将控制第4位(个位)的段选数据(数字4的编码)移入U2,再将控制第3位(十位)的段选数据(数字3的编码)移入U2并“挤”到U1,接着是2和1。发送完16位数据后,一个STCP上升沿同时更新U1和U2的输出。此时,U1输出中对应“个位”的引脚为低(导通),其他位为高(截止);U2输出数字“4”的段码。于是,只有个位数码管显示“4”。接下来,通过快速轮询(动态扫描),在下一个周期让U1选择十位,U2输出“3”,由于视觉暂留,人眼就看到稳定的“1234”。

3.2 与微控制器的硬件连接

连接极其简单,仅需3根信号线(如果使用OE进行调光,则需4根):

  • DS-> 连接单片机任意IO(如 Arduino D11)
  • SHCP-> 连接单片机任意IO(如 Arduino D12)
  • STCP-> 连接单片机任意IO(如 Arduino D8)
  • OE-> 如需调光,连接一个支持PWM的IO;否则接地。
  • VCC-> 接5V或3.3V(注意数码管和595的电压匹配)
  • GND-> 共地。

实操心得:在面包板上自己搭建电路时,SHCP和STCP信号线上最好接一个1kΩ左右的上拉电阻到VCC,可以增强抗干扰能力,特别是在导线较长或环境嘈杂时。模块化产品通常已做内部处理。

4. 软件驱动:从底层移位到高级库函数

驱动74HC595的本质就是模拟SPI时序。理解底层时序后,你可以选择直接操作IO,也可以使用现成的库来提高效率。

4.1 底层驱动时序模拟与代码实现

以Arduino平台为例,我们首先看最基础的shiftOut函数,它封装了移位时序:

// 引脚定义 const int dataPin = 11; // DS const int clockPin = 12; // SHCP const int latchPin = 8; // STCP void setup() { pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(latchPin, OUTPUT); } void write595(byte data1, byte data2) { // 先拉低锁存引脚,准备数据 digitalWrite(latchPin, LOW); // 先发送控制位选(U1)的数据,后发送控制段选(U2)的数据 // 因为数据是先进入U1,再被挤到U2 shiftOut(dataPin, clockPin, MSBFIRST, data1); // 发送给U1(位选) shiftOut(dataPin, clockPin, MSBFIRST, data2); // 发送给U2(段选) // 所有数据就位后,拉高锁存引脚,一次性更新输出 digitalWrite(latchPin, HIGH); }

对于驱动4位数码管,我们需要动态扫描。首先需要一个数组存储段码(共阴数码管0-9的编码):

byte digitSegCode[10] = { 0x3F, // 0 (0011 1111) 0x06, // 1 (0000 0110) 0x5B, // 2 (0101 1011) 0x4F, // 3 (0100 1111) 0x66, // 4 (0110 0110) 0x6D, // 5 (0110 1101) 0x7D, // 6 (0111 1101) 0x07, // 7 (0000 0111) 0x7F, // 8 (0111 1111) 0x6F // 9 (0110 1111) }; byte displayBuffer[4] = {1, 2, 3, 4}; // 要显示的数字 int currentDigit = 0; // 当前扫描的位 void scanDisplay() { // 关闭所有位选(对于共阴,位选输出高电平关闭) write595(0xFF, 0x00); // 先送全1(所有位关闭),段码任意 // 计算当前位的段码和位选码 byte segData = digitSegCode[displayBuffer[currentDigit]]; // 位选码:只有当前位对应的引脚为低电平,例如第0位(最左)对应Q0为低 byte bitSelect = ~(1 << currentDigit); // 取反,因为低电平有效 // 更新显示 write595(bitSelect, segData); // 移动到下一位 currentDigit = (currentDigit + 1) % 4; }

然后在loop()中定期调用scanDisplay(),间隔时间约1-5ms,利用人眼视觉暂留形成稳定显示。

4.2 使用高效库函数简化开发

对于更复杂的应用(如显示浮点数、负号、自定义字符),直接操作底层比较繁琐。我们可以封装一个简单的类,或者使用像SevSeg这样的优秀库。SevSeg库支持多种硬件配置(共阳/共阴,单芯片/多芯片),能自动处理扫描和字符编码。

#include <SevSeg.h> SevSeg sevseg; void setup() { byte numDigits = 4; // 定义连接引脚:数码管位选由一片595控制(我们假设用U1,连接arduino引脚8,9,10模拟?不,SevSeg需要直接位选IO) // 但对于纯595驱动的模块,我们需要告诉库我们使用“硬件”模式,并指定595的控制引脚。 // 更常见的用法是:如果模块的位选和段选都由595控制,则库可能不支持,需要自己修改底层。 // 这里展示一个更通用的自定义驱动思路: // 定义段选引脚(对应U2的输出顺序,假设a~dp对应Q0~Q7) byte segmentPins[] = { /*虚拟引脚,实际由595控制*/ }; // 定义位选引脚(对应U1的输出顺序,控制4位数码管) byte digitPins[] = { /*虚拟引脚,实际由595控制*/ }; // sevseg.begin(COMMON_CATHODE, numDigits, digitPins, segmentPins, false, false); // 上述方法不适用,因为我们没有直接连接位选和段选到MCU的IO。 // 因此,最佳实践是:基于shiftOut和定时器中断,自己编写稳定的扫描函数。 }

注意事项:使用shiftOut函数时,其时钟频率是固定的(在Arduino上大约几百KHz),对于大多数应用足够。但在高速MCU(如STM32)或需要极高刷新率时,建议直接使用寄存器操作或硬件SPI来模拟,可以大幅提升速度。例如,STM32可以将SHCP和DS配置为SPI的SCK和MOSI,利用硬件加速发送数据。

5. 动态扫描算法优化与显示效果提升

动态扫描是驱动多位数码管的核心技术,其算法优劣直接决定显示亮度、均匀度和稳定性。

5.1 扫描频率与占空比计算

扫描频率太低,显示会闪烁;太高,则可能增加MCU负担且亮度可能不足。通常扫描频率设置在60Hz以上(即每位数码管点亮周期小于16.7ms/位数)。对于4位数码管,每位点亮时间约3-4ms,整体扫描频率约250Hz,远高于人眼识别范围,非常稳定。

亮度控制:亮度由每个段点亮的电流和占空比决定。在段电流固定的情况下,占空比=每位点亮时间/扫描周期。例如,4位数码管,无亮度调节时,每位的理论占空比为1/4=25%。如果觉得太亮,可以通过两种方式调暗:

  1. 硬件调光:使用PWM控制595的OE引脚,整体调节所有段的电流。
  2. 软件调光:在扫描函数中,减少每位实际点亮的时间。例如,在4ms的扫描窗口内,只让段码输出2ms,其余时间关闭段码(或关闭位选)。软件调光更灵活,可以实现每位独立调光。

5.2 消除鬼影与残影的实战技巧

鬼影是指在切换显示内容时,不该亮的段微弱发光。残影是指当前位的内容隐约出现在其他位上。这两个问题是动态扫描的常见敌人。

  • 根本原因:段选或位选信号切换不同步,导致在极短时间内,错误的段选和位选组合被施加到数码管上。
  • 74HC595的天然优势:其STCP(锁存)信号确保了所有8位输出同时更新,从根本上避免了因段选数据逐位变化而产生的鬼影。
  • 常见残影排查:
    1. 位选关闭不彻底:在切换到下一位之前,必须确保当前位的位选信号已被完全关闭(对于共阴,拉高;对于共阳,拉低)。在我的代码示例中,write595(0xFF, 0x00);就是先关闭所有位选。顺序很重要:先送全关的位选码和任意段码(或全零段码),锁存;然后再送新的一位选码和段码,再锁存。确保中间状态不会点亮不该点的段。
    2. 三极管开关速度:如果模块使用三极管做位选驱动,要确保三极管有足够快的开关速度。使用像8550这样的通用开关三极管通常没问题,但如果电阻取值不当导致开关过慢,也可能产生残影。
    3. 电源滤波:在595的VCC和GND之间,靠近芯片引脚处,并联一个0.1uF的瓷片电容,可以滤除电源毛刺,使输出更干净。

实操心得:一个非常有效的调试方法是“单步扫描”。写一个程序,让数码管固定显示“8888”,然后以非常慢的速度(比如每秒一位)轮流扫描每一位。用眼睛仔细观察切换瞬间,或者用手机慢动作视频拍摄,很容易就能发现是哪一位关闭不彻底导致了残影。确认硬件连接无误后,问题几乎百分百出在软件扫描顺序和时序上。

6. 项目实战:制作一个4位计数器

让我们用一个完整的、可复现的项目来巩固所有知识:制作一个从0000累加到9999的4位计数器,并增加复位和暂停功能。

6.1 硬件清单与连接确认

  • Arduino Uno x1
  • 74HC595驱动4位共阴数码管模块 x1
  • 杜邦线若干
  • USB数据线

连接如下:

  • 模块 VCC -> Arduino 5V
  • 模块 GND -> Arduino GND
  • 模块 DS (DATA) -> Arduino D11
  • 模块 SHCP (CLK) -> Arduino D12
  • 模块 STCP (LATCH) -> Arduino D8
  • (模块OE如果引出,可接D9用于PWM调光,本例先接地)

6.2 完整代码实现与逐行解析

// 引脚定义 const int PIN_DATA = 11; const int PIN_CLOCK = 12; const int PIN_LATCH = 8; const int PIN_BUTTON_RESET = 2; // 复位按钮,接GND const int PIN_BUTTON_PAUSE = 3; // 暂停按钮,接GND // 共阴数码管段码 (a,b,c,d,e,f,g,dp) const byte SEGMENT_CODES[] = { 0x3F, // 0 0x06, // 1 0x5B, // 2 0x4F, // 3 0x66, // 4 0x6D, // 5 0x7D, // 6 0x07, // 7 0x7F, // 8 0x6F // 9 }; // 显示缓冲区和计数器 int displayNumber = 0; byte displayDigits[4] = {0}; bool isPaused = false; unsigned long lastCountTime = 0; const unsigned long COUNT_INTERVAL = 100; // 计数间隔100ms // 函数声明 void updateDisplayBuffer(int num); void writeToShiftRegisters(byte digitSelect, byte segmentData); void scanDisplay(); void setup() { // 初始化引脚 pinMode(PIN_DATA, OUTPUT); pinMode(PIN_CLOCK, OUTPUT); pinMode(PIN_LATCH, OUTPUT); pinMode(PIN_BUTTON_RESET, INPUT_PULLUP); // 启用内部上拉电阻 pinMode(PIN_BUTTON_PAUSE, INPUT_PULLUP); // 初始化显示 updateDisplayBuffer(displayNumber); lastCountTime = millis(); } void loop() { // 1. 处理按钮输入(带简单消抖) static unsigned long lastDebounceTime = 0; if (millis() - lastDebounceTime > 50) { if (digitalRead(PIN_BUTTON_RESET) == LOW) { displayNumber = 0; updateDisplayBuffer(displayNumber); isPaused = false; // 复位时自动解除暂停 lastDebounceTime = millis(); } if (digitalRead(PIN_BUTTON_PAUSE) == LOW) { isPaused = !isPaused; // 切换暂停状态 lastDebounceTime = millis(); } } // 2. 计数器逻辑 if (!isPaused) { unsigned long currentTime = millis(); if (currentTime - lastCountTime >= COUNT_INTERVAL) { lastCountTime = currentTime; displayNumber++; if (displayNumber > 9999) { displayNumber = 0; } updateDisplayBuffer(displayNumber); } } // 3. 动态扫描显示(必须持续调用) scanDisplay(); // 注意:这里没有使用delay,扫描是非阻塞的,保证了按钮响应的及时性。 } // 将整数分解为4个单独的数字存入缓冲区 void updateDisplayBuffer(int num) { num = constrain(num, 0, 9999); displayDigits[0] = num / 1000; // 千位 displayDigits[1] = (num / 100) % 10; // 百位 displayDigits[2] = (num / 10) % 10; // 十位 displayDigits[3] = num % 10; // 个位 } // 向两个595芯片写入数据(位选 + 段选) void writeToShiftRegisters(byte digitSelect, byte segmentData) { digitalWrite(PIN_LATCH, LOW); shiftOut(PIN_DATA, PIN_CLOCK, MSBFIRST, digitSelect); // 先送位选(控制哪一位亮) shiftOut(PIN_DATA, PIN_CLOCK, MSBFIRST, segmentData); // 再送段选(控制显示什么) digitalWrite(PIN_LATCH, HIGH); } // 动态扫描函数,使用静态变量维持状态 void scanDisplay() { static int currentScanDigit = 0; static unsigned long lastScanTime = 0; unsigned long now = micros(); // 使用微秒更精确 // 控制扫描间隔,这里设定每位显示2ms if (now - lastScanTime < 2000) { return; } lastScanTime = now; // 先关闭所有位选(共阴数码管,位选高电平关闭) // 送一个全1的位选码(0xFF)和任意段码(这里送0) writeToShiftRegisters(0xFF, 0x00); // 准备当前位的数据 byte segData = SEGMENT_CODES[displayDigits[currentScanDigit]]; // 计算位选码:只有当前位为低电平(导通),其他位为高(关闭) // 假设模块连接是Q0-Q3分别控制第1-4位数码管(从左到右) byte bitSelect = 0xFF; // 默认全关 bitSelect &= ~(1 << currentScanDigit); // 将当前位清零(置低) // 更新显示 writeToShiftRegisters(bitSelect, segData); // 移动到下一位 currentScanDigit++; if (currentScanDigit >= 4) { currentScanDigit = 0; } }

代码关键点解析:

  1. 非阻塞设计:loop()中的计数和scanDisplay()中的扫描都基于时间判断(millis()和micros()),没有使用delay(),保证了按钮响应实时性。
  2. 显示缓冲区:displayDigits数组存储了分解后的数字,扫描函数从中读取。这样做避免了在扫描中断中执行复杂的数学运算(如除法和取模)。
  3. 消抖处理:按钮检测加入了50ms的简单防抖逻辑,防止一次按下被误判多次。
  4. 扫描时序:scanDisplay()函数被loop()频繁调用,但内部通过时间判断(if (now - lastScanTime < 2000))控制每位显示2ms,实现了稳定的250Hz扫描频率(4位 * 2ms = 8ms周期,频率约125Hz,实际可调)。
  5. 关闭所有位的时机:在更新新一位显示前,先发送关闭所有位的命令,这是消除残影的关键步骤。

7. 故障排查与性能优化指南

即使按照教程操作,你也可能会遇到一些问题。这里汇总了常见故障及其解决方法。

7.1 常见问题速查表

现象可能原因排查步骤与解决方案
完全无显示1. 电源未接通或接反。
2. OE引脚被意外拉高。
3. STCP(锁存)信号始终为低。
1. 用万用表检查VCC和GND间电压(5V或3.3V)。
2. 检查OE引脚连接,如果悬空可能内部上拉为高,尝试将其接地。
3. 用示波器或逻辑分析仪检查STCP引脚是否有上升沿脉冲。程序里确认digitalWrite(PIN_LATCH, HIGH)被执行。
显示乱码/错位1. 段码表错误(共阴/共阳弄反)。
2. 数据发送顺序(MSB/LSB)错误。
3. 位选与段选对应关系错误。
1. 验证段码表。一个简单方法:让所有段点亮(送0xFF),看是不是显示“8.”,如果不是,可能是共阳管用了共阴码。
2.shiftOut的最后一个参数是MSBFIRST(高位在前)还是LSBFIRST(低位在前),需与硬件连接顺序匹配。通常a段接Q0,那么发送数据的最高位应对应a段。
3. 编写一个测试程序,依次单独点亮每一位的某一固定段(如a段),观察亮的位置是否符合预期。
显示暗淡1. 限流电阻过大。
2. 扫描频率过高,占空比过低。
3. 电源带载能力不足。
1. 检查模块上限流电阻值,常用330Ω-1kΩ。可尝试减小电阻(但需确保单段电流不超过595输出能力,通常10-20mA)。
2. 降低扫描频率,增加每位点亮时间。检查scanDisplay函数中的延时。
3. 尝试单独为模块供电,或检查MCU的5V输出电流是否足够(特别是驱动多位且全亮时)。
有鬼影/残影1. 位选关闭不彻底或顺序错误。
2. 三极管开关速度慢。
3. 程序扫描间隔不稳定。
1.这是最常见原因。确保在切换位选前,先发送关闭所有位的命令(见6.2节代码)。
2. 可尝试在位选三极管的基极电阻上并联一个几十pF的小电容到地,加速关断。
3. 避免在扫描函数中使用delay(),改用非阻塞的时间戳判断。
只有一位显示,或几位同时亮1. 位选数据发送错误。
2. 级联顺序错误。
3. 某一位的位选驱动电路(三极管)损坏。
1. 检查位选码计算逻辑。对于共阴,要点亮的那位应为0,其他为1。
2. 确认级联顺序:数据是先进入控制位选的595,再进入控制段选的595。发送数据时,先发送位选数据(对应级联中靠后的芯片)。
3. 用万用表测量位选三极管是否正常工作。

7.2 高级优化技巧

  1. 使用定时器中断进行扫描:对于主循环任务繁重的系统,将扫描显示放在定时器中断服务程序(ISR)中,可以保证显示刷新率绝对稳定,不受主程序阻塞影响。在Arduino上,可以使用TimerOne库。
  2. 利用硬件SPI加速:74HC595的时序与SPI协议高度相似。在支持硬件SPI的MCU(如STM32、ESP32、AVR的USART)上,可以将DS接MOSI,SHCP接SCK。这样只需用SPI发送函数传输数据,速度极快且不占用CPU时间。STCP仍需用普通IO控制。
  3. 实现小数点与自定义字符:段码表中的每个位对应一个段。dp是小数点。要显示小数点,只需在发送段码时,将最高位(对应dp段)置1。例如,显示“5.”,段码为0x6D | 0x80 = 0xED(假设dp是最高位)。自定义字符(如A, b, C, d, E, F等)需要自己定义段码。
  4. 多模块级联以驱动更多位数:原理相同,只需将第一个模块最后一颗595的Q7‘连接到第二个模块第一颗595的DS。发送数据时,先发送离STCP最远的模块的数据。例如,驱动8位数码管(4片595),需要发送32位数据,然后一个STCP信号同时更新所有输出。注意数据总量和刷新率,避免因数据过长导致扫描频率过低。

相关新闻

  • Unity RPG游戏开发:核心玩法系统设计与工程实践指南
  • AI多语言翻译工具:跨境电商说明书高效解决方案
  • 如何免费获得经典Garamond字体:EB Garamond12完整指南

最新新闻

  • 智慧校园的数字孪生实践:从教学到管理的全面赋能
  • 5分钟上手Vosk:Python离线语音识别从环境配置到实战应用
  • 广德市防水补漏_2026安徽东南部三省通衢城市漏水维修流程教程与五大正规团队推荐 - 雨婺虹房屋维修
  • Voronoi图核心性质剖析:从凸性、空圆到对偶性,掌握空间划分的算法基石
  • 酷安UWP桌面版终极指南:在Windows上畅享酷安社区的最佳体验
  • 基于Hadoop大数据的b站热门视频的数据分析与研究大数据分析系统(源码+lw+部署文档+讲解等)

日新闻

  • 7步掌握KMS智能激活工具:Windows和Office永久激活完整方案
  • 如何在Windows上运行iOS应用:ipasim跨平台模拟器终极指南
  • 2026年重庆工伤赔偿律师口碑推荐:洪家木律师用专业赢得信赖 - 本地品牌推荐

周新闻

  • 大连理工大学与东京大学联手打造的“主动型AI助手“
  • 170.2026年国家级科研瓶颈:超精密单点金刚石切削(SPDT)光学表面生成
  • SongBloom:革命性歌曲生成框架深度解析——如何通过交织自回归与扩散模型创作完整音乐

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号