Вывод информации на 4 разрядный 7сегментный индикатор при помощи двух 74hc595

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

http://arduino.ru/Reference/Serial/Available

  if (gsm.available()) {
    while (gsm.available()) {
      .
      .
      .
      .
    }
.
.
.
}

 

mag155
Offline
Зарегистрирован: 21.12.2017

Получилось вот так 

void loop() {
  

 
if (radio.available()) {
while (radio.available()) {
  val = radio.read();
} 
   float numbers[] = {val}; 
      Serial.println(val);
  
 unsigned long currentMillis = millis();
   
 if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
   
  getDigits(numbers[numindex]);
    numindex += 1;
 
    if (numindex >= sizeof(numbers)/sizeof(float)) numindex = 0;
  }
 
  displayMessage(arr);

}
}

 

mag155
Offline
Зарегистрирован: 21.12.2017

Значение через val не могу вывести больше 250 ???

alexeko
Offline
Зарегистрирован: 03.01.2014

mag155, дайте определение динамической индикации, а не выжимайте из AVR невозможного. Если динамику делать на ардуинке, то считаем: время затухания светодиода, после того как убираете напряжение и скорость обновления (полного прохода) по коду. Тут, как писано в старых учебниках, надо, при большом количестве диодов, повышать напряжение, что бы горели лучше. Но, индикатор может сгореть, если что то не так пойдет. Если мигает - результат большого времени работы программного кода. 

Есть отдельные драйвера, которые сами делают индикацию, а ардуинка подает только данные для определенного диода. 

А, так получается, Вы пытаетесь что выжать из ее максимума. Я не хочу Вас обидеть. Просто надо искать ошибки не только кода, но и железа.

 

 

mag155
Offline
Зарегистрирован: 21.12.2017

Точнее передать только 0-250

 val = analogRead(potent_pin);    
 val = map(val, 0, 1023, 0, 1023);  
  //val = constrain(val, 0, 250);      
      Serial.println(val);  
  analogWrite(3,val);
radio.write(val);

 

mag155
Offline
Зарегистрирован: 21.12.2017

Я и пытаюсь с ардуинки сделать драйвер чтоб можно было подключать любой индикатор. И к моему восторгу это таки получилось. Сейчас просто передаю значение с другой ардуины потенциометра но что то голова совсем зависла передает только от 0до 250 а надо от 0 до 1023??? Пойду наверно кофе бахну.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

mag155 пишет:

Получилось вот так 

void loop() {
  

 
if (radio.available()) {
while (radio.available()) {
  val = radio.read();
} 
   float numbers[] = {val}; 
      Serial.println(val);
  
 unsigned long currentMillis = millis();
   
 if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
   
  getDigits(numbers[numindex]);
    numindex += 1;
 
    if (numindex >= sizeof(numbers)/sizeof(float)) numindex = 0;
  }
 
  displayMessage(arr);

}
}

 

фигня получилась - скобки расставьте правильно, а то получается что отображение на дисплей происходит с периодом interval только в том случае если по SErial вам что то придет иначе ничего не отображается

нарисуте на бумаге (или в голове мысленно) что должно происходить

1. т.е. каждые полсекунды чтение датчика

2. при каждом loop отображение значения датчика

3. при приеме байта (слова) из Serial выводить в монитор число и что то делать

и все это должно работать независимо друг от друга

а щас у вас каша и в голове и в коде

mag155
Offline
Зарегистрирован: 21.12.2017
}

   float numbers[] = {val}; 
      Serial.println(val);

 unsigned long currentMillis = millis();
   
 if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;

  getDigits(numbers[numindex]);
    numindex += 1;
 }

    if (numindex >= sizeof(numbers)/sizeof(float)) numindex = 0;
 

Так кажись лучше отображается когда что-то пришло и без периода интерва

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

mag155 пишет:

}

   float numbers[] = {val}; 
      Serial.println(val);

 unsigned long currentMillis = millis();
   
 if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;

  getDigits(numbers[numindex]);
    numindex += 1;
 }

    if (numindex >= sizeof(numbers)/sizeof(float)) numindex = 0;
 

Так кажись лучше отображается когда что-то пришло и без периода интерва

и как можно разобраться по этому огрызку кода, в котором даже не понятно где начало и конец фигурных скобок

mag155
Offline
Зарегистрирован: 21.12.2017

Пардон

 

