Микросхема 74HC595 с 7-сегментным дисплеем постоянно отображает либо все единицы, либо все нули
Я сделал простую схему с Arduino Nano ESP32, к которой я подключил 8-битный чип сдвигового регистра 74HC595, а также 7-сегментный дисплей с резистором 100 Ом на общем проводе (катоде) для отображения состояния сдвигового регистра.
Ожидаемое поведение
Семисегментный дисплей показывает двоичный счет от 0 до 255.
Наблюдаемое поведение
Семисегментный дисплей непрерывно показывает 8.
, что по сути означает, что состояние сдвигового регистра равно 0b11111111
.
Когда я использую 5 В (VBUS) вместо 3,3 В для VCC микросхемы, сдвиговый регистр показывает все нули вместо всех единиц.
Попытки отладки
Я проверил все входные кабели с помощью мультиметра на предмет наличия сломанных соединений, и, похоже, все в порядке. Я также несколько раз менял сам чип, результаты были такими же. Я пробовал заменить резистор на общем выводе семисегментного дисплея на что-то около 1000 Ом, а затем обратно. Результаты были такими же. Я также использовал разные схемы для тестирования, результаты были такими же.
Ресурсы
Я сделал текущую версию своей схемы и кода как проект WOKWI (эмулятор): https://wokwi.com/projects/396140725340271617 [УСТАРЕЛО (также не обновляется по какой-то причине)]
Он имеет примерно те же самые соединения, что и моя макетная плата.
Вот скриншот схемы:
И код, на случай, если Вокви прекратит свое существование в будущем..
//************************************************************//
// Имя: shiftOutCode, Привет, мир
// Автор: Карлин Мо, Том Иго, Дэвид А. Меллис
// Дата: 25 октября 2006 г.
// Изменено: 23 марта 2010 г.
// Версия: 2.0
// Примечания: Код для использования сдвигового регистра 74HC595 //
// : для счета от 0 до 255
//***************************************************************
//Вывод подключен к ST_CP 74HC595
int latchPin = 8;
//Вывод подключен к SH_CP 74HC595
int clockPin = 12;
////Контакт подключен к DS 74HC595
int dataPin = 11;
void setup() {
//установить выводы на выход, чтобы можно было управлять сдвиговым регистром
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop() {
// счет от 0 до 255 ankKomd отображает число
// на светодиодах
for (int numberToDisplay = 0; numberToDisplay < 256; numberToDisplay++) {
// установите latchPin на низкий уровень, чтобы
// светодиоды не меняются во время отправки битов:
digitalWrite(latchPin, LOW);
// сдвигаем биты:
shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay);
//установите защелку на высокий уровень, чтобы светодиоды загорелись:
digitalWrite(latchPin, HIGH);
// пауза перед следующим значением:
delay(500);
}
}
@Niko, 👍5
3 ответа
Лучший ответ:
Не могу поверить, что для тактирования данных требуется задержка в одну секунду. У меня есть циклы, которые тактируют биты с использованием SPI без задержек, что даже быстрее, чем shiftOut. См. Использование выходного сдвигового регистра 74HC595 в качестве расширителя портов.
У вас есть какая-то другая проблема.
Возможно, дело в том, что все работает отлично, но число меняется так быстро, что создается впечатление, будто включены все сегменты.
Плюс, вам действительно не следует проводить тестирование без токоограничивающих резисторов на каждом сегменте. Один общий резистор будет вести себя странно в зависимости от того, сколько сегментов включено одновременно.
Я никогда не ожидал этого, но оказалось, что мой MCU был «слишком быстрым» (я полагаю), и поэтому ничего не отображалось. Вот код до исправления:
digitalWrite(latchPin, LOW); // Защелкиваем данные
// без задержки
digitalWrite(latchPin, HIGH); // Снять фиксацию для следующих данных
а это код после:
digitalWrite(latchPin, LOW); // Защелкиваем данные
delay(1000); // Короткая задержка для видимости (настройте по мере необходимости)
digitalWrite(latchPin, HIGH); // Снять фиксацию для следующих данных
Я все еще экспериментирую со сдвиговым регистром, поэтому я отредактирую этот ответ, если появится что-то новое или если мой ответ будет полностью неверным.
ПРАВКА: Мне не нужна была задержка в одну секунду между тактовыми импульсами, мне, по-видимому, просто нужна была некоторая задержка, чтобы увидеть изменение семисегментных дисплеев. (спасибо @NickGammon)
РЕДАКТИРОВАНИЕ: Вот полный код, если кому-то он нужен. Он отображает спиральную анимацию на 7-сегментном дисплее.
uint8_t latchPin = D8;
uint8_t clockPin = D12;
uint8_t dataPin = D11;
const byte segments[10] = { // Таблица поиска для цифровых шаблонов (общий катод)
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111100, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111 // 9
};
void setup() {
// Установить управляющие контакты как выходы
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
Serial.begin(115200); // Запуск последовательной связи для отладки
Serial.println("Starting...");
displaySegments(0x00000000); // сбрасывается при запуске, не нужен, просто выглядит лучше ig
delay(1000);
}
void spiralAnimation() {
// Проходим по каждому сегменту в спиральном порядке
for (int i = 0; i < 7 - 1; i++) { // 7 — количество сегментов, игнорируем G, поэтому выглядит лучше
shiftOut(dataPin, clockPin, MSBFIRST, 0b00000001 << i);
digitalWrite(latchPin, LOW);
delayMicroseconds(1000);
digitalWrite(latchPin, HIGH);
delay(80); // Настройте задержку для скорости анимации
}
}
void loop() {
// Пройти по каждому шаблону цифр (изменить для конкретного дисплея)
// для (int i = 0; i < 10; i++) {
// shiftOut(dataPin, clockPin, MSBFIRST, segments[i]);
// digitalWrite(latchPin, LOW); // Зафиксировать данные
// delay(100); // Короткая задержка для видимости (настройте по мере необходимости)
// digitalWrite(latchPin, HIGH); // Снять фиксацию для следующих данных
// Serial.print("Отображение: ");
// Serial.println(i);
// }
spiralAnimation();
}
void displaySegments(byte pattern) {
shiftOut(dataPin, clockPin, MSBFIRST, pattern);
digitalWrite(latchPin, LOW);
delayMicroseconds(1000); // нет необходимости редактировать это
digitalWrite(latchPin, HIGH);
}
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) // на всякий случай
{
uint8_t i;
for (i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST)
digitalWrite(dataPin, !!(val & (1 << i)));
else
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
}
Во-первых, код в вопросе не соответствует коду в «предполагаемом решении». Функция ShiftOut довольно медленная, поэтому она может работать как дополнительная задержка при размещении между настройками защелки. Так что рассматриваемый код выглядит надежным в этом смысле, имхо.
Далее, сомнительно требовать задержку в целую миллисекунду даже во втором случае. Чип 74hc595 должен иметь возможность обрабатывать сигнал быстрее 10 МГц даже при питании 3v3. И функция digitalWrite также довольно медленная (как и весь дополнительный слой совместимости Arduino), так что я не вижу здесь никакой проблемы.
Скорее всего, это происходит из-за паразитной емкости. Поэтому линия защелки (слишком длинная?) не успевает разрядиться даже на скорости в несколько мегабайт. Тогда сдвиговый регистр никогда не увидит низкий уровень напряжения, за исключением запуска. Правильные соединения (пайка проводов или, по крайней мере, использование только коротких перемычек) должны решить проблему.
- Как часто надо опрашивать 74HC165, если мы хотим обнаруживать нажатия кнопок?
- esp32, platformio A fatal error occurred: Packet content transfer stopped (received 8 bytes) *** [upload] Error 2
- Как выбрать альтернативные контакты I2C на ESP32?
- Драйверы для чипа последовательного порта CH9102X
- Как преобразовать форматированный оператор print в строковую переменную?
- ESP32 - "Детектор Браунаута был активирован" при запуске Wi-Fi
- Питание esp32cam от аккумулятора
- Контакты RX и TX на esp32