2

構造体を EEPROM に読み書きする組み込みプロジェクトに取り組んでいます。sprintf を使用して、デバッグ情報を簡単に表示できるようにしています。

何らかの理由で、このコードには 2 つの問題があります。最初; sprintf は非常に奇妙な出力を出力しています。「addr++」を印刷すると、意味をなさないパターン「0、1、2、3、4、32、...」に従います。

void ee_read(char * buf, unsigned int addr, unsigned int len) {
    unsigned int i;

    sprintf(bf1, "Starting EEPROM read of %u bytes.\r\n", len); // Debug output
    debugr(bf1);

    IdleI2C1();
    StartI2C1();
    WriteI2C1(EE_ADDR | EE_W);
    IdleI2C1();
    WriteI2C1((unsigned char)addr>>8); // Address to start reading data from
    IdleI2C1();
    WriteI2C1((unsigned char)addr&0xFF);
    IdleI2C1();
    RestartI2C1();
    WriteI2C1(EE_ADDR | EE_R);
    IdleI2C1();
    for (i=0; i<len; i++) {
        buf[i] = ReadI2C1(); // Read a byte from EEPROM

        sprintf(bf1, "Addr: %u Byte: %c\r\n", addr, buf[i]); // Display the read byte and the address
        debugr(bf1);

        addr++; // Increment address

        IdleI2C1();
        if (i == len-1) { // This makes sure the last byte gets 'nAcked'
            NotAckI2C1();
        } else {
            AckI2C1();
        }
    }
    StopI2C1();
}

上記の出力は次のとおりです: https://gist.github.com/3803316 about 出力は、アドレス値の %x で取得されたことに注意してください (したがって、addr は 16 進数です)。

出力で気付いたかもしれない 2 番目の問題は、i > len のときに停止しないことです。それは私が提供した出力よりもさらに続き、マイクロコントローラのウォッチドッグが再起動するまで停止しません。

編集: 関数の呼び出し

Location loc;
ee_read(&loc, 0, sizeof(Location));

宣言:

struct location_struct {
    char lat[12]; // ddmm.mmmmmm
    char latd[2]; // n/s
    char lon[13]; // dddmm.mmmmmm
    char lond[2]; // e/w
    char utc[11]; // hhmmss.sss
    char fix[2]; // a/v
};

typedef struct location_struct Location;

char bf1[BUFFER_SIZE];

競合状態ではないと思います。bf1 を使用する割り込みを無効にします。それでも、それが発生した場合、デバッグ文字列全体が破損し、確かに再現性が低くなります。

編集 addr の値はゼロから始まります。これは次の場所で確認できます: https://gist.github.com/3803411

編集 これが行うことになっていることは、ロケーション構造をバイトごとに EEPROM にコピーし、必要なときにそれを呼び出すことです。

閉鎖 だから、私はこの問題を決して解決しませんでした。プロジェクトは EEPROM から離れ、OS、コンパイラ、IDE を変更しました。この問題を再現する可能性は低いです。

4

1 に答える 1

1

私はあなたのコードに1つの問題があることを伝えます。この行です:

(unsigned char)addr>>8

あなたが必要と思われることをしません。

addr値をunsigned charwhichに変換します(8 ビットcharと 16 ビットのいずれか、intまたはより広い の下位 16 ビットのみを使用すると仮定int) は、常に下位 8 ビットを提供します。

それを 8 ビット右シフトすると、常に 0 になります。

アドレスの上位 8 ビットを取得することが目的の場合は、次を使用する必要があります。

(unsigned char)(addr>>8)

シフトが最初に行われるようにします。

于 2015-01-21T02:59:52.100 に答える