mag155
Offline
Зарегистрирован: 21.12.2017

void loop() {
  

 
if (radio.available()) {
while (radio.available()) {
  val = radio.read();
}

   float numbers[] = {val}; 
      Serial.println(val);

 unsigned long currentMillis = millis();
   
 if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;

  getDigits(numbers[numindex]);
    numindex += 1;
 }

    if (numindex >= sizeof(numbers)/sizeof(float)) numindex = 0;
 
 
  displayMessage(arr);
}

}

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

и чем последний код отличается от кода в сообщении 252?

ЗЫ. Вы мне напоминаете одного программиста из одной очень известной компании России,

промышленный банковский продукт, ошибка в работе его части кода,

он частенько тупо менял названия переменных, и типа исправил :)

естественно ошибка так и осталась.

mag155
Offline
Зарегистрирован: 21.12.2017

То что индикатор работает только если пришли данные мне подходит . Но я не пойму где вы видите что он моргает с периодом интервал ??? Подскажите  а то реально не пойму где?

void loop() {
  

 
if (radio.available()) {
while (radio.available()) {
  val = radio.read();
}

   float numbers[] = {val}; 
      Serial.println(val);

 unsigned long currentMillis = millis();
   
 if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;

  getDigits(numbers[numindex]);
    numindex += 1;
 
 }
    if (numindex >= sizeof(numbers)/sizeof(float)) numindex = 0;
 

  displayMessage(arr);
}

}

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

вот так попробуйте

void loop() {
  
 unsigned long currentMillis = millis();

 
if (radio.available()) {
while (radio.available()) {
  val = radio.read();
}

   float numbers[] = {val}; 
      Serial.println(val);
}

   
 if((currentMillis - previousMillis) > interval) {
previousMillis = currentMillis;

  getDigits(numbers[numindex]);
    numindex += 1;
    if (numindex >= sizeof(numbers)/sizeof(float)) numindex = 0;
 
 }
 

  displayMessage(arr);

}

 

mag155
Offline
Зарегистрирован: 21.12.2017

В порту данные есть а на индикаторе Err .??

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

mag155 пишет:

В порту данные есть а на индикаторе Err .??

ниче не понял в чем вопрос

mag155
Offline
Зарегистрирован: 21.12.2017

В порту цифры 66 на индикаторе Err а должно быть тоже 66 ?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

вот смотрите:

приходят данные , переводятся в переменную val, выводяться в монитор,

далее каждые interval времени процедура getDigits формирует строку символов для вывода на экран - правильно?

возникает вопрос: а эта процедура которая формирует строку - она использует переменную val с исходными данными?

 

mag155
Offline
Зарегистрирован: 21.12.2017

Получается что нет.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

mag155 пишет:

Получается что нет.

вот и разбирайтесь почему, т.е. эту переменную надо сделать или глобальной и учитывать в функции рисования или передавать значение как второй параметр в процедуру.

mag155
Offline
Зарегистрирован: 21.12.2017

Ок. 

mag155
Offline
Зарегистрирован: 21.12.2017

Здялал так 

void loop() {
  unsigned long currentMillis = millis();
if (radio.available()) {
while (radio.available()) {
  val = radio.read();
}
 
  
     // Serial.println(val);
}  float numbers[] = {val};

  if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;

  getDigits(numbers[numindex]);
    numindex += 1;
  
       if (numindex >= sizeof(numbers)/sizeof(float)) numindex = 0;
  
}
  displayMessage(arr);

}

 

mag155
Offline
Зарегистрирован: 21.12.2017

И видимость переменной

int val=radio.read(); 

 

mag155
Offline
Зарегистрирован: 21.12.2017

Пкретикуйте если не сложно ??

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Работает? Устраивает? Значит нефиг ломать работающее.

mag155
Offline
Зарегистрирован: 21.12.2017

Работает устраивает. Но чё то точку не отображает?

mag155
Offline
Зарегистрирован: 21.12.2017
void loop() {
  unsigned long currentMillis = millis();
if (radio.available()) {
while (radio.available()) {
  val = radio.read();
}
//val = map(val, 0, 500, 1, 500);
  val = constrain(val, 0, 500);
  
      Serial.println(val);
}  float numbers[] = {val};

  if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;

  getDigits(numbers[numindex]);
    numindex += 1;
  
       if (numindex >= sizeof(numbers)/sizeof(float)) numindex = 0;
  
  }
  displayMessage(arr);

}

