在 LCD 上显示整数
Displaying integer on an LCD
我正在尝试在 LCD 显示器上显示一个整数。 Lcd 的工作方式是您向它发送一个 8 位 ASCII 字符并显示该字符。
我目前的代码是:
unsigned char text[17] = "ABCDEFGHIJKLMNOP";
int32_t n = 123456;
lcd.printInteger(text, n);
//-----------------------------------------
void LCD::printInteger(unsigned char headLine[17], int32_t number)
{
//......
int8_t str[17];
itoa(number,(char*)str,10);
for(int i = 0; i < 16; i++)
{
if(str[i] == 0x0)
break;
this->sendCharacter(str[i]);
_delay_ms(2);
}
}
void LCD::sendCharacter(uint8_t character)
{
//....
*this->cOutputPort = character;
//...
}
所以如果我尝试在 LCD 上显示 123456
,它实际上显示 -7616
,这显然不是正确的整数。
我知道可能有问题,因为我将字符转换为有符号int8_t
,然后将它们输出为无符号uint8_t
。但我必须以无符号格式输出它们。我不知道如何将 int32_t
输入整数转换为 ASCII uint8_t
-String.
在您的体系结构中,int
是 int16_t
,而不是 int32_t
。因此,itoa
将 123456
视为 -7616
,因为:
123456 = 0x0001_E240
-7616 = 0xFFFF_E240
如果将它们截断为 16 位,它们是相同的 - 这就是您的代码所做的。除了使用 itoa
,您还有以下选项:
- 自己计算 ASCII 表示;
- 使用
ltoa(long value, char * buffer, int radix)
,如果可用,或
- 杠杆
s[n]printf
如果可用。
对于最后一个选项,您可以使用以下 "mostly" 可移植代码:
void LCD::printInteger(unsigned char headLine[17], int32_t number) {
...
char str[17];
if (sizeof(int) == sizeof(int32_t))
snprintf(str, sizeof(str), "%d", num);
else if (sizeof(long int) == sizeof(int32_t))
snprintf(str, sizeof(str), "%ld", num);
else if (sizeof(long long int) == sizeof(int32_t))
snprintf(str, sizeof(str), "%lld", num);
...
}
当且仅当您的平台没有 snprintf
时,您可以使用 sprintf
并删除第二个参数 (sizeof(str)
)。您的 go-to 函数应该始终是 n
变体,因为它可以让您少用一颗子弹来射击您的脚:)
由于您正在使用 C++ 编译器进行编译,我假设至少 half-decent,以上代码应该以可移植的方式执行 "the right thing",而不会发出所有不必要的代码。传递给 if
的测试条件是 compile-time 常量表达式。即使是一些相当老的 C 编译器也可以正确处理。
吹毛求疵:不要在 char
可以使用的地方使用 int8_t
。 itoa
、s[n]printf
等需要 char
个缓冲区,而不是 int8_t
个缓冲区。
我正在尝试在 LCD 显示器上显示一个整数。 Lcd 的工作方式是您向它发送一个 8 位 ASCII 字符并显示该字符。
我目前的代码是:
unsigned char text[17] = "ABCDEFGHIJKLMNOP";
int32_t n = 123456;
lcd.printInteger(text, n);
//-----------------------------------------
void LCD::printInteger(unsigned char headLine[17], int32_t number)
{
//......
int8_t str[17];
itoa(number,(char*)str,10);
for(int i = 0; i < 16; i++)
{
if(str[i] == 0x0)
break;
this->sendCharacter(str[i]);
_delay_ms(2);
}
}
void LCD::sendCharacter(uint8_t character)
{
//....
*this->cOutputPort = character;
//...
}
所以如果我尝试在 LCD 上显示 123456
,它实际上显示 -7616
,这显然不是正确的整数。
我知道可能有问题,因为我将字符转换为有符号int8_t
,然后将它们输出为无符号uint8_t
。但我必须以无符号格式输出它们。我不知道如何将 int32_t
输入整数转换为 ASCII uint8_t
-String.
在您的体系结构中,int
是 int16_t
,而不是 int32_t
。因此,itoa
将 123456
视为 -7616
,因为:
123456 = 0x0001_E240
-7616 = 0xFFFF_E240
如果将它们截断为 16 位,它们是相同的 - 这就是您的代码所做的。除了使用 itoa
,您还有以下选项:
- 自己计算 ASCII 表示;
- 使用
ltoa(long value, char * buffer, int radix)
,如果可用,或 - 杠杆
s[n]printf
如果可用。
对于最后一个选项,您可以使用以下 "mostly" 可移植代码:
void LCD::printInteger(unsigned char headLine[17], int32_t number) {
...
char str[17];
if (sizeof(int) == sizeof(int32_t))
snprintf(str, sizeof(str), "%d", num);
else if (sizeof(long int) == sizeof(int32_t))
snprintf(str, sizeof(str), "%ld", num);
else if (sizeof(long long int) == sizeof(int32_t))
snprintf(str, sizeof(str), "%lld", num);
...
}
当且仅当您的平台没有 snprintf
时,您可以使用 sprintf
并删除第二个参数 (sizeof(str)
)。您的 go-to 函数应该始终是 n
变体,因为它可以让您少用一颗子弹来射击您的脚:)
由于您正在使用 C++ 编译器进行编译,我假设至少 half-decent,以上代码应该以可移植的方式执行 "the right thing",而不会发出所有不必要的代码。传递给 if
的测试条件是 compile-time 常量表达式。即使是一些相当老的 C 编译器也可以正确处理。
吹毛求疵:不要在 char
可以使用的地方使用 int8_t
。 itoa
、s[n]printf
等需要 char
个缓冲区,而不是 int8_t
个缓冲区。