Serial.print печатает, а lcd.print - нет.

Следующий код считывает текстовый файл с SD-карты, находит соответствующий символ и печатает следующие 12 символов:

...
      char temp;
      byte who = random(1, 13); // 1 to 12
      temp = findName(who);
      Serial.print(who);
      Serial.print("  ==> ");
      Serial.println(temp);
...

    char findName (byte number) {
      char text[12];
      byte i;
      txt = SD.open("test.txt");
      txt.seek(12 * (number - 1));
      for (i = 0; i < 11; i++) text[i] = txt.read();
      txt.close();
      return text;
    }

А вот следующее на ЖК-дисплее этого не делает. (setCursor и т. д. опущены для ясности)

...
char temp;
byte who = random(1, 13); // от 1 до 12
temp = findName(who);
lcd.print(who);
lcd.print("  ==> ");
lcd.print(temp);
...

Я уверен, что причина в несоответствии типа данных переменной, но не знаю, как ее решить. Любая помощь приветствуется.

Спасибо.

, 👍0

Обсуждение

что такое переменная lcd, @Jaromanda X

Как узнать, что ваш ЖК-дисплей работает? ... запустите пример эскиза ЖК-дисплея в Arduino IDE, чтобы убедиться, @jsotola

ЖК-дисплей работает. Переменная представляет собой массив символов, созданный функцией findName()., @ghpg2

Тип lcd и библиотека?, @Juraj

Переменная представляет собой массив символов ... так зачем же массиву символов иметь метод print?, @Jaromanda X

Юрай, обычный символьный ЖК на шине i2c, библиотека LiquidCrystal_I2C.h. Джароманда X, мне следует преобразовать его в строку? Если да, то как? Спасибо., @ghpg2


1 ответ


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

0

В функции findName() вы объявляете массив символов с именем text. Внутренне text является указателем на блок памяти размером 12 байт.

Когда вы возвращаете текст внутри функции findName(), вы передаете обратно указатель на блок памяти. Тип возвращаемого значения char несовместим с командой возврата. Но, вероятно, более проблематичным является то, что после завершения findName() память, выделенная для массива text, помечается как неиспользуемая. Он больше не зарезервирован для хранения чего-либо и может быть перераспределен в любое время с помощью какой-либо другой функции или операции.

В C/C++ переменные массива относятся не ко всему массиву, а к первому элементу массива. Тот факт, что ваша программа работает с Serial.print(), вероятно, просто удача. lcd.print() может объявлять некоторую переменную или буфер, которые перезаписывают то, что функция findName() поместила в эти 12 байтов.

Чтобы решить эту проблему, можно использовать множество подходов. Один из способов — объявить массивы символов в «самой высокой» области видимости, в которой они будут использоваться, и объявить их с самым большим размером, который вы когда-либо видели в работе вашей программы.

В вашем случае вы можете:

...
      char temp[12];
      byte who = random(1, 13); // от 1 до 12
      findName(temp, who);
      Serial.print(who);
      Serial.print("  ==> ");
      Serial.println(temp);
...

    void findName (char *text, byte number) {
      byte i;
      txt = SD.open("test.txt");
      txt.seek(12 * (number - 1));
      for (i = 0; i < 11; i++) text[i] = txt.read();
      txt.close();
    }

Что это делает:

  1. temp теперь представляет собой массив символов
  2. findName() принимает указатель на массив символов и число в качестве аргументов.
  3. findName() изменяет text, который ссылается на тот же блок уже выделенной памяти, что и temp, и этот блок памяти не исчезать в конце findName().
  4. Поскольку findName() не возвращает значение, тип возвращаемого значения — void.
,

Спасибо, сэр! Многому научился из вашего ответа, и ваш фрагмент наконец решил проблему. Теперь я наконец могу продолжить. Еще раз спасибо., @ghpg2