void getDigits (float value) {
  Serial.println("");

  // Выдаем ошибку на те значения, которые не можем показать
  if ((value >= 10000) ||
      (value <= -1000) ||
      (value > -0.01 && value < 0.001)) {
    for (int i = 0; i < 4; i++) { // Каждый разряд по очереди
      for (int k = 0; k < 8; k++) {// Каждый сегмент по очереди - исходя из заданной карты
        arr[i][k] = err[i][k];
      }
    }
    return; // Выходим
  }
  int digits = 4; // У нас 4 разряда
  if (value < 0) digits = 3; // Из-за минуса один символ убирается*/
  // Делим число на 2 группы - отдельно целую часть и дробную.
  int intPart = (int)abs(value);
  int intLength = ((String)intPart).length(); // Смотрим, сколько разрядов занимает целая часть
  // На дробную часть у нас остается разрядов: digits-intLength
  int fracPart = (int)((abs(value) - abs(intPart)) * 1000); // Мы можем показать максимум 3 знака после запятой - 0,000
  int fracDigits = digits - intLength;
  fracPart = (((String)fracPart).substring(0, fracDigits)).toInt();
  // Собираем строку для отображения
  String output = (value < 0) ? "-"  : "";
  output += (String)intPart;
  String outputFrac = ((digits - intLength <= 0) || (fracPart == 0)) ? "" : ((String)"." + ((String)fracPart).substring(0, digits - intLength));
  output += (String)outputFrac;
   // Дополняем символы спереди, если цифр слишком мало, например для "-1" делаем "  -1"
  String spaces = "     ";
  digits = 4;
  if (~output.indexOf(".")) digits += 1;
  if (output.length() < digits) output = spaces.substring(0, digits - output.length()) + output;
  // Формирум данные для показа:
  int dig = -1;
  for (int i = 0; i < output.length(); i++) {
    String _char = output.substring(i, i + 1);
    if (_char != ".") dig += 1; // Точка не занимает сегмент - увеличиваем на 1
    int actualdigit = 11; // По умолчанию пустой символ
    if ((_char == "-")) {
      actualdigit = 10;
    }
    else if (_char == " " || _char == ".") {
    }
    else {
      actualdigit = _char.toInt();
    }
    if (_char == ".") {
      arr[dig][7] = 1; // Если нужно - ставим точку
    }
    else  {
      for (int n = 0; n <= 7; n++) {
        arr[dig][n] = seg[actualdigit][n];
      }
    }
  }
}
void displayMessage(int dig[4][8]) {
  for (int i = 0; i < 4; i++) { // Каждый разряд по очереди
   for (int k = 0; k < 8; k++) {// Каждый сегмент по очереди - исходя из заданной карты
   digitalWrite(segmentsPins[k], ((dig[i][k] == 1) ? 1 : 0));
 }
digitalWrite(anodPins[i], 0);
delay(2);
digitalWrite(anodPins[i], 1);
  
  }
  }

 

mag155
Offline
Зарегистрирован: 21.12.2017

Даже если вот так пишу показует только 9

float numbers[] = {9.3};

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Чтоб отображать точку, надо установить нужный бит в нужное состояние, соответственно в вашей процедуре заполняющей нужные биты необходимо дополнить нужное условие, например если второй разряд = установить 7 бит - одна строка программы

mag155
Offline
Зарегистрирован: 21.12.2017

А разве 45 и 46 строки не для этого ?

mag155
Offline
Зарегистрирован: 21.12.2017

Или все дело в 63 строке?

mag155
Offline
Зарегистрирован: 21.12.2017

И 73 с 74 ?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Вроде они, но как видите не работает)
Разбираться надо - некогда

mag155
Offline
Зарегистрирован: 21.12.2017

ПРОБЛЕМА ОКАЗАЛАСЬ В БИБЛИОТЕКЕ 

#include <SoftwareSerial.h>

 

mag155
Offline
Зарегистрирован: 21.12.2017

Доброго времени суток решил добить тему с индикатором. Вопрос как допилить код чтоб работатл со здвиговыми регистрами как например в 174 сообщении ???

arduino_kz
Offline
Зарегистрирован: 25.08.2016

Доброго времени суток.

В начале темы автор сделал схему подключения скетч для индикатора с общим анода. Что можно сделать если индикатор с общим катодом? без транзисторов не обойтись?

