4

ああ、PROGMEM、ポインタ、ポインタへのポインタ、ポインタのアドレス...頭がおかしくなります。

問題のフォントのデータ配列があります

const uint8_t dejaVuSans9ptBitmaps[] = 
{
    /* @0 ' ' (5 pixels wide) */
    0x00, /*          */
    0x00, /*          */
...

PROGMEMを追加しました

const uint8_t dejaVuSans9ptBitmaps[] PROGMEM =

これは、そのような別の構造で参照されます。

const FONT_INFO dejaVuSans9ptFontInfo = {
   13,
   ' ',
   '~',
   dejaVuSans9ptDescriptors, 
   dejaVuSans9ptBitmaps,
};

構造は次のように定義されます。

typedef struct {
   const uint8_t           height;       
   const uint8_t           startChar;    
   const uint8_t           endChar;      
   const FONT_CHAR_INFO*   charInfo;    
   const uint8_t*          data;         
} FONT_INFO;

これをに変更する必要があると仮定して正しいですか。

typedef struct {
   const uint8_t           height;       
   const uint8_t           startChar;    
   const uint8_t           endChar;      
   const FONT_CHAR_INFO*   charInfo;    
   const PGM_P             data;         
} FONT_INFO;

私がそうするとき、それはそれを不平を言います

warning: pointer targets in initialization differ in signedness

FONT_INFO変数のこの特定の行。

const FONT_INFO dejaVuSans9ptFontInfo = {
    13,
    ' ',
    '~',
    dejaVuSans9ptDescriptors, 
--> dejaVuSans9ptBitmaps, <--
};

次に、関数を使用して描画されます。

void drawString(uint16_t x, uint16_t y, uint16_t color, const FONT_INFO *fontInfo, char *str) {
    ...
    drawCharBitmap(currentX, y, color, &fontInfo->data[charOffset], charWidth, fontInfo->height);
    ...

最終的にグリフを描画します。

void drawCharBitmap(const uint16_t xPixel, const uint16_t yPixel, uint16_t color, const uint8_t *glyph, uint8_t cols, uint8_t rows) {
   ...
      if (glyph[indexIntoGlyph] & (0X80)) drawPixel(currentX, currentY, color);
   ...

私は頭を抱えています:/誰かが私にいくつかの方向性を与えることができますか?PGM_Pやpgm_read_byteなどを使用しようとして何時間も費やして無駄になりました-私はいつも画面にゴミが表示されます。

私を救ってください!

4

2 に答える 2

1

わかりました、ここで何が起こっているのか理解できたと思います。

1const uint8_t* dataつ目は、PROGMEM に格納されているデータへのポインターです。

へのfunction void drawString(uint16_t x, uint16_t y, uint16_t color, const FONT_INFO *fontInfo, char *str)ポインタを渡しますfontInfo

続行するには、次のことを理解することが重要です。

fontInfo.data
(*ptr_to_fontInfo).data
ptr_to_fontInfo->data

すべて同じです。したがってptr_to_fontInfo->data、データを返します(アドレスではありません)

次に、&演算子を使用して、このデータの「アドレス」を次の関数に渡します

drawCharBitmap(currentX, y, color, 
  &fontInfo->data[charOffset], charWidth, fontInfo->height)

このアドレスは、ここで宣言されたポインター変数に格納されunint8_t *glyphます。

void drawCharBitmap(const uint16_t xPixel, const uint16_t yPixel, 
  uint16_t color, const uint8_t *glyph, uint8_t cols, uint8_t rows)

これを念頭に置いてください。

int *ptr;
int a;

ptr = &a;

次に、グリフは と同じアドレスを指しますfontInfo->data[charOffset]

次に知っておくべきことは次のとおりです。

C の a[b] は *(a + b) を書くためのちょっとした方法です。

したがって、グリフはポインターであり、このように使用glyph[indexIntoGlyph]すると、 と同じ*(glyph + indexIntoGlyph)であり、逆参照演算子*は、そのアドレスでデータを取得することを意味します。

そこから、説明したように pgm ルールを使用できます。

変数が PROGMEM にある場合、逆参照演算子 * の代わりに pgm_read_byte() を使用します。RAM 内の「通常の」変数の場合、単に a の代わりに *(&a) を記述して、変数 a の値を返すことができます。したがって、progmem から 8 ビット幅の変数を返すには、pgm_read_byte(&x) と記述します。

この説明が正しく、人々 (私のような初心者!) がそれをよりよく理解するのに役立つことを願っています.

于 2011-11-28T02:32:53.107 に答える
0

私は AVRfreaks.net で素晴らしいサポートを得て、このコミュニティが今後参照できるように、ここに回答を投稿しようと考えました。ありがとうございます!

「wek」は、私が提供した情報に基づいて、&fontInfo->data[charOffset]inから始まる複数のバイトを送信する必要があることを特定しましたdrawCharBitmap()

変数が PROGMEM にある場合は、間接pgm_read_byte()参照演算子の代わりに使用します*。RAM 内の「通常の」変数*(&a)の場合は、変数の値を返すだけでなく、いつでも書き込むことができますa。したがって、progmem から 8 ビット幅の変数を返すには、次のように記述しpgm_read_byte(&x)ます。

a[b]ここで、C での は単に手の込んだ書き方であることを思い出してください*(a + b) (aは配列の最初のメンバーを指すポインターであるため、ポインター演算の規則が適用されます)。したがって、、または のいずれかに drawCharBitmap変更できます。glyph[indexIntoGlyph]pgm_read_byte(&(glyph[indexIntoGlyph]))pgm_read_byte(glyph + indexIntoGlyph)

私はまだここのリンクを理解しようとしていますが、ここに載せるに値する素晴らしい答えでした. これを見て時間を割いてくれたすべての人に感謝します。

于 2011-11-28T00:33:02.273 に答える