2011-11-26 41 views
4

啊,PROGMEM,指针,指向指针的指针,指针的地址...我的头很大。在FLASH中保留一个数据数组(字体) - 在AVR GCC中编程

我有用于所讨论的字体

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等无济于事 - 我总是在屏幕上看到垃圾。

救救我吧!

+0

您是否尝试过审阅http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html的文档? – Jeff

+0

@Jeff我当然了!我认为这更多的是通过我的指针和地址指针。我不知道什么时候告诉编译器从pgmspace读取。 – mriksman

回答

1

好的,我想我明白这里发生了什么。

首先,const 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]相同的地址。

接下来要知道的是;

一个并[b]在C是只用于写入*一个奇特的方式(A + B)

所以字形是一个指针,这样glyph[indexIntoGlyph]使用时,它是相同的*(glyph + indexIntoGlyph),而取引用操作符*表示我们在该地址获取数据。

从那里,我们可以使用pgm规则描述为wex;

如果该变量在PROGMEM中,则使用pgm_read_byte()作为替代引用运算符*的 。对于 RAM中的“正常”变量,可以始终写入*(& a),而不是仅返回变量a的值 ;所以要从progmem返回一个8位宽的变量,你需要写入pgm_read_byte(& x)。

希望这个解释是正确的,并帮助人们(像我这样的新手)更好地理解它。

0

我在AVRfreaks.net上得到了一些很好的支持,并且认为我会在这里发布答案,以供将来社区参考。谢谢'wek'!

'wek'根据我给出的信息确定,我需要发送多个字节,从&fontInfo->data[charOffset]开始,位于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)

我仍然试图了解这里的链接,但这是一个很好的答案,它应该放在这里。感谢所有花时间看这个的人。