2

この関数を使用して単一の文字を操作する Atmega32 に接続された LCD があります。

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++);
    }
}

これは、ASCII 値が大きくずれていることを示す意味不明なメッセージを LCD に表示するだけです。また、空の文字列 ( send_string("")) を渡そうとすると、少なくとも 3 つの意味不明な文字が 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で動作する機能を区別するために使用される一般的な規則です。

これらすべてとそれ以上がここでうまく説明されています。また、この種の質問については、 AVRFreaksフォーラムを試してみることをお勧めします。確かに、Stack Overflowユーザーよりもこれらの問題の経験が豊富で、いつでも喜んでお手伝いします。

于 2010-11-26T14:42:23.153 に答える
1

あなたのコードに明らかに問題があるとは思いません (Atmega32 との対話方法を知っているわけではありません)。デバッガーの下で実行してみて、 をc呼び出すたびに出力するsend_charprintf("%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 に答える