我有一个 LCD,连接到 Atmega32,使用此函数处理单个字符:
void send_char(uint8_t c){
PORTD = c; // set the output pins to the ascii value of the char
PORTB |= 0x05;
_delay_us(1);
PORTB &= 0xfa;
_delay_us(60);
PORTD = 0x00;
update_cursor();
}
我可以用一个字符作为参数来调用它:send_char('a');
并且它可以工作。
然后我尝试在它周围包装一个 send_string 函数:
void send_string(const char * msg){
while (*msg != '\0'){
send_char(*msg++);
}
}
这只会在我的 LCD 上显示乱码,表明 ASCII 值相差很远。当我尝试传递一个空字符串 (send_string("")
) 时,LCD 上会显示至少三个乱码字符。
最佳答案
首先,您似乎正在使用 avr-gcc 编译器。在提出有关嵌入式设备的问题时,您始终需要说明您正在使用哪个编译器。
我现在将尝试帮助您了解您的代码有什么问题以及您的解决方案为何有效。您定义的函数:
void send_string(const char * msg);
需要 RAM 中的字符串指针。即使您使用了 const 关键字,编译器仍然希望字符串位于 RAM 中。因此,如果 ROM 中有一个字符串:
const char msg[] PROGMEM = "Test";
并且您尝试将其传递到您的函数中:
send_string(msg);
它只是向其传递了一个无效地址,因此会显示乱码。如果您首先将其复制到 RAM,就像您在解决方案中所做的那样,它可以正常工作:
char buf[strlen(msg)];
strcpy_P(buf,msg);
send_string(buf);
如果你想定义一个直接读取ROM字符串的函数,你可以这样做:
void send_string_P(const char *data)
{
while (pgm_read_byte(data) != 0x00)
send_char(pgm_read_byte(data++));
}
注意 _P
后缀。这是用于区分在 ROM 上运行的函数与在 RAM 上运行的函数的一般约定。
所有这些以及更多内容都得到了很好的解释 here 。我还建议您尝试 AVR Freaks 此类问题的论坛。那里的人们在这些问题上肯定比 Stack Overflow 用户更有经验,并且总是很乐意提供帮助。
关于c - 使用 ATmega32 在 LCD 上显示数组中的 ASCII 字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4259819/