啊哈,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 等,但无济于事 - 我总是在屏幕上看到垃圾。
救我!
最佳答案
好的,我想我明白这里发生了什么。
一、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] in C is just a fancy way for writing *(a + b)
所以字形是一个指针,当像这样使用时
glyph[indexIntoGlyph]
, 同 *(glyph + indexIntoGlyph)
, 和解引用运算符 *
意味着我们在该地址获取数据。从那里,我们可以使用 wex 描述的 pgm 规则;
If the variable is in PROGMEM, you use pgm_read_byte() as a replacement for the dereference operator *. For "normal" variables in RAM you can always write *(&a) instead of just a to return the value of the variable a; so to return a 8-bit wide variable from progmem you write pgm_read_byte(&x).
希望这个解释是正确的,可以帮助人们(像我这样的新手!)更好地理解它。
关于string - 在FLASH中留下数据数组(字体) - AVR GCC中的PROGMEM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8276172/