我有一台连接到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("")
)时,液晶显示屏上会显示至少三个乱码。
答案 0 :(得分:3)
首先,您似乎正在使用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上运行的不同函数的通用约定。
所有这些以及更多内容都得到了很好的解释here。我还建议你尝试 AVR Freaks 论坛来解决这些问题。那些人在这些问题上肯定比Stack Overflow用户更有经验,并且总是很乐意提供帮助。
答案 1 :(得分:1)
我没有看到任何明显错误的代码(不是我知道如何与Atmega32交谈)。尝试在调试器下运行它,并在每次调用c
时打印send_char
,或者只将printf("%d\n", (int)c);
作为send_char
的第一行。
答案 2 :(得分:1)
这对我有用:
#include <stdio.h>
#include <stdint.h>
void send_char(uint8_t c)
{
printf("%c", c);
}
void send_string(const char * msg)
{
while (*msg != '\0')
{
send_char(*msg++);
}
}
int main()
{
send_string("Stackoverflow!");
return 0;
}
在您的代码中,在sleep(1);
调用后插入send_char()
,看看它是否会改变您正在观察的行为。
答案 3 :(得分:1)
这适用于我的Atmel控制器(虽然我不知道为什么):
首先必须通过来自<avr/pgmspace.h>
的PROGMEM将文字添加到ROM中:
const char msg[] PROGMEM = "Test";
然后将文字复制到控制器RAM中的缓冲区:
char buf[strlen(msg)];
strcpy_P(buf,msg);
现在可以按预期使用send_string(msg)
..