Замена нескольких выводов pinMode() и digitalWrite() на массив

Я хотел бы «очистить» код, который включает несколько строк pinMode() и digitalWrite(), используя одну строку массива. Я новичок в обоих массивах, поэтому немного запутался. Следующие примеры — это разделы кода, который управляет 4-разрядным 7-сегментным светодиодом.

// Define display pins
// Digit pins (common cathode)
int digit1 = 13; //Display pin 1
int digit2 = 12; //Display pin 2
int digit3 = 11; //Display pin 6
int digit4 = 10; //Display pin 8
// Segment pins
int segA = 2; //Display pin 14
int segB = 3; //Display pin 16
int segC = 4; //Display pin 13
int segD = 5; //Display pin 3
int segE = 6; //Display pin 5
int segF = 7; //Display pin 11
int segG = 8; //Display pin 15

void setup() {                
  pinMode(segA, OUTPUT);
  pinMode(segB, OUTPUT);
  pinMode(segC, OUTPUT);
  pinMode(segD, OUTPUT);
  pinMode(segE, OUTPUT);
  pinMode(segF, OUTPUT);
  pinMode(segG, OUTPUT);

  pinMode(digit1, OUTPUT);
  pinMode(digit2, OUTPUT);
  pinMode(digit3, OUTPUT);
  pinMode(digit4, OUTPUT);
}

#define SEGMENT_ON  LOW
#define SEGMENT_OFF HIGH

  switch (numberToDisplay){

  case 0:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_OFF);
    break;

Определение пинов:

Я почти уверен, что приведенный ниже код — правильный способ сохранения контактов в виде массива (но, пожалуйста, поправьте меня, если я ошибаюсь).

digitPins[] = {13 12 11 10};
segPins[] = {2 3 4 5 6 7 8};

pinMode():

Я понимаю, что могу использовать цикл for для установки режимов выводов, но есть ли еще более простой способ? Будет ли работать что-то вроде этого?

pinMode(digitPins[], OUTPUT);
pinMode(segPins[], OUTPUT);

digitalWrite():

Я мог бы получить доступ к соответствующему пину из массива для использования в digitalWrite(), как в коде ниже, но это привело бы к тому же количеству строк кода (и было бы еще более запутанным). Есть ли другой вариант?

digitalWrite(segPins[1], HIGH);

, 👍7

Обсуждение

