PROGMEM的使用问题
本帖最后由 shihaipeng04 于 2014-3-11 21:50 编辑PROGMEM 说是可以把常量储存到flash里,这样就不用占用sram的空间了。 我在捣鼓小屏幕,想重写一下卖家送的库,因为不太方便。现在刚开头就困难重重的。呵呵。
字库文件用一个数组存放,6个字节一个字母,大约500多个字节。人家原来程序也是用PROGMEM存的,就一切正常。 我自己啥也没改,读出来的字库就是混乱的,可是如果就是用 uint8_t font6x8[] = {****};就正常。加上 uint8_t PROGMEMfont6x8[] = {}就是乱码。 太神奇了。
唯一的区别是,原来库是在一个 .c的文件里,include到主程序里的,我只是为了修改方便,都放到主程序里了,这应该没影响啊。换了uno和mrico 2种板子,故障现象一样。 好像找到点问题。。。例子文件的 .H 上面还有一句 #define PROGMEM
虽然不知道是干啥的,但是感觉肯定和我这个问题有关系。 PROGMEM关键词声明的数据需要用pgmspace系列函数先读到内存里面,再使用
http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html
http://arduino.cc/en/Reference/PROGMEM histamine 发表于 2014-3-11 16:30 static/image/common/back.gif
PROGMEM关键词声明的数据需要用pgmspace系列函数先读到内存里面,再使用
http://www.nongnu.org/avr-lib ...
诶,洋文的真心看不懂了,不过按照原来例子的使用方法到是学会啦。也谢谢你哈。 能用就好,深的技术面不研究。呵呵 shihaipeng04 发表于 2014-3-11 21:51 static/image/common/back.gif
诶,洋文的真心看不懂了,不过按照原来例子的使用方法到是学会啦。也谢谢你哈。 能用就好,深的技术面不研 ...
#define PROGMEM就是用宏定义,使得编译时预处理器会把PROGMEM关键词删除掉,然后就和没有使用PROGMEM一样了:L histamine 发表于 2014-3-12 09:17 static/image/common/back.gif
就是用宏定义,使得编译时预处理器会把PROGMEM关键词删除掉,然后就和没有使用PROGMEM一样了
大致明白了, 反正前面加上 #define PROGMEM,后面再有 uint8_t PROGMEMfont6x8[] = {....}就正常了。 本帖最后由 Super169 于 2014-4-2 23:00 编辑
shihaipeng04 发表于 2014-3-12 15:47 static/image/common/back.gif
大致明白了, 反正前面加上 #define PROGMEM,后面再有 uint8_t PROGMEMfont6x8[] = {....}就正常了。
你不是明白了, 而是受騙了.
我看過好幾個庫, 都是不明白 PROGMEM 的用法, 而加上了 #define PROGMEM (之前買的 OLED 的庫也是一樣).
當你加入 #define PROGMEM 後沒有問題, 以為可以用到, 其實是因為你只是在用 SRAM 中, 並沒有真正使用 flash memory.
不信的話, 你嘗試加入 #define PROGMEM 後, 再用 PROGMEM create 一個 4K 的 array.你的 flash 應該足夠的, 但也會出現問題.
因為 #define PROGMEM 之後沒東西, 結果就會把程式中 PROGMEM 的字除去.#define 同時有取代的作用, 就如 #define _width_ 128, 當程式中出現 _width_ 時, 都會被轉換成 128 去 compile.
結果uint8_t PROGMEMfont6x8[] = {****}就變回uint8_t font6x8[] = {****} 了, 當然沒問題, 只是做不到想要的效果.
之前寫庫的人, 用 #define PROGMEM 去 當成已"解決"問題, 有點誤導成份.
正確使用方法, 是要改變讀取數值的方式, arduino.cc 中有清楚的例子, 必須用 pgm_read_??? 去讀取資料.
例如 http://arduino.cc/en/Reference/PROGMEM 中的例子,
如果用 SRAM 時, string_table[ i ] 的數值, 當便用 PROGMEM 時, 就要用 pgm_read_word(&(string_table[ i ])) 去讀取.
補充少少解釋, 希望容易明白一點:
- string_table[ i ] 是原來的資料, 在 SRAM 中的話, 直接讀取就可以
- &(string_table[ i ]) 是資料的地址
本來, 地址指向的地方, 直接讀取就可以.但現在有兩個放資料的地方 (SRAM 及 flash), 預設是 SRAM.
當你直接讀取是, 系統會在 SRAM 對應的位置讀取, 結果就出亂碼了.
舉一個簡單例子, 假設你住在 北京大廈, 而世上只有一座大廈時, 當你說 10樓 8室, 自然是北京大廈的 10 樓 8室.
如果還有另一座 上海大廈的存在, 又如何?由於你本身在北京大廈, 當你只說 10樓 8室, 會被看成是 北京大廈 10 樓 8室.
但當你想找的 是在 上海大廈 10 樓 8 室時, 就不可以用預設的方式了, 必須清楚說明了.
PROGMEM 亦是一樣, 系統預設是在 SRAM 中讀取, 因此如不加說明, 系統就會走到 SDRAM 那個地址去了.
所以你一開始出現亂碼, 是正常的, 證明你成功放到 PROGMEM 中, 在 SRAM 相同位置中找錯對象了.
後來你加入 #define PROGMEM 而成功讀出, 表面上的成功, 只是證明了不是放到 PROGMEM 中.
要讀出 PROGMEM 中的資料, 就要告訴系統你的地址是在 PROMEM 中, 不能用 SRAM 的讀法.
pgm_read_word(&(string_table[ i ]))就是這個作用了.
所以, 如果你想真正用到 flash 而不是 SRAM, 就要把原來讀取資料的地方改了, 而不是加入 #define 的語句.
页:
[1]