使用 ATmega32 在 LCD 上显示数组中的 ASCII 字符

发布于 2024-10-04 09:42:48 字数 610 浏览 4 评论 0原文

我有一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦情居士 2024-10-11 09:42:48

首先,您似乎正在使用 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 上运行的函数的一般约定。

所有这些以及更多内容都在此处得到了很好的解释。我还建议您尝试访问 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:

void send_string(const char * msg);

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:

const char msg[] PROGMEM = "Test";

and you try to pass it in your function:

send_string(msg);

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:

char buf[strlen(msg)];
strcpy_P(buf,msg);
send_string(buf);

If you want to define a function that will directly read a ROM string, you can do it like this:

void send_string_P(const char *data)
{
    while (pgm_read_byte(data) != 0x00)
        send_char(pgm_read_byte(data++));
} 

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.

阳光下的泡沫是彩色的 2024-10-11 09:42:48

我没有发现您的代码有任何明显的错误(并不是说我知道如何与 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 to send_char, or just put printf("%d\n", (int)c); as the first line to send_char.

梦里梦着梦中梦 2024-10-11 09:42:48

这对我有用:

#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;
}

在您的代码中,在 send_char() 调用之后插入 sleep(1); ,看看它是否会改变您正在观察的行为。

This works for me:

#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;
}

In your code, insert sleep(1); after the send_char() call and see if it changes the behavior you are observing.

两个我 2024-10-11 09:42:48

这适用于我的 Atmel 控制器(虽然我不知道为什么):

第一个必须通过 PROGMEM 从 将文字添加到 ROM:

const char msg[] PROGMEM = "Test";

然后将文字复制到控制器 RAM 中的缓冲区:

char buf[strlen(msg)];
strcpy_P(buf,msg);

现在可以按预期使用 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>:

const char msg[] PROGMEM = "Test";

Then copy the literal to a buffer in the controller's RAM:

char buf[strlen(msg)];
strcpy_P(buf,msg);

Now send_string(msg) can be used as expected..

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文