Некоторые соответствующие вопросы: [Подключение клавиатуры к Arduino с 7 -сегментным дисплеем](https://arduinoprosto.ru/q/30222/interfacing-key-pad-with-arduino-with-7-segment-display) и [код 7-сегментного дисплея](https://arduinoprosto.ru/q/29159/7-segment-display-code)., @gre_gor

Поскольку речь идет о 4-разрядном 7-сегментном дисплее, наиболее уместным вопросом для проверки, вероятно, будет: [Как использовать 7-сегментный 4-разрядный дисплей с общим анодом?](http://arduinoprosto.ru/q/21608)., @Edgar Bonet


4 ответа


3

[ДОПОЛНИТЕЛЬНЫЙ КОД и ОБЪЯСНЕНИЕ КОДА]

Это функция, которая используется в ссылке, размещенной в комментариях:

void number(int num)                        //num — это число для отображения
{
  for(int i=0; i<7; i++)                    //проходим 7 сегментов (7 светодиодов)
  {
    digitalWrite(segment[i], nums[num][i]); //сообщить arduino включить или выключить какой светодиод
  }
}

Это здорово, потому что вы можете воспользоваться им, позвонив:

number(/*the number you want to display*/);

Использование цикла for позволит избежать копирования и вставки кучи вещей. Это также позволяет вам сэкономить много памяти.

Затем, чтобы отобразить небольшой таймер от 0 до 9, вы можете сделать следующее:

for(int i=0; i<10; i++)
{
  number(i);            //отобразить число
  delay(1000);          //ждем 1сек
}

[ОРИГИНАЛЬНЫЙ ОТВЕТ]

Используйте массив и цикл for.

int segments = {2,3,4,5,6,7,8}; //объявление пинов

void setup() {
  for(int i=0;i<8;i++)
  {
    pinMode(segments[i], OUTPUT); //объявляем их как выходы
  }
}

Это очень полезно. Сделайте то же самое и для цифр.

Этот метод работает во многих случаях:

  • много датчиков, переключателей
  • множество выходов, таких как светодиоды, реле, транзисторы
,

7

правильный способ хранения пинов в виде массива

Ваши инициализаторы массива почти верны; вам просто нужно разделить значения запятыми:

digitPins[] = {13, 12, 11, 10};
segPins[] = {2, 3, 4, 5, 6, 7, 8};

Вам нужно будет вызвать pinMode() в цикле; он не принимает массивы в качестве аргументов.

А как насчет digitalWrite(), где это смесь HIGH и LOW?

Есть (как минимум) два способа: создать массивы значений HIGH и LOW, сопоставляя массивы digitPins[] и segPins[] один к одному соответственно. Или для более простого обслуживания объявите структуру данных (struct) номера контакта и значения; создайте из них массив. Это немного сложнее, но и полезнее. Например:

typedef struct {
    uint8_t pinNum;
    bool pinVal;
} pinInit_t;

pinInit_t digitPins[] {
    {13, HIGH},
    {12, LOW},
    {11, LOW},
    {10, HIGH}
};

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}

struct — это сокращение от «data structure» (структура данных); оно позволяет объединять данные разных типов в одну именованную и адресуемую единицу. typedef объявляет новый тип данных и сообщает: «Не выделяйте сейчас память; это (pinInit) — всего лишь описание. Я воспользуюсь им позже». Это делает pinInit именованным типом данных, пригодным для использования везде, где можно использовать собственный тип данных И допустим многозначный тип данных (например, массив).

Таким образом, мы можем создать массив pinInit (пары номер вывода / логическое значение), просто используя имя нового типа.

Тогда ваш инициализирующий код может выглядеть так:

uint8_t i;
for( i = 0; i < sizeof(digitPins)/sizeof(pinInit_t); ++i ){
   pinMode(digitPins[i].pinNum, OUTPUT);
   digitalWrite(digitPins[i].pinNum, digitPins[i].pinVal);
}

Выражение sizeof(digitPins)/sizeof(pinInit) вычисляет количество инициализаторов (количество байтов в массиве / количество байтов в одном элементе массива).

Выражение digitPins[i].pinNum означает: «в массиве pinInit digitPins получить i-й элемент...» (помните, это пара значений), «... и взять значение члена «pinNum». Немного сложнее, на первый взгляд, но посмотрите, как легко читается массив. И подсказка о чтении этого выражения: я прочитал его наоборот: «член pinNum i-го элемента массива digitPins».

Завтра или в следующем месяце, когда нам понадобится еще один пин-код, не нужно обновлять 2 массива (конечно, не забывая сохранять их последовательность друг с другом!); просто добавьте еще один двузначный элемент в массив digitPins[].

,

0

Использование пользовательского метода

Использованная ссылка: https://stackoverflow.com/a/33235154/5500092

Вы можете использовать такой пользовательский метод:

template<size_t size>
void pinMode(const uint8_t (&pin)[size], uint8_t mode) {
    for (size_t i = 0; i < size; ++i) {
        pinMode(pin[i], mode);
    }
}

template<size_t size>
void digitalWrite(const uint8_t (&pin)[size], uint8_t val) {
    for (size_t i = 0; i < size; ++i) {
        digitalWrite(pin[i], val);
    }
}

Затем вы определяете массив с пинами:

uint8_t displayPins[4] = {13, 12, 11, 10};
uint8_t segmentPins[7] = {2, 3, 4, 5, 6, 7, 8};

И наконец, в вашей настройке используйте:

void setup() {                
    pinMode(displayPins, OUTPUT);
    pinMode(segmentPins, OUTPUT);
}

void loop() {
    // Ваша логика с digitalWrite.
}

Ваша логика

P.S.: Для вашей логики вы даже можете использовать:

template<size_t size>
void digitalWrite(const uint8_t (&pin)[size], const uint8_t (&val)[size]) {
    for (size_t i = 0; i < size; ++i) {
        digitalWrite(pin[i], val[i]);
    }
}

И определить для каждого номера сегмента массив пользовательских значений.

uint8_t zero[7] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, LOW};
...

Или даже:

uint8_t segment[][7] = {{HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, LOW }, // 0
                        {____, ____, ____, ____, ____, ____, ____}, // 1
                        {____, ____, ____, ____, ____, ____, ____}, // 2
                        ...
                        {____, ____, ____, ____, ____, ____, ____}}; // F

И используйте:

digitalWrite(segmentPins, segment[5]); // print 5
,

-4
func(){ 
   boolean pins[] ={ 1,1,1,1,1,1,0};
   for(int i=0; i<7;i++)`
   digitalWrite(segPins[i], pins[i]);
}

вот и все :)

,