2

我有一个 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 上至少会显示三个乱码。

4

4 回答 4

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 上运行的函数与在 RAM 上运行的函数的一般约定。

所有这些以及更多在这里都得到了很好的解释。我还建议您尝试AVR Freaks论坛来解决这类问题。那里的人在这些问题上肯定会比 Stack Overflow 用户更有经验,并且总是乐于提供帮助。

于 2010-11-26T14:42:23.153 回答
1

我看不出您的代码有任何明显错误(不是说我知道如何与 Atmega32 交谈)。尝试在调试器下运行它并c在每次调用时打印到send_char,或者只是将printf("%d\n", (int)c);第一行放在send_char.

于 2010-11-23T19:21:32.143 回答
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()调用之后插入,看看它是否会改变您正在观察的行为。

于 2010-11-23T19:29:03.487 回答
1

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

第一个必须通过 PROGMEM 从以下位置将文字添加到 ROM <avr/pgmspace.h>

const char msg[] PROGMEM = "Test";

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

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

现在send_string(msg)可以按预期使用..

于 2010-11-23T20:58:46.927 回答