Пролистывающая текстовая программа Arduino через некоторое время зависает - PullRequest
0 голосов
/ 23 января 2019

Я использую 16x2 символьный ЖК-дисплей для отображения текста. Я хочу, чтобы первая строка была фиксированной, а вторая - прокручиваемой.

Я написал программу, которая работает нормально, но проблема в том, что через некоторое время Arduino не отвечает. Я подозреваю, что в коде может быть ошибка или утечка памяти.

Соответствующий код выглядит следующим образом.

void scrollTextFromRight(int line, char text[])
{
    const char space[16] = "                ";
    char screen[16];
    char * longText;

    longText = malloc(sizeof(char) * (sizeof(text) + 17));

    memset(longText, '\0', sizeof(char) * (sizeof(text) + 17));
    memset(screen, '\0', sizeof(screen));

    for (int i = 0; i < 16; ++i)
    {
        longText[i] = space[i];
    }

    for (int j = 0; j < sizeof(text) + 17; ++j)
    {
        longText[16+j] = text[j];
    }


    for (int i = 0; i < sizeof(text) + 17; ++i)
    {

        lcd.setCursor(0, line);
        strncpy(screen, longText + i, 17 );
        lcd.print(screen);
        delay(350);
    }
}

Я вызываю эту функцию из основной программы следующим образом:

scrollTextFromRight(1, "Scrolling text");

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

Я добавил эту часть после третьего цикла for.

free longText;

Обновление 2:
После прочтения комментариев я решил использовать класс Arduino String. Код стал таким:

void scrollTextFromRight(int line, String text)
{
    const String space = "                ";
    const String longText = space + text + ' ';
    int displaySize = 16;

    for (int i = 0; i <= longText.length(); ++i)
    {
        lcd.setCursor(0, line);
        String display = longText.substring(i, i + displaySize);
        lcd.print(display);
        delay(350);
    }
}

1 Ответ

0 голосов
/ 23 января 2019

Когда вы объявляете аргумент как char text[], компилятор переводит его как char* text.То есть это указатель.

И получение размера указателя (например, sizeof(text)) дает вам размер указателя , а не то, на что он указывает.Если это байтовая строка с нулевым символом в конце, тогда используйте strlen, чтобы получить длину (но учтите, что нулевой терминатор не учитывается).

Или, что еще лучше, прекратите использовать строки Cи функции, потому что Arduino фактически запрограммирован на C ++ и имеет собственный стандартный класс String, который должен использоваться для всех строк.


Также обратите внимание, что

const char space[16] = "                ";

создает массив из 16 элементов и устанавливает для всех этих элементов символ пробела ' '. Но это не строка с нулевым символом в конце, потому что терминатор не помещается в массив.

Вы также знаете о функции memset, но, кажется,забыть функцию memcpy при копировании из ваших массивов.

Вместо явного циклического копирования из space, вы можете просто сделать

memcpy(longText, space, sizeof space);  // Using sizeof since space is not null-terminated

Наконец, будьте осторожны сstrncpy функция может не завершать строку назначения нулем.

...