Как я могу правильно вызвать функцию lcd.begin() из нескольких разных файлов кода?

У меня есть проект, разделенный на несколько файлов:

//Loop.cpp
#include "LiquidCrystal.h"

void setup(){
    LiquidCrystal lcd(12, 11, 5, 4, 3, 2);  
    lcd.begin(16, 2);  
}

void loop() {
//Code
}
//Display.cpp
#include "LiquidCrystal.h"

namespace display {
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void displayData(const InputPacket &inputPacket, const DataPacket &dataPacket) {
    lcd.setCursor(0,1);
    lcd.print("Foo");    //Это создает ошибку отображения, если только я не вызову lcd.begin(16, 2) в этой функции
}

} //namespace display

Моя первоначальная проблема заключается в том, что - без вызова функции lcd.begin() из функции displayData() - символы отображаются неправильно. Другими словами, вызов функции lcd.begin() в setup() не помогает. (Мне кажется, что setup() имеет неявное статическое свойство, не так ли?)

В качестве попытки решения я мог бы создать жидкокристаллический объект в Display.cpp, и вызовите lcd.begin() из displayData(). Даже если символы отображаются правильно, это дает мне мерцание дисплея. (Предположительно в результате повторного вызова этих функций в цикле во время выполнения).

Таким образом, единственное решение этой дилеммы, которое я могу придумать, - это вызвать lcd.begin() из функции, написанной для запуска только один раз внутри displayData(). Или это так?

Мой вопрос в том, есть ли другие более элегантные решения/альтернативы?

, 👍0


1 ответ


Лучший ответ:

2

Объект под названием lcd, который вы создаете внутри функции setup, является локальной переменной. Он живет только до тех пор, пока эта функция выполняется - так что не очень долго. Оно не существует вне этой функции.

ЖК-объект, который у вас есть в пространстве имен, с другой стороны, является глобальной переменной. Этот живет до тех пор, пока ваша программа, что означает, пока вы не сбросите свой Arduino здесь. (Это совершенно не связано с объектом внутри установки.)

Если вы хотите, чтобы весь ваш ЖК-код был сгруппирован внутри пространства имен дисплея, вы можете сделать это в Display.cpp:

namespace display {
  // Это глобальная переменная, полное имя `display::lcd`
  LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

  void setup() {
    // этот `жк-дисплей` относится к глобальному `дисплею::lcd`, определенному выше
    lcd.begin(16, 2);
  }

  // остальные функции дисплея
}

Создайте файл Display.h, чтобы предоставить прототипы для модуля отображения:

#ifndef DISPLAY_H
#define DISPLAY_H

// Include заголовок, определяющий InputPacket и DataPacket здесь

namespace display
{
void setup();
void displayData(const InputPacket &inputPacket, const DataPacket &dataPacket);
}

#endif

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

#include "Display.h" // нет необходимости включать LiquidCrystal.h, если все
                               // Обработка жидкокристаллического дисплея производится в Display.cpp
void setup(){
  // Initialize display
  display::setup();
}
,

Потрясающе, спасибо. Ваш ответ дал мне много интересного для размышления!, @Erik