mag155
Offline
Зарегистрирован: 21.12.2017

Нужно управлять минусом тоест low.

arduino_kz
Offline
Зарегистрирован: 25.08.2016

Делаю все по схеме так же?

по части скетча где нужно поменять?

Буду благодарен за совет?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

А нужны ли эти заморочки когда есть дешевая микросхема TM1650, а также TM1637 TM1638

 

 

CheBuraw
Offline
Зарегистрирован: 10.02.2015

arduino_kz пишет:

Делаю все по схеме так же?
по части скетча где нужно поменять?
Буду благодарен за совет?

Вам нужно поправить только в этом месте:

// Настройка комбинации для отображения каждого номера на дисплее.
// Комбинация выбрана на основе таблицы отображаемого знака данным порта
// Соответственно { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , dp, - }
byte g_digits[12]={192,249,164,176,153,146,130,248,128,144,127,255}; //массив цифр, генерирующий из сегментов цифры
byte g_registerArray[4]={1,2,4,8}; //массив цифр, указывающий разряды

А рассчитать можно по аналогии с табличкой:

Соответствие отображаемого знака данным порта
общий анод
__________________________________________________
     |   двоичный вид по сегментам   |            |
Цифра|dp | G | F | E | D | C | B | A | Десятичный |
-----|---|---|---|---|---|---|---|---|------------|
  0  | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |    192     |
  1  | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |    249     |
  2  | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |    164     |
  3  | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |    176     |
  4  | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 |    153     |
  5  | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |    146     |
  6  | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |    130     |
  7  | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |    248     |
  8  | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |    128     |
  9  | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |    144     |
 dp  | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |    127     |
-----*---*---*---*---*---*---*---*---*------------*

Только у вас там где 1 должен быть 0. К примеру цифра "0" при общем аноде имеет
бинарный вид: 11000000 = 192 в десятичном виде, при общем катоде:
бинарный вид: 00111111 = 63 в десятичном виде, и так далее для остальных символов.

При этом не забудте поправить и массив для разрядов. там так же нужно пересчитать по тому же принципу:
общий анод, первый разряд 00000001 = 1
общий катод, 11111110 = 254
а можно еще проще для разрядов - имеющийся адрес вычитать из 255:
255-1=254, 255-2=253, 255-4=251, 255-8=247 и тогда для разрядов адреса будут такие:
 

byte g_registerArray[4]={254,253,251,247}; //массив цифр, указывающий разряды

Если лень вспоминать школьный курс информатики ;)

jeka_tm пишет:

А нужны ли эти заморочки когда есть дешевая микросхема TM1650, а также TM1637 TM1638

Лично я затеял все это потому что было много трофейных 74hc595 и думал куда их можно пристроить, хотелось вообще разобраться как с ними можно работать и нужен был индикатор для одной поделки. 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

CheBuraw пишет:

Лично я затеял все это потому что было много трофейных 74hc595 и думал куда их можно пристроить, хотелось вообще разобраться как с ними можно работать и нужен был индикатор для одной поделки. 

Да я тоже самое делал. Просто сейчас если и ставить только расширения выходных портов, для семисегментного уже пожалуй нет

arduino_kz
Offline
Зарегистрирован: 25.08.2016

Получилось спасибо большое!

iStarCom
Offline
Зарегистрирован: 21.06.2020

Всем привет.

Есть статья на радиокоте https://www.radiokot.ru/lab/controller/08/ с использованием 9 разрядов 7 сегментного индикатора от телефона Русь 25-27. Лежал у меня подобный индикатор но сравнив схемы я обнаружил в своем варианте некоторые отличия и решил отрисовать свой вариант. Плата панельки построена на 3-х индикаторах TOT-3361AH-1N с общим катодом и двух сдвиговых регистра 74HC595D.

Сегменты распаяны хаотично. Первым идет сдиговый регистр разрядов а потом сегментов.

Вывести что то адекватное на него не получается. Код привожу ниже, адаптировав его под Общий катод и сдвиговые регистры.

1) То есть нужно воять свою таблицу символов под данную распайку сегментов?


int latchPin = 10;     //Пин "защелки" первого регистра подключен к ST_CP входу первого регистра отвечающего за сегменты
int clockPin = 13;    //Пин подключен к SH_CP входу 74HC595
int dataPin = 12;     //Пин подключен к DS входу 74HC595

