1

奇妙な問題を抱えています。最後に、ループ内でインクリメントする変数「i」を、ディスプレイに出力される文字に変換する関数に渡すことができる文字列に変換する方法を見つけました。

問題は、値が 1 ではなく 2 ずつ増加することです。いくつかの異なることを試しましたが、問題がどこにあるのかわかりません。

最初は、おそらく、別の関数を呼び出す関数があり、両方が同じ変数を使用してインクリメントする場合 (つまり、for(int i=0; i<10; ++i))、「outer」関数の「i」は、「外側」ループで 1 回、「内側」ループで 1 回インクリメントされるため、2 ずつインクリメントされます。しかし、私はそうではないと思います。私の場合、「i」が2以上インクリメントされると、すべてのカウンター変数を変更せずに別の名前に変更しようとしました。とにかく、言語が機能するのはばかげた方法です。もちろんそうでない限り、私は啓発されたいと思っています。

問題を引き起こしているコードブロックは次のとおりです。

for (int i=0; i<100; i++){
    char c[1]={0};                    // Create variable to hold character
    sprintf(c,"%d", i);               // Copy value of "i" as string to variable
    writeText(c,0,0,WHITE,BLACK,3);   // Write the character "c" at position 0,0. Size 3
    OLED_buffer();                    // Send display buffer
    delay_ms(500);                    // Delay before next increment
}

ここに writeText() があります:

void writeText(unsigned char *string, int16_t x, int16_t y, uint16_t color, uint16_t bgcolor, uint8_t size){
    unsigned char letter;
    for (int i=0; i<strlen(string); ++i){
        letter = string[i];
        if (letter != NULL){
            drawChar(x+(i*6*size),y,letter,color,bgcolor,size);
        }
    }
}

以下は、writeText によって呼び出される drawChar です。

void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size) {

    if((x >= _width)            ||  // Clip right
    (y >= _height)              ||  // Clip bottom
    ((x + 5 * size - 1) < 0)    ||  // Clip left
    ((y + 8 * size - 1) < 0))       // Clip top
    return;

    for (int8_t i=0; i<6; i++ ) {
        uint8_t line;
        if (i == 5)
        line = 0x0;
        else
        line = font[(c*5)+i];
        for (int8_t j = 0; j<8; j++) {
            if (line & 0x1) {
                if (size == 1) // default size
                drawPixel(x+i, y+j, color);
                else {  // big size
                    fillRect(x+(i*size), y+(j*size), size, size, color);
                }
                } else if (bg != color) {
                if (size == 1) // default size
                drawPixel(x+i, y+j, bg);
                else {  // big size
                    fillRect(x+i*size, y+j*size, size, size, bg);
                }
            }
            line >>= 1;
        }
    }
}

そして最後に、drawChar によって呼び出される drawPixel (ただし、問題がこれほど深いものになることを心から疑っています):

void drawPixel(int16_t x, int16_t y, uint16_t color) {
    if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
    return;

    // check rotation, move pixel around if necessary
    switch (getRotation()) {
        case 1:
        swap(x, y);
        x = WIDTH - x - 1;
        break;
        case 2:
        x = WIDTH - x - 1;
        y = HEIGHT - y - 1;
        break;
        case 3:
        swap(x, y);
        y = HEIGHT - y - 1;
        break;
    }

    // x is which column
    if (color == WHITE)
    buffer[x+(y/8)*SSD1306_LCDWIDTH] |= _BV((y%8));
    else
    buffer[x+(y/8)*SSD1306_LCDWIDTH] &= ~_BV((y%8));
}

このすべての結果として、ディスプレイには遅延の長さの 2 倍ずつ増加する数値が表示されます。たとえば、ここでの遅延は 500 ミリ秒なので、1 秒ごとに更新されます。行くのではなく

1、2、3、4、5...

当然のことながら、それは行きます

1、3、5、7、9...

アドバイスできる人はいますか?これは私の最初のループでのばかげた単純な問題だと確信していますが、今はわかりません。

xmega32a4u をプログラムするために Atmel Studio 6 を使用しています。示されているライブラリ関数は、私が Atmel Studio に移植した SSD1306 128x32 OLED 用の Adafruit グラフィック ライブラリの一部です。

助けてくれてどうもありがとう!

更新:私のコードにはいくつかの問題がありましたが、実際の問題は実際には OLED の対処方法にありました。Adafruit は、表示用にライブラリに正しいページ アドレスを設定するのを忘れていたようです。ディスプレイのコントローラーは 128x64 と 128x32 のディスプレイをサポートできるため、コントローラーがディスプレイ RAM のどの部分にアクセスするかを認識できるように、ディスプレイの「終了」アドレスを正しく設定する必要があります。その機能がありませんでした。ディスプレイがデータ RAM に書き込む方法と、ディスプレイの高さが 32 ピクセルしかないことを「認識」しなかったため、ディスプレイに送信されるフレームは 1 つおきにディスプレイ RAM の「下部」部分に実際に書き込まれていました (つまり、ディスプレイが 128x64 の場合に表示される部分で、高さが 2 倍になります)。だから今、すべてがうまくいきます!

問題のその側面について考えさせられる表示タイミングについての彼の提案がなければ、問題を理解するのに長い時間がかかったかもしれません。

4

1 に答える 1