代码:
static volatile unsigned char TMR0 @ 0x01;
static volatile unsigned char PORTA @ 0x05;
static volatile unsigned char PORTB @ 0x06;
static volatile unsigned char PORTC @ 0x07;
此代码来自PIC16F877A的HT-PICC编译器pic.h库文件
我了解static volatile和其他关键字的含义。
这里的Timer0寄存器地址为0x01,但是为什么要在其前面使用@
?它与指针有关吗?
答案 0 :(得分:6)
它是许多嵌入式编译器中常见的编译器扩展,可让您将变量放在绝对内存地址中。
摘自HI-TECH C编译器手册:
3.5.4绝对变量
大多数变量可以通过以下声明在绝对地址中: 构造 @ address ,其中 address 是内存中要放置变量的位置。这样的变量称为绝对变量。
3.5.4.1 数据存储器中的绝对变量
绝对变量主要用于将C标识符的地址与 一个特殊的功能寄存器,但可用于将普通变量置于绝对位置 数据存储器中的地址。
在您的示例中:
static volatile unsigned char TMR0 @ 0x01;
TMR0
大概是8位无符号硬件寄存器,位于地址0x01。
答案 1 :(得分:4)
它是位于特定存储位置(@
)处的变量。因此,在地址TMR0
处有一个8位变量0x01
。在PIC的Hi-Tech C编译器手册中,请参阅第3.4.4节“指针类型”以获取更多信息。
在香草C中,等效值为:
static volatile unsigned char * TMR0 = (volatile unsigned char *) 0x01;
@
运算符用于内存非常低的体系结构,以帮助减少内存占用。
答案 2 :(得分:2)
这是用于在特定地址分配变量的常见非标准符号。在您的情况下,它用于将硬件寄存器映射到C变量。
具体地说,@
的目的是允许链接程序/调试器将寄存器当作对象使用。这意味着您可以像在任何其他变量中一样,在调试器中为其添加监视或读写断点。
否则,如果不需要在调试器中查看这些内容,则可以使用标准的C语言:
#define TMR0 (*(volatile uint8_t*)0x01u)
当然,不需要为硬件寄存器分配空间,因为无论C程序做什么,它们已经存在于硬件中。
好的调试器带有MCU支持,并且可以选择在单独的窗口中查看MCU特定的寄存器。因此,将@
用于寄存器/寄存器映射的主要原因是因为工具链附带了糟糕的调试器。不幸的是,这是我对嵌入式工具链的经验:调试器越差,编译器提供的寄存器映射就越混乱。
但是@
符号也可以用于声明特定位置的RAM / ROM变量。其他编译器的其他非标准扩展使用各种#pragma
,___declspec(section...
或__attribute__(section...
。如果存在标准方法,那会很好,但可惜没有。