int TimeLight = 2;  //время для разогрева сегментов
int sensorPin = A0;

byte SegDisplay; // переменная для вывода символов на индикаторе
byte RazrDisplay; // переменная для включения разрядов

// Настройка комбинации для отображения каждого номера на дисплее.
// Комбинация выбрана на основе таблицы отображаемого знака данным порта
// Соответственно { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , dp, - }
byte g_digits[12] = {63, 6, 91, 79, 102, 109, 125, 7, 127, 111, 128, 64}; //OK, массив цифр, генерирующий из сегментов цифры

byte g_registerArray[9] = {254, 253, 251, 247, 239, 223, 191, 127, 255}; //OK, массив цифр, указывающий разряды


void setup() {
  // обозначаем все пины как выходы
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop() {
  int disp = 0; //создаем переменную для вывода на экран

  int analogueValue = analogRead(sensorPin);  // читаем аналоговый пин A0
  analogueValue = map(analogueValue, 0, 1023, 0, 8888); //преобразуем диапазон с А0 (0-1023) в нужный нам (0-8888)

  disp = analogueValue; // записываем получившуюся после преобразования цифру в переменну для вывода на экран

  // Разбиваем цифру по разрядам индикатора
  if (disp < 10) // если наша цифра меньше 10, то
  {
    Indicate(5, 11); // пишем в первый разряд пусто
    Indicate(6, 11); // пишем во второй разряд пусто
    Indicate(7, 11); // пишем в третий разряд пусто
    Indicate(8, disp); // пишем в четвертый разряд нашу цифру
  }
  else if (disp < 100) // если наша цифра меньше 100, то
  {
    Indicate(5, 11); // пишем в первый разряд пусто
    Indicate(6, 11); // пишем во второй разряд пусто
    Indicate(7, disp / 10); // пишем в третий разряд - цифру делёную на 10
    Indicate(8, disp % 10); // пишем в четвертый разряд цифру оставшуюся от деления на 10
    /*
      Допустим наша цифра 25.
      Если мы ее поделим на 10, то у нас получится 2,5. Цифры после запятой, в данном случае,
      у нас не остаются. Таким образом мы имеем в третем разряде цифру 2.
      В чевертый разряд мы, как раз и записываем цифру-остаток полученную в результате деления.
      В нашем случае это и есть та самая 5.
      Аналогичным образом разбивается наша цифра и далее.
    */
  }
  else if (disp < 1000)
  {
    Indicate(5, 11);
    Indicate(6, disp / 100);
    Indicate(7, (disp % 100) / 10);
    Indicate(8, disp % 10);
  }
  else
  {
    Indicate(5, disp / 1000);
    Indicate(6, (disp % 1000) / 100);
    Indicate(7, (disp % 100) / 10);
    Indicate(8, disp % 10);
  }
}

void Indicate(int r, int x)
{
  SegDisplay = g_digits[x]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
  RazrDisplay = g_registerArray[r]; // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре.
  digitalWrite(latchPin, LOW);  // устанавливаем синхронизацию "защелки" на LOW
  shiftOut(dataPin, clockPin, MSBFIRST, RazrDisplay); // Записываем информацию для второго регистра (Номер разряда)
  shiftOut(dataPin, clockPin, MSBFIRST, SegDisplay);  // Записываем информацию для первого регистра (Номер символа)
  digitalWrite(latchPin, HIGH);  //"защелкиваем" регистр, тем самым устанавливая значения на выходах
  delay(TimeLight); // пауза, чтобы сегменты "разгорелись"
}

2) Как адаптировать код на радиокоте под 9 разрядов к данной реализации?

iStarCom
Offline
Зарегистрирован: 21.06.2020

1) [РЕШЕНО]

Изменил кодовую страницу под данное подключение сегментов так

byte g_digits[12] = {235, 72, 115, 122, 216, 186, 187, 104, 251, 250, 4, 16};

Все цифры отображаются нормально! 

2) 9 разряд подключен на Q7S (14 и 9 пин регистра сдвига) [НЕ РЕШЕНО]

Как решение с радиокота перенести на ардуино код?

 

CheBuraw
Offline
Зарегистрирован: 10.02.2015

1) Только Вам хотел написать, что надо под свою распайку индивидуально коды указывать, а Вы уже всё решили :)

