我已经阅读了几天访问PROGMEM,并梳理了其他几个问题,但我仍然无法使我的代码正常工作。任何帮助将不胜感激。
我在下面列出了Arduino的完整测试草图。它的大部分工作,但是当我循环遍历“alpha”字符的每个字节时,正如“alphabytes”所指出的那样,我只是把垃圾拿出来所以我显然没有访问正确的内存位置。问题是,我无法弄清楚如何访问该内存位置。
我已经看到了其他几个这样的例子,但没有一个在指针数组中有不同大小的数据数组。
请看“以>>>>>开头的行?问题是......”
// Include PROGMEM library
#include <avr/pgmspace.h>
// Variable to hold an alphabet character row
char column_byte;
// Used to hold LED pixel value during display
char led_val;
// Used to hold the screen buffer for drawing the screen
char matrix_screen[64];
/*
Define Alphabet characters. This should allow for characters of varying byte lengths.
*/
const char alpha_A[] PROGMEM = {0x06, 0x38, 0x48, 0x38, 0x06};
const char alpha_B[] PROGMEM = {0x7E, 0x52, 0x52, 0x2C};
const char alpha_C[] PROGMEM = {0x3C, 0x42, 0x42, 0x24};
/*
The "alphabytes" contains an array of references (pointers) to each character array.
Read right-to-left, alphabytes is a 3-element constant array of pointers,
which points to constant characters
*/
const char* const alphabytes[3] PROGMEM = {
alpha_A, alpha_B, alpha_C
};
/*
This array is necessary to list the number of pixel-columns used by each character.
The "sizeof" function cannot be used on the inner dimension of alphabytes directly
because it will always return the value "2". The "size_t" data
type is used because is a type suitable for representing the amount of memory
a data object requires, expressed in units of 'char'.
*/
const char alphabytes_sizes[3] PROGMEM = {
sizeof(alpha_A), sizeof(alpha_B), sizeof(alpha_C)
};
/**
* Code Setup. This runs once at the start of operation. Mandatory Arduino function
**/
void setup(){
// Include serial for debugging
Serial.begin(9600);
}
/**
* Code Loop. This runs continually after setup. Mandatory Arduino function
**/
void loop(){
// Loop through all alphabet characters
for( int a = 0; a < 3; a++) {
// Reset screen
for (int r = 0; r < 64; r++) {
matrix_screen[r] = 0;
}
// This line works to read the length of the selected "alphabyte"
int num_char_bytes = pgm_read_byte(alphabytes_sizes + a);
for (int b = 0; b < num_char_bytes; b++){
// Based on alphabytes definition,
// Examples of desired value for column_byte would be:
//
// When a=0, b=0 -> column_byte = 0x06
// When a=0, b=1 -> column_byte = 0x38
// When a=0, b=2 -> column_byte = 0x48
// When a=0, b=3 -> column_byte = 0x38
// When a=0, b=4 -> column_byte = 0x06
// When a=1, b=0 -> column_byte = 0x7E
// When a=1, b=1 -> column_byte = 0x52
// When a=1, b=2 -> column_byte = 0x52
// When a=1, b=3 -> column_byte = 0x2C
// When a=2, b=0 -> column_byte = 0x3C
// When a=2, b=1 -> column_byte = 0x42
// When a=2, b=2 -> column_byte = 0x42
// When a=2, b=3 -> column_byte = 0x24
// >>>>> Question is... how to I get that? <<<<<<<
// column_byte = pgm_read_byte(&(alphabytes[a][b])); // This doesn't work
// Thought: calculate offset each time
// int offset = 0;
// for(int c = 0; c < a; c++){
// offset += pgm_read_byte(alphabytes_sizes + c);
// }
// column_byte = pgm_read_byte(&(alphabytes[offset])); // This doesn't work
// column_byte = (char*)pgm_read_word(&alphabytes[a][b]); // Doesn't compile
column_byte = pgm_read_word(&alphabytes[a][b]); // Doesn't work
// Read each bit of column byte and save to screen buffer
for (int j = 0; j < 8; j++) {
led_val = bitRead(column_byte, 7 - j);
matrix_screen[b * 8 + j] = led_val;
}
}
// Render buffer to screen
draw_screen();
// Delay between frames
delay(5000);
}
}
/**
* Draw the screen. This doesn't have the correct orientation, but
* that's fine for the purposes of this test.
**/
void draw_screen(){
for (int a = 0; a < 8; a++) {
for (int b = 0; b < 8; b++) {
Serial.print((int) matrix_screen[a * 8 + b]);
Serial.print(" ");
}
Serial.println();
}
Serial.println();
}
答案 0 :(得分:0)
经过大量研究(坦率地说是很多试验和错误),我遇到了一个有效的解决方案。我不知道这是否是最正确或最优雅的解决方案,但它确实有效。
column_byte = pgm_read_byte(pgm_read_byte(&alphabytes[a]) + b);
对pgm_read_byte()的内部调用:
pgm_read_byte(&alphabytes[a])
返回一个值,该值是被评估字符的地址(注意前导“address-of”运算符“&amp;”)。
外部pgm_read_byte以偏移量“b”读取该内存。
此解决方案也可分为两部分:
int memory_loc = pgm_read_byte(&alphabytes[a]);
column_byte = pgm_read_byte(memory_loc + b);
我的C技能还不足以真正解释“memory_loc”是否需要是一个int(我把它作为“char”尝试并且它也有效)。
答案 1 :(得分:0)
请注意, alphabytes 是数组,每个元素都包含一个REFERENCE(即地址),其中存储了相应的字符。因此,您应该分两步访问它。
第一步是知道所需项目的编程中的地址。地址宽16位(除非您使用的是128 + k设备)。
PGM_VOID_P ptr = (PGM_VOID_P) pgm_read_word(&alphabytes[a]);
并且,如果你想逐字节访问它,你可以使用这个指针读取,然后递增它:
for (int b = 0; b < num_char_bytes; b++) {
uint8_t column_byte = pgm_read_byte(ptr++);
...
}