Замена нескольких выводов 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);
@zdub, 👍7
Обсуждение4 ответа
[ДОПОЛНИТЕЛЬНЫЙ КОД и ОБЪЯСНЕНИЕ КОДА]
Это функция, которая используется в ссылке, размещенной в комментариях:
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); //объявляем их как выходы
}
}
Это очень полезно. Сделайте то же самое и для цифр.
Этот метод работает во многих случаях:
- много датчиков, переключателей
- множество выходов, таких как светодиоды, реле, транзисторы
правильный способ хранения пинов в виде массива
Ваши инициализаторы массива почти верны; вам просто нужно разделить значения запятыми:
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[].
Использование пользовательского метода
Использованная ссылка: 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
func(){
boolean pins[] ={ 1,1,1,1,1,1,0};
for(int i=0; i<7;i++)`
digitalWrite(segPins[i], pins[i]);
}
вот и все :)
- Работает ли конструкция int array[100] = {0} на Arduino?
- Массив динамического размера в качестве члена класса
- Итерация массива объектов
- Как получить размер (sizeof) массива структур
- Работает с gcc, но не с Arduino. ошибка: taking address of temporary array
- Безопасно ли использовать std::array (из C++ STL) на Arduino? Использует ли он динамическое выделение памяти?
- Есть ли ограничения на размер массива в Arduino Mega 2560?
- Как масштабировать растровое изображение (массив uint8_t) в Arduino?
Некоторые соответствующие вопросы: [Подключение клавиатуры к 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