我知道你在说什么,我自己也遇到过同样的问题。问题在于,使用带有与变量本身内联的地址的 @ 符号是大多数工具链的附加功能。虽然许多嵌入式工具链都支持它,因此您可以显式调用 SFR 或其他寄存器的位置,但这不是标准 C 的正常行为。
虽然我不熟悉您正在使用的特定编译器,但我知道大多数编译器提供了一种更复杂的方式来指定内存映射。例如,来自 Atmel 的 ATmega 系列提供了在项目设置中指定自定义内存部分的功能。例如,在 GNU 工具链上,这些部分用作变量声明的一部分,方法是使用带有变量的 section 属性:
__attribute__((__section__("<section_name>")))
对于 ATmega 系列,您可以在 EEPROM 中定位任何内存,方法是在变量声明的同一行(之前或之后,只要它位于赋值中的“=”之前)包含以下文本:
__attribute__((__section__(".eeprom")))
如果您想保证 EEPROM 中的特定内存地址设置为二进制映像的一部分,因此它只在第一次写入映像时被编程一次,您可以在项目设置中声明一个自定义内存部分(如果您在 Atmel Studio 中开发,它位于“工具链”设置的“内存设置”下)。
例如,我通过在内存设置的 EEPROM 部分中声明“.tune_data”部分(遵循提供的地址偏移等文档)然后声明如下变量,完全按照您对数据块的描述:
const __attribute__((__section__(".tune_data))) Tune_Data_s as_tune_data = { <all_my_data> };
显然它会略有不同,因为您没有使用 GNU 编译器,也可能没有使用 Atmel Studio。但是,如果您仔细研究一下,几乎每个嵌入式编程工具链都提供了一些方法来声明自定义内存部分,然后可以通过编译指示(或 GNU 工具链的属性)将其附加到代码中的变量。规范应该可以通过命令行参数和/或使用命令行选项修改标准链接描述文件来指定非默认链接描述文件。我知道第二种方法是在 IAR 提供的工具链上执行此操作的标准方法,也是唯一方法。