使用 ATmega32 在 LCD 上显示数组中的 ASCII 字符
我有一个 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 上会显示至少三个乱码。
I've got an LCD, connected to an Atmega32, working with single characters using this function:
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();
}
I can call this with a character as an argument: send_char('a');
and it works.
Then I tried wrapping a send_string function around it:
void send_string(const char * msg){
while (*msg != '\0'){
send_char(*msg++);
}
}
This just puts gibberish on my LCD indicating that the ASCII value has been far off. And when I try passing an empty string (send_string("")
) a minimum of three gibberish characters get displayed on the LCD.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
首先,您似乎正在使用 avr-gcc 编译器。在提出有关嵌入式设备的问题时,您始终需要说明您正在使用哪个编译器。
我现在将尝试帮助您了解您的代码有什么问题以及您的解决方案为何有效。您定义的函数:
需要 RAM 中的字符串指针。即使您使用了 const 关键字,编译器仍然希望字符串位于 RAM 中。因此,如果 ROM 中有一个字符串:
并且尝试将其传递到函数中:
它只会向其传递无效地址,因此会显示乱码。如果您首先将其复制到 RAM,就像您在解决方案中所做的那样,它可以正常工作:
如果您想定义一个直接读取 ROM 字符串的函数,您可以这样做:
注意
_P 后缀。这是用于区分在 ROM 上运行的函数与在 RAM 上运行的函数的一般约定。
所有这些以及更多内容都在此处得到了很好的解释。我还建议您尝试访问 AVR Freaks 论坛来解答此类问题。那里的人们在这些问题上肯定比 Stack Overflow 用户更有经验,并且总是很乐意提供帮助。
First, it seems that you are using the avr-gcc compiler. When making questions for embedded devices, you always need to say which compiler you are using.
I will now try to help you understand what is wrong with your code and why your solution works. The function you have defined:
expects a string pointer in RAM. It doesn't matter that you have used the
const
keyword, the compiler still expects the string to be in RAM. So if you have a string in ROM:and you try to pass it in your function:
it just passes an invalid address to it and thus gibberish are displayed. If instead you copy it first to RAM, as you did in your solution, it works fine:
If you want to define a function that will directly read a ROM string, you can do it like this:
Notice the
_P
suffix. This is the general convention used to distinct functions that operate on ROM from the ones that operate on RAM.All these and more are nicely explained here. I also suggest that you try the AVR Freaks forum for these kind of questions. People there will be certainly more experienced in these issues than Stack Overflow users and are always happy to help.
我没有发现您的代码有任何明显的错误(并不是说我知道如何与 Atmega32 对话)。尝试在调试器下运行它,并在每次调用
send_char
时打印c
,或者直接输入printf("%d\n", (int)c);
作为send_char
的第一行。I don't see anything obviously wrong with your code (not that I know how to talk to an Atmega32). Try running it under a debugger and print
c
on every invocation tosend_char
, or just putprintf("%d\n", (int)c);
as the first line tosend_char
.这对我有用:
在您的代码中,在
send_char()
调用之后插入sleep(1);
,看看它是否会改变您正在观察的行为。This works for me:
In your code, insert
sleep(1);
after thesend_char()
call and see if it changes the behavior you are observing.这适用于我的 Atmel 控制器(虽然我不知道为什么):
第一个必须通过 PROGMEM 从
将文字添加到 ROM:然后将文字复制到控制器 RAM 中的缓冲区:
现在可以按预期使用
send_string(msg)
。This works on my Atmel controller (although I don't know why):
First one has to add the literal to the ROM via PROGMEM from
<avr/pgmspace.h>
:Then copy the literal to a buffer in the controller's RAM:
Now
send_string(msg)
can be used as expected..