的易失性的关键字是类型限定符防止从编译器optimization.According至C标准的对象,具有挥发性限定类型可以以实施方式未知进行修改或具有其他未知侧effects.You也可以说,一个对象可以随时更改volatile限定对象的值,而不需要代码执行任何操作。
如果一个对象被volatile限定符限定,那么每次程序访问它时,编译器都会从内存中重新加载该值,这意味着它阻止将变量缓存到寄存器中。从内存中读取值是检查内存的唯一方法。价值的不可预测的变化。
是的,我们可以用C语言创建一个易失性指针。 int * volatile piData; // piData是一个指向整数的易失性指针。
在这里,我指出了一些需要使用volatile关键字的重要位置。
#define COM_STATUS_BIT 0x00000006
uint32_t const volatile * const pStatusReg = (uint32_t*)0x00020000;
unit32_t GetRecvData()
{
//Code to recv data
while (((*pStatusReg) & COM_STATUS_BIT) == 0)
{
// Wait untill flag does not set
}
return RecvData;
}
volatile int giFlag = 0;
ISR(void)
{
giFlag = 1;
}
int main(void)
{
while (!giFlag)
{
//do some work
}
return 0;
}
const关键字是编译器强制执行的,并且表示程序无法更改对象的值,这意味着它使对象成为不可修改的类型。 例如, const int a = 0; 如果你试图修改“a”的值,你将得到编译器错误,因为“a”符合const关键字,阻止更改整数变量的值。
在另一方面,volatile阻止任何编译器优化,并且表示对象的值可以通过程序无法控制的内容进行更改,因此编译器不会对该对象做出任何假设。 例如, volatile int a;
当编译器看到上述声明时,它避免对“a”做出任何假设,并且在每次迭代中从分配给变量的地址中读取值。
是的,我们可以同时使用常量和常量。volatile和const关键字的最大用途之一是访问GPIO寄存器时。对于GPIO,如果将其配置为输入,则可以通过“外部因素”(如果交换机或任何输出设备与GPIO连接)更改其值。在这种情况下,volatile起着重要作用,并确保编译器始终从GPIO地址读取值并避免做出任何假设。
使用volatile关键字后,无论何时访问端口,都会得到正确的值,但是这还有一个问题,因为指针不是const类型,因此可能是程序更改了指针的指向地址。所以我们必须用volatile关键字创建一个常量指针。
声明的语法,
int volatile * const PortRegister;
如何阅读上述声明,
int volatile * const PortRegister;
| | | | |
| | | | +------> PortRegister is a
| | | +-----------> constant
| | +---------------> pointer to a
| +---------------------> volatile
+---------------------------> integer
考虑一个简单的下面例子:
#define PORTX 0x00020000 // GPIO的地址
uint32_t volatile * const pcPortReg =(uint32_t *)PORTX;
pcPortReg是一个指向易失性无符号整数的常量指针,使用* pcPortReg我们可以访问内存映射寄存器。
* pcPortReg = value; //将值写入端口 value = * pcPortReg; //从端口读取值