啊,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等无济于事 - 我总是在屏幕上看到垃圾。
救救我!
答案 0 :(得分: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]
相同的地址。
接下来要知道的是;
a中的[b]只是编写*(a + b)
的一种奇特方式
所以字形是一个指针,当像glyph[indexIntoGlyph]
一样使用时,它与*(glyph + indexIntoGlyph)
相同,解引用运算符*
表示我们在该地址获取数据。
从那里,我们可以像wex描述的那样使用pgm规则;
如果变量在PROGMEM中,则使用pgm_read_byte()作为 替换解除引用运算符*。对于“正常”变量 RAM你可以随时写*(&amp; a)而不只是a来返回值 变量a;所以从progmem返回一个8位宽的变量你 写pgm_read_byte(&amp; x)。
希望这个解释是正确的,并帮助人们(像我这样的新手!)更好地理解它。
答案 1 :(得分:0)
我在AVRfreaks.net得到了一些很大的支持,并认为我会在这里发布答案以供本社区参考。谢谢'wek'!
'wek'根据我提供的信息确定,我需要从&fontInfo->data[charOffset]
的{{1}}开始发送多个字节。
如果变量在PROGMEM中,则使用
drawCharBitmap()
作为 替换解除引用运算符pgm_read_byte()
。对于“正常”变量 在RAM中你总是可以写*
而不是只用a来返回 变量*(&a)
的值;所以从中返回一个8位宽的变量 你写的是a
。现在回想一下,C中的
pgm_read_byte(&x)
只是写a[b]
的一种奇特方式 (其中*(a + b)
是指向数组第一个成员的指针, 因此指针算术规则适用)。所以在a
你 可以将drawCharBitmap
更改为glyph[indexIntoGlyph]
或pgm_read_byte(&(glyph[indexIntoGlyph]))
。
我仍在尝试理解这里的链接,但这是一个非常好的答案,应该放在这里。感谢所有花时间看这个的人。