avr-gcc如何在函数调用时直接将字符串存入PROGMEM?类似Arduino的F()宏
解决方案
完全可以实现类似Arduino F() 宏的效果,无需提前单独声明PROGMEM字符串变量,avr-libc已经提供了现成的实现,也可以自己基于GCC扩展自定义。
步骤1:使用预定义PSTR()宏
avr-libc的 <avr/pgmspace.h> 头文件中已经内置了 PSTR() 宏,刚好满足你单行调用的需求,调用形式如下:
ParAdd(11, PSTR("Name1"));
步骤2:适配函数实现
由于AVR是哈佛架构,Flash(PROGMEM)和RAM的地址空间相互独立,普通的指针访问默认操作的是RAM空间,你需要对ParAdd函数的实现做对应调整:
- 读取PROGMEM地址中的字符时,不能直接用
ParName[n]形式,需要调用pgm_read_byte()等专用读取函数 - 如果你使用avr-gcc 5及以上版本,也可以用
__flash关键字标记参数,编译器会自动处理PROGMEM读取逻辑:void ParAdd(uint8_t type, const __flash char *ParName)
完整示例代码
#include <avr/pgmspace.h> #include <stdint.h> void ParAdd(uint8_t type, const char *ParName){ // 示例逻辑:逐字符读取PROGMEM中的字符串 char c; while((c = pgm_read_byte(ParName++)) != '\0'){ // 处理字符逻辑 } } int main (void){ ParAdd(11, PSTR("Name1")); ParAdd(22, PSTR("Name2")); ParAdd(30, PSTR("Name3")); return 0; }
实现原理
PSTR() 宏基于GNU C的复合字面量扩展实现,核心逻辑如下:
#define PSTR(s) ((const char *)(&(const char[] PROGMEM) { s }))
(const char[] PROGMEM) { s } 会创建一个带PROGMEM属性的临时字符数组,编译器会直接将其分配到Flash空间,无需提前定义全局变量,返回的指针可以直接作为参数传递给函数。
内容的提问来源于stack exchange,提问作者eSlavko
相关产品推荐
相关产品推荐

