7 сегментный индикатор и странный глюк платы.

uscr
Offline
Зарегистрирован: 17.08.2012

 Здравствуйте. Подключил к Mega 2560 7 сегментный индикатор: земля на землю, аноды через 220 Ом резисторы на пины 22-28.

Написал говнокод:

//  __2__
// |     |
// 0     3
// |     |
// ---1---
// |     |
// 4     6
// |     |
//  --5--
int ind_pins[7] = {
  22, 23, 24, 25, 26, 27, 28};
int ind_pins_count = 7;

int dig = 0;

void setup() {
  for (int i=0; i<ind_pins_count; i++) {
    pinMode(ind_pins[i], OUTPUT);
  }
}

void seven_seg_digit_out(int pins_array[7], int digit) {
  for (int i=0; i<ind_pins_count; i++) {
    digitalWrite(pins_array[i], LOW);
  }
  if (digit == 0) { 

    digitalWrite(pins_array[0], HIGH);
    digitalWrite(pins_array[2], HIGH);
    digitalWrite(pins_array[3], HIGH);
    digitalWrite(pins_array[4], HIGH);
    digitalWrite(pins_array[5], HIGH);
    digitalWrite(pins_array[6], HIGH);
  }
 ...
 
  if (digit == 8) 
  {
    for (int i=0; i<ind_pins_count; i++) {
      digitalWrite(pins_array[i], HIGH);
    }
    /*digitalWrite(pins_array[0], HIGH);
    digitalWrite(pins_array[1], HIGH);
    digitalWrite(pins_array[2], HIGH);
    digitalWrite(pins_array[3], HIGH);
    digitalWrite(pins_array[4], HIGH);
    digitalWrite(pins_array[5], HIGH);
    digitalWrite(pins_array[6], HIGH);
    digitalWrite(pins_array[7], HIGH);*/
  }
}

void loop() {

  seven_seg_digit_out(ind_pins, dig);
  dig++;
  if (dig > 9) {
    dig = 0;
  }
  delay (500);

}

Если я вывожу восьмёрку так, как показано сейчас, то всё нормально. Но если я убираю цикл и убираю комментирование с куска кода, то при выводе восьмёрки, начинает светится светодиод на 7 выводе. Он загорается и больше не гаснет. Если пропускать восьмёрку при выводе, то светодиод не загорается. Что не так?

leshak
Offline
Зарегистрирован: 29.09.2011

 ПОтому что в строке 49 вы вообще выпрыгнули за границы массива. Элемента pins_array[7] - не существует. То есть вы взяли случайное значение из памяти, посчитали его пином и включили этот пин.

Следующим, после массива, в памяти оказался "int ind_pins_count = 7;"

Вот эта семерка у вас и пошла "на выход" :)

leshak
Offline
Зарегистрирован: 29.09.2011

 И номера пинов лучше было сделать byte. Привыкайте память экономить.

А еще можно повеститься на пины одного порта, например PORTB (52,52,51,50,10,11,12,13)

Тогда можно будет без всяких циклов загать цифру одной коммандой

PORTB=0b11111111 // восьмерка

PORTB=0b11111101 // ноль.

Обязваить что-то типа массив

byte dgs[]={
 0x111111101 // 0
 0x 11011011  // 1
 ... 
 0x 11111111  // 8
};

и зажигать нужную цифру так

PORTB=dgs[0] ; // зажгли 0
PORTB=dgs[1] ; // зажгли 1
....
PORTB=dgs[8] ; // зажгли 8

 

leshak
Offline
Зарегистрирован: 29.09.2011

А если не хочется с прямой записью в порт морочится или хочется сохранить возможность располагать пины как душа пожелает, или просто digitalWrite менее страшным кажется :), то

все-таки объявить dgs[] (сделать маски наших цифр. каждый по одному байту для каждой цифры, каждый бит этого байта означает какой сегменент нужное состояние сегмента)

и написать вашу функцию так:

void seven_seg_digit_out(int pins_array[7], byte digit) {
  for(byte i=7;i>=0;i--)digitalWrite(pins_array[i],bitRead(dgs[digit],i));
}

 Помоему так как-то компактней функция выглядит :)

uscr
Offline
Зарегистрирован: 17.08.2012

leshak пишет:

 ПОтому что в строке 49 вы вообще выпрыгнули за границы массива. Элемента pins_array[7] - не существует. То есть вы взяли случайное значение из памяти, посчитали его пином и включили этот пин.

Следующим, после массива, в памяти оказался "int ind_pins_count = 7;"

Вот эта семерка у вас и пошла "на выход" :)

 

Спасибо. Глупая ошибка :)