Программирование 74HC595 с помощью микроконтроллера

Тема в разделе "Микроконтроллеры AVR", создана пользователем Vallek, 13 мар 2015.

  1. Vallek

    Vallek Нерд

    Кто-нибудь сталкивался? Пытался запрограммировать со светодиодной шкалой (http://amperka.ru/product/bar-led) - для выполнения бегущего огонька, но вообще странно получается. Либо всё горит. Либо всё не горит. Либо хаотично моргает. Что самое забавное, если на мои 3 сегментника подать только питание и землю, а выводы подключить к светодиодной шкале, то тоже начинается это хаотичное моргание. Почему? Ведь я не управляю сдвигом, защёлкой и данными! Я понял бы, если бы это было на одном 595, но так ведут себя все 3! Причём, на ардуине, всё работало (раньше, месяца 3 назад проверял, после этого не использовал).
    Также, пробовал использовать как AtTiny2313A, также и Atmega8A. Ничего не вышло. Хотя "Hello World" на обоих контроллерах проходит на ура =).

    Ниже, пример кода:

    #include <avr/io.h>
    #include <util/delay.h>


    #define ST PD0
    #define DS PD1
    #define SH PD2


    void intializationPorts() {
    DDRD |= (1<<PD0); // PortB Pin0 -> output
    DDRD |= (1<<PD1); // PortB Pin1 -> output
    DDRD |= (1<<PD2); // PortB Pin2 -> output
    ACSR = 0x80;
    }


    void shiftOutput(unsigned char byte) {

    char i; //Current register of 74HC595
    unsigned char mask = 1; // define mask as 1

    for (i = 0; i < 8; i ++) { /* Loop by registers of 74HC595 */

    if (byte & mask) {
    PORTB = 1 << DS;
    } else {
    PORTB = 0 << DS;
    }
    PORTB = 1 << SH;
    PORTB = 0 << SH;
    mask = mask >> 1;
    }
    PORTD = 1 << ST; /* SHOW SHIFTING RESULT*/
    }


    int main(void) {

    unsigned char segments[9] = {
    0b10000000, 0b01000000, 0b00100000, 0b00010000, 0b00001000,
    0b00000100, 0b00000010, 0b00000001,0b00000000
    };

    intializationPorts();
    while (1) {
    int index;
    for (index = 0; index < 8; index ++) {

    shiftOutput(segments[index]);
    _delay_ms(50);
    }
    }
    return 0;
     
  2. Unixon

    Unixon Оракул Модератор

    Ну естественно фигня будет. Инициализируете порт D, а потом работаете с портом B, да и то неправильно - вместо модификации отдельных битов порта переписываете его весь.
     
    Vallek нравится это.
  3. Vallek

    Vallek Нерд

    По поводу порта - прошу прощения, это я сейчас на работе по памяти набросал - не заметил. Так то да, я работал с одним портом. А вот по поводу модификации, можно поподробнее?
     
  4. Unixon

    Unixon Оракул Модератор

    Установка бита:
    неправильно: PORTB = 1<<DS;
    правильно: PORTB |= 1<<DS;
    правильно: PORTB = PORTB | 1<<DS;

    Сброс бита:
    неправильно: PORTB = 0<<DS;
    правильно: PORTB &=~(1<<DS);
    правильно: PORTB = PORTB & ~(1<<DS);
     
    Vallek и Tomasina нравится это.
  5. Vallek

    Vallek Нерд

    О, спасибо большое! Обязательно попробую!
     
  6. Vallek

    Vallek Нерд

    А можно тогда ещё раз спросить, о чём я спрашивал ранее, почему, если мы не подключаем управляющие линии, а только питание, и землю, ну и соответственно выводы непосредственно на светодиоды, то тоже начинается хаотичное моргание? Мы же никак не управляем сдвиговым регистром!
     
  7. Unixon

    Unixon Оракул Модератор

    Плавающий КМОП вход ловит помехи и переключается хаотически. Притяните входы резисторами 10кОм к шине питания, соответствующей неактивному уровню (/SCLR,/G - к Vcc, остальные к GND), и все моргание прекратится.
     
    Vallek нравится это.
  8. Vallek

    Vallek Нерд

    Прошу прощения за некомпетентность, но что такое /SCLR,/G? Просто я недавно только начал изучать всё это дело, поэтому не совсем понял, о чём идёт речь. Я пробовал подключать Vcc и /MR через 10 кОм к шине питания, но не помогло
     
    Последнее редактирование: 13 мар 2015
  9. Unixon

    Unixon Оракул Модератор

    Обозначения выводов 74HC595 из его даташита. Вы по какой документации работаете?
     
    Vallek нравится это.
  10. Vallek

    Vallek Нерд

    Да вот тут местная есть: http://files.amperka.ru/datasheets/74hc595.pdf
     
  11. Unixon

    Unixon Оракул Модератор

    Ну в этом даташите /SCLR и /G называются /MR и /OE.
     
    Vallek нравится это.
  12. Vallek

    Vallek Нерд

    Благодарю! Обязательно попробую!
     
  13. Vallek

    Vallek Нерд

    Проверил! Да, всё отлично работает!!! Титаническое спасибо!!! Но всё-таки /G (Он же /OE) подключается походу дела к земле, а не к Vcc, так как на Vcc - не работает!
    И ещё у меня вопрос, в цикле, что нужно сдвигать, маску или передаваемое значение byte? И как делать непосредственно сдвиг, как я писал ранее в программе правильно? (mask = mask >> 1;)
    Просто если вручную действия делать, то всё отлично работает, а в цикле немножко бред. Хотя бегающий огонёк и есть, но он начинается где-то с середины, и вообще их два.
     
  14. Vallek

    Vallek Нерд

    Хотя всё, и на это нашёл ответ, сдвигаю маску вроде правильно, а первоначально нужно было к 0x80 присвоить маску, и сейчас полноценный огонёк получился! В любом случае огромнейшее спасибо за совет и помощь! Подчерпнул для себя хороший опыт! Так как 4 дня не мог его одолеть
     
  15. Unixon

    Unixon Оракул Модератор

    Если выходы регистра постоянно включены - тогда к земле, если управляются с МК - одновременно и к ноге МК и через подтягивающий резистор к Vcc (по умолчанию выходы выключены) или к земле (по умолчанию выходы включены).
     
    Последнее редактирование: 17 мар 2015
  16. Vallek

    Vallek Нерд

    Т.е. и в том и в другом случае выходы будут выключены по умолчанию?
     
  17. Unixon

    Unixon Оракул Модератор

    Исправил опечатку.
     
  18. Vallek

    Vallek Нерд

    Ок! Понятно! Спасибо большое! В принципе с бегущим огоньком разобрался, теперь хочу с матрицей светодиодной справиться. В принципе подвижки уже есть! В любом случае большое спасибо! Без Вашего совета, я бы ещё долго разбирался!
     
  19. Здравствуйте, подскажите в чем допустил ошибки. Создал проект в симуляторе proteus из ардуино, сдвигового регистра 74hc595 и семи сегментного индикатора ОА. Для примера попробовал вывести число 6, на индикаторе отобразило 600. В чем мой косяк?
     
    Последнее редактирование: 21 авг 2019
  20. Код
    Код (C++):
    const uint8_t latchPin = 8;//Пин присоединённый ко входу ST_CP 74HC595
    const uint8_t clockPin = 9;//Пин присоединенный ко входу SH_CP 74HC595
    const uint8_t dataPin = 10;//Пин присоединённый ко входу DS 74HC595

    const uint8_t digitPins[4] = {
      3,4,5,6}; // пины для управления 4 разрядами индикатора ОА

    const byte digit[10] =
    {
      B00111111, //0
      B00000110, //1
      B01011011, //2
      B01001111, //3
      B01100110, //4
      B01101101, //5
      B01111101, //6
      B00000111, //7
      B01111111, //8
      B01101111  //9
    };

    uint8_t digitBuffer[4] = {0};
    uint8_t digitScan = 0;
    volatile uint8_t soft_scaler = 0;
    uint8_t tmp;

    ISR(TIMER2_OVF_vect) { // Обработчик прерывания по переполнению таймера 2
      soft_scaler++;
      if(soft_scaler==15)
      {
        refreshDisplay();
        soft_scaler = 0;
      }
    };

    void setup()   {        
      for(uint8_t i=0; i<4; i++)
      {
        pinMode(digitPins[i],OUTPUT);
      }
      pinMode(latchPin, OUTPUT);
      pinMode(clockPin, OUTPUT);
      pinMode(dataPin, OUTPUT);

     
      TCCR2A = 0;
      TCCR2B = (1<<CS21);  // Предделитель на 8
      TIMSK2 = (1<<TOIE2); // Разрешение прерывания по переполнению таймера 2
      TCNT2 = 0;

      sei();
    }

    void refreshDisplay()
    {
      for(uint8_t k=0; k<4; k++)
      {
        digitalWrite(digitPins[k], LOW);
      }
      digitalWrite(latchPin, LOW);  // начинаем передачу бит
      shiftOut(dataPin, clockPin, MSBFIRST, B11111111);
      digitalWrite(latchPin, HIGH); // защелкиваем регистр
      delayMicroseconds(400);
      digitalWrite(digitPins[digitScan], HIGH);

      digitalWrite(latchPin, LOW);
      if (digitScan == 2)
      {
        shiftOut(dataPin, clockPin, MSBFIRST, ~(digit[digitBuffer[digitScan]] | B10000000)); //устанавливаем положение десятичной точки
      }
      else
      {
        shiftOut(dataPin, clockPin, MSBFIRST, ~digit[digitBuffer[digitScan]]);
      }
      digitalWrite(latchPin, HIGH); // защелкиваем регистр
      digitScan++;
      if(digitScan>3) digitScan=0;
    }

    void loop()            
    {
      tmp = 6;
      digitBuffer[3] = tmp/1000;
      digitBuffer[2] = (tmp%1000)/100;
      digitBuffer[1] = (tmp%100)/10;
      digitBuffer[0] = (tmp%100)%10;

      delay(50);
    }

     
     
    Последнее редактирование: 21 авг 2019