2) Могу заблуждаться, но предположу что 9 разряд не подключить, так как у 595 всего 8 выходов, а  Q7S создан для иных задач- Выход для последовательного соединения регистров. Тут хорошая статья про 74hc595: https://codius.ru/articles/Arduino_Сдвиговый_регистр_74НС595_или_размножаем_экономим_выходы_платы

iStarCom
Offline
Зарегистрирован: 21.06.2020

Ну судя по решению с радиокота, автор там четко описал как юзая связку пина 9 и 14 двух регистров сдвига он смог использовать 9 разряд. Вот бы его решение перенести на ардуино код. Жалко терять 9 разряд!

b707
Offline
Зарегистрирован: 26.05.2017

iStarCom пишет:

Ну судя по решению с радиокота, автор там четко описал как юзая связку пина 9 и 14 двух регистров сдвига он смог использовать 9 разряд. Вот бы его решение перенести на ардуино код. Жалко терять 9 разряд!

ну там вроде все понятно обьяснено. Загружаете последовательно, сначала данные для 9-ого разраяда - в виде 0b00000000 для включения, 0b11111111 для выключения. а потом биты остальных восьми разрядов. Защелкиваете Latch и наслаждаетесь

iStarCom
Offline
Зарегистрирован: 21.06.2020

Знаний маловато, можно Вас попросить показать на примере?

iStarCom
Offline
Зарегистрирован: 21.06.2020

b707 пишет:

iStarCom пишет:

Ну судя по решению с радиокота, автор там четко описал как юзая связку пина 9 и 14 двух регистров сдвига он смог использовать 9 разряд. Вот бы его решение перенести на ардуино код. Жалко терять 9 разряд!

ну там вроде все понятно обьяснено. Загружаете последовательно, сначала данные для 9-ого разраяда - в виде 0b00000000 для включения, 0b11111111 для выключения. а потом биты остальных восьми разрядов. Защелкиваете Latch и наслаждаетесь

Все оказалось намного проще, мал мал поправил код для 328p (Ардуино нано) и все получилось!

// WinAvr
#include <avr/io.h>
#include <avr/interrupt.h>
#define DATA  5
#define SHIFT 6
#define STORAGE 7
#define PORTSERIAL  PORTD
#define DDRSERIAL    DDRD
#define BUT   0
#define BIT(bit)  (1<<(bit))

unsigned char lcd_buffer[9] = {0xEB, 0x48, 0x73, 0x7A, 0xD8, 0xBA, 0xBB, 0x68, 0xFB};
//*************************************************************
void data_shift(unsigned char data)
{
  // выводим бит данных, сдвигаем и так 8 раз.
  unsigned char i = 0;
  for (i = 8; i ; i--) {
    if (data & BIT(i - 1) )  PORTSERIAL |= BIT(DATA); // выводим бит данных
    else   PORTSERIAL &= ~BIT(DATA);
    PORTSERIAL |= BIT(SHIFT); // сдвиг данных
    PORTSERIAL &= ~BIT(SHIFT);
  }
}
//*************************************************************
void num_out(unsigned char znmesto)
{
  unsigned char i = 0;
  PORTSERIAL |= BIT(STORAGE); // выводы микросхем в Z состояние
  data_shift(lcd_buffer[znmesto]);// загружаем символ в первый регистр

  if (znmesto == 7) i = 1; //7 знакоместо
  if (znmesto == 8) i = 2; //8 знакоместо
  znmesto = ~(1 << (znmesto)); // число в бит места (пример 0х3->0b11110111)

  data_shift(znmesto);// вывод знакоместа, символ сдвигается в второй регистр

  if ( i == 0 )
  {
    PORTSERIAL &= ~BIT(STORAGE);
    PORTSERIAL |= BIT(STORAGE); // сохранили
    PORTSERIAL &= ~BIT(STORAGE); // и вывели
  }
  else if (i >= 1) { // 7 знакоместо
    PORTSERIAL &= ~BIT(STORAGE);
    PORTSERIAL |= BIT(SHIFT) | BIT(STORAGE); // сохранили и вывели
    PORTSERIAL &= ~(BIT(SHIFT) | BIT(STORAGE));
    //shift нужен потому что 0 переместился из Q6 в -Q7
  }
  if (i == 2)   data_shift(0x0); //9 разряд.
  //Сейчас все выходы первого регистра уст в 1,
  //загружаем регистр нулями в итоге -Q7 = 0, но не сохроняем.

  PORTSERIAL &= ~(BIT(DATA) | BIT(SHIFT) | BIT(STORAGE));
}
//*************************************************************
int main( void )
{
  unsigned char i = 0;
  PORTSERIAL = BIT(BUT) | BIT(STORAGE);
  DDRSERIAL = 0xf0;
  TCCR0B = 3;
  while (1) {
    TCNT0 = 127;
    while (!(TIFR0 & BIT(0))); // Задержка такая :-) по идеи 2ms
    TIFR0 |= 1;
    //if ( !TESTBIT(PIND,BUT) ) //если включить то вывод цифры
    {
      //while ( !TESTBIT(PIND,BUT) );// будет только по нажатию
      if (i > 8) i = 0;
      num_out(i);
      i++;
    }
  }
}

