Arduino 滚动文本程序在一段时间后冻结
Arduino scrolling text program freeze after some time
我使用 16x2 字符 LCD 来显示一些文本。我想要的是第一行是固定的,第二行是滚动的。
我编写了一个运行良好的程序,但问题是一段时间后 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, '[=10=]', sizeof(char) * (sizeof(text) + 17));
memset(screen, '[=10=]', 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:
阅读评论和答案后,我用 free 函数释放了分配的内存 space。我上传了新代码并测试它是否按预期工作。
我在第三个for循环之后添加了这部分。
free longText;
更新 2:
阅读评论后,我决定使用 Arduino 的 String class。代码变成了这样:
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);
}
}
当您将参数声明为 char text[]
时,编译器会将其翻译为 char* text
。也就是说,它是一个指针。
获取指针的大小(例如 sizeof(text)
)可以得到 指针 的大小,而不是它指向的任何内容。如果是空终止字节串,则使用strlen
获取长度(但注意空终止符不算)。
或者更好的是,停止使用 C 字符串和函数,因为 Arduino 实际上是用 C++ 编程的,并且有自己的标准 String
class 应该用于所有字符串。
另请注意
const char space[16] = " ";
创建一个包含 16 个元素的数组,并将所有这些元素设置为 space 字符 ' '
。 但是它不是以 null 结尾的字符串,因为终止符不适合数组。
您也知道 memset
函数,但是当您从数组中复制时,似乎忘记了 memcpy
函数。
而不是显式循环从 space
复制,你可以简单地做
memcpy(longText, space, sizeof space); // Using sizeof since space is not null-terminated
最后,注意 strncpy
函数,它可能不会以 null 终止目标字符串。
我使用 16x2 字符 LCD 来显示一些文本。我想要的是第一行是固定的,第二行是滚动的。
我编写了一个运行良好的程序,但问题是一段时间后 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, '[=10=]', sizeof(char) * (sizeof(text) + 17));
memset(screen, '[=10=]', 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:
阅读评论和答案后,我用 free 函数释放了分配的内存 space。我上传了新代码并测试它是否按预期工作。
我在第三个for循环之后添加了这部分。
free longText;
更新 2:
阅读评论后,我决定使用 Arduino 的 String class。代码变成了这样:
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);
}
}
当您将参数声明为 char text[]
时,编译器会将其翻译为 char* text
。也就是说,它是一个指针。
获取指针的大小(例如 sizeof(text)
)可以得到 指针 的大小,而不是它指向的任何内容。如果是空终止字节串,则使用strlen
获取长度(但注意空终止符不算)。
或者更好的是,停止使用 C 字符串和函数,因为 Arduino 实际上是用 C++ 编程的,并且有自己的标准 String
class 应该用于所有字符串。
另请注意
const char space[16] = " ";
创建一个包含 16 个元素的数组,并将所有这些元素设置为 space 字符 ' '
。 但是它不是以 null 结尾的字符串,因为终止符不适合数组。
您也知道 memset
函数,但是当您从数组中复制时,似乎忘记了 memcpy
函数。
而不是显式循环从 space
复制,你可以简单地做
memcpy(longText, space, sizeof space); // Using sizeof since space is not null-terminated
最后,注意 strncpy
函数,它可能不会以 null 终止目标字符串。