基于Arduino的四路交通灯系统LED异常问题求助
四路交通灯移位寄存器异常排查与解决
问题描述
使用Arduino Uno R3 + 2个74HC595移位寄存器搭建四路交通灯系统(每路红黄绿3个LED,共12个),当前用默认序列测试代码,未接入红外传感器。测试中发现第二个移位寄存器控制的Road3、Road4存在以下异常:
- 默认状态下Road3黄灯亮起而非红灯
- Road3轮到通行时,红黄灯同时点亮,绿灯始终不亮;直至进入Road4阶段后,Road3绿灯才亮起
测试代码(原代码)
// Pin Definitions const int dataPin = 10; // DS const int clockPin = 8; // SH_CP const int latchPin = 9; // ST_CP // Sensors const int sensor1 = A0, sensor2 = A1, sensor3 = A2, sensor4 = A3; // LED States (12 LEDs controlled via 2 shift registers) byte road1 = 0b001; // Red: 1, Yellow: 0, Green: 0 byte road2 = 0b001; byte road3 = 0b001; byte road4 = 0b001; void setup() { // Setup Serial monitor Serial.begin(9600); // Shift register pins pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(latchPin, OUTPUT); // Sensor pins pinMode(sensor1, INPUT); pinMode(sensor2, INPUT); pinMode(sensor3, INPUT); pinMode(sensor4, INPUT); } void loop() { defaultSequence(); } void updateTraffic(int road) { // Set all roads to red road1 = 0b001; road2 = 0b001; road3 = 0b001; road4 = 0b001; // Update the road based on priority switch (road) { case 1: road1 = 0b100; break; // Green for Road 1 case 2: road2 = 0b100; break; // Green for Road 2 case 3: road3 = 0b100; break; // Green for Road 3 case 4: road4 = 0b100; break; // Green for Road 4 } writeShiftRegisters(); delay(10000); // Green light duration setYellow(road); //delay(1000); //setRed(road); } void setYellow(int road) { // Set the selected road to yellow switch (road) { case 1: road1 = 0b010; break; case 2: road2 = 0b010; break; case 3: road3 = 0b010; break; case 4: road4 = 0b010; break; } writeShiftRegisters(); delay(2000); // Yellow light duration } void setRed(int road) { // Set the selected road to red switch (road) { case 1: road1 = 0b001; break; case 2: road2 = 0b001; break; case 3: road3 = 0b001; break; case 4: road4 = 0b001; break; } writeShiftRegisters(); } void defaultSequence() { for (int i = 1; i <= 4; i++) { Serial.print("Road: "); Serial.println(i); updateTraffic(i); delay(10000); // Delay for default traffic } } void writeShiftRegisters() { // Combine all roads into a 16-bit data word unsigned int allRoads = (road4 << 9) | (road3 << 6) | (road2 << 3) | road1; Serial.print("allRoads (binary): "); for (int i = 15; i >= 0; i--) { Serial.print((allRoads >> i) & 1); } Serial.println(); // Send data to shift registers digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, MSBFIRST, highByte(allRoads)); // First register delay(10); shiftOut(dataPin, clockPin, MSBFIRST, lowByte(allRoads)); // Second register digitalWrite(latchPin, HIGH); }
问题根源分析
- 移位寄存器级联的位顺序不匹配:使用
MSBFIRST发送数据时,第一个发送的比特会最终落在第二个移位寄存器的最高位(Q7),但原代码的位拼接逻辑未匹配该硬件级联顺序,导致Road3、Road4的灯位完全错位。 - 位拼接偏移计算错误:原代码中
road4 << 9、road3 << 6的偏移量未对应实际硬件连接的移位寄存器输出位,造成灯状态映射混乱。 - 冗余延迟导致逻辑混乱:
defaultSequence中额外的delay(10000)与updateTraffic内的延迟重复,导致路口切换逻辑出现不必要的等待。
解决方法
1. 修正位拼接与移位发送逻辑
重新构造移位寄存器的输出字节,改用LSBFIRST发送,确保每路LED的位与移位寄存器的输出引脚一一对应:
- 第二个移位寄存器控制Road3(Q0-Q2)、Road4(Q3-Q5)
- 第一个移位寄存器控制Road1(Q0-Q2)、Road2(Q3-Q5)
2. 移除冗余延迟
删除defaultSequence中重复的delay(10000),避免路口切换逻辑混乱。
3. 验证硬件连接
确认第二个移位寄存器的DS引脚连接到第一个移位寄存器的Q7'引脚,LED引脚对应关系与代码逻辑一致。
修正后的完整代码
// Pin Definitions const int dataPin = 10; // DS const int clockPin = 8; // SH_CP const int latchPin = 9; // ST_CP // Sensors const int sensor1 = A0, sensor2 = A1, sensor3 = A2, sensor4 = A3; // LED States (12 LEDs controlled via 2 shift registers) byte road1 = 0b001; // Red: bit0=1, Yellow: bit1=1, Green: bit2=1 byte road2 = 0b001; byte road3 = 0b001; byte road4 = 0b001; void setup() { // Setup Serial monitor Serial.begin(9600); // Shift register pins pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(latchPin, OUTPUT); // Sensor pins pinMode(sensor1, INPUT); pinMode(sensor2, INPUT); pinMode(sensor3, INPUT); pinMode(sensor4, INPUT); } void loop() { defaultSequence(); } void updateTraffic(int road) { // Set all roads to red road1 = 0b001; road2 = 0b001; road3 = 0b001; road4 = 0b001; // Update the road based on priority switch (road) { case 1: road1 = 0b100; break; // Green for Road 1 case 2: road2 = 0b100; break; // Green for Road 2 case 3: road3 = 0b100; break; // Green for Road 3 case 4: road4 = 0b100; break; // Green for Road 4 } writeShiftRegisters(); delay(10000); // Green light duration setYellow(road); } void setYellow(int road) { // Set the selected road to yellow switch (road) { case 1: road1 = 0b010; break; case 2: road2 = 0b010; break; case 3: road3 = 0b010; break; case 4: road4 = 0b010; break; } writeShiftRegisters(); delay(2000); // Yellow light duration } void setRed(int road) { // Set the selected road to red switch (road) { case 1: road1 = 0b001; break; case 2: road2 = 0b001; break; case 3: road3 = 0b001; break; case 4: road4 = 0b001; break; } writeShiftRegisters(); } void defaultSequence() { for (int i = 1; i <= 4; i++) { Serial.print("Road: "); Serial.println(i); updateTraffic(i); } } void writeShiftRegisters() { // 构造两个移位寄存器的输出字节 // reg2控制第二个移位寄存器:Road3(bit0-2)、Road4(bit3-5) byte reg2 = (road4 << 3) | road3; // reg1控制第一个移位寄存器:Road1(bit0-2)、Road2(bit3-5) byte reg1 = (road2 << 3) | road1; // 打印调试信息 Serial.print("reg2 (Road3/Road4): "); for (int i = 7; i >= 0; i--) { Serial.print((reg2 >> i) & 1); } Serial.print(" | reg1 (Road1/Road2): "); for (int i = 7; i >= 0; i--) { Serial.print((reg1 >> i) & 1); } Serial.println(); // 发送数据到移位寄存器 digitalWrite(latchPin, LOW); // 级联时先发送第二个寄存器的内容(LSBFIRST让最低位对应Q0) shiftOut(dataPin, clockPin, LSBFIRST, reg2); shiftOut(dataPin, clockPin, LSBFIRST, reg1); digitalWrite(latchPin, HIGH); }
内容的提问来源于stack exchange,提问作者Haris Ali
相关产品推荐
相关产品推荐