Всем спасибо за пинОК )))

iStarCom
Offline
Зарегистрирован: 21.06.2020

Пофиксенный вариант.

// WinAvr
// Fix by iStarCom 2020 for ATMEGA328P.
#include <avr/io.h>
#include <avr/interrupt.h>
#define DATA  5
#define SHIFT 6
#define STORAGE 7
#define PORTSERIAL  PORTD
#define DDRSERIAL    DDRD
#define BUT   0
#define BIT(bit)  (1<<(bit))

unsigned char lcd_buffer[9] = {0xEB, 0x48, 0x73, 0x7A, 0xD8, 0xBA, 0xBB, 0x68, 0xFB}; // РУСЬ 27 (ОК)
//unsigned char lcd_buffer[9] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F}; // СТАНДАРТ (ОК)
//*************************************************************
void data_shift(unsigned char data)
{
  // выводим бит данных, сдвигаем и так 8 раз.
  unsigned char i = 0;
  for (i = 8; i ; i--) {
    if (data & BIT(i - 1) )  PORTSERIAL |= BIT(DATA); // выводим бит данных
    else   PORTSERIAL &= ~BIT(DATA);
    PORTSERIAL |= BIT(SHIFT); // сдвиг данных
    PORTSERIAL &= ~BIT(SHIFT);
  }
}
//*************************************************************
void num_out(unsigned char znmesto)
{
  unsigned char i = 0;
  PORTSERIAL |= BIT(STORAGE); // выводы микросхем в Z состояние
  data_shift(lcd_buffer[znmesto]);// загружаем символ в первый регистр

  if (znmesto == 7) i = 1; //7 знакоместо
  if (znmesto == 8) i = 2; //8 знакоместо
  znmesto = ~(1 << (znmesto)); // число в бит места (пример 0х3->0b11110111)

  data_shift(znmesto);// вывод знакоместа, символ сдвигается в второй регистр

  if ( i == 0 )
  {
    PORTSERIAL &= ~BIT(STORAGE);
    PORTSERIAL |= BIT(STORAGE); // сохранили
    PORTSERIAL &= ~BIT(STORAGE); // и вывели
  }
  else if (i >= 1) { // 7 знакоместо
    PORTSERIAL &= ~BIT(STORAGE);
    PORTSERIAL |= BIT(SHIFT) | BIT(STORAGE); // сохранили и вывели
    PORTSERIAL &= ~(BIT(SHIFT) | BIT(STORAGE));
    //shift нужен потому что 0 переместился из Q6 в -Q7
  }
  if (i == 2)   data_shift(0x0); //9 разряд.
  //Сейчас все выходы первого регистра уст в 1,
  //загружаем регистр нулями в итоге -Q7 = 0, но не сохроняем.

  PORTSERIAL &= ~(BIT(DATA) | BIT(SHIFT) | BIT(STORAGE));
}
//*************************************************************
int main( void )
{
  unsigned char i = 0;
  PORTSERIAL = BIT(BUT) | BIT(STORAGE);
  DDRSERIAL = 0xf0;
  TCCR0B = 3;
  while (1) {
    TCNT0 = 127;
    while (!(TIFR0 & BIT(0))); // Задержка такая :-) по идеи 2ms
    TIFR0 |= 1;
  //  if ( !bitRead(PIND, BUT) ) //если включить то вывод цифры
    {
   //   while ( !bitRead(PIND, BUT) ); // будет только по нажатию
      if (i > 8) i = 0;
      num_out(i);
      i++;
    }
  }
}