"); //-->
自以为对51很熟了,但是最近发现越用越觉得陌生,在网上看的东西越多越觉得自己懂得少,惊出一身冷汗。
今天看到了C51中关键字volatile 的用法。联想起上星期做的东西,正是由于中断内修改标志flag,在主程序中判断这个flag标志进行后续操作。思路上没有什么问题,但是实际运行起来的时候,虽然中断启动了,也修改了flag,但主程序就死活不能识别修改过的flag,进行相应的后续动作。当时百思不得起解,只好用别的笨方法完成了相同的功能。今天才知道原来是flag变量没有用volatile来声明的原因。
现转载一下网上高人的指点,因为我看的也是转载的所以不知那位高人是谁,说不了出处了,望见谅!
volatile用于防止相关变量被优化。例如对外部寄存器的读写。对有些外部设备的寄存器来说,读写操作可能都会引发一定硬件操作,但是如果不加volatile,编译器会把这些寄存器作为普通变量处理,例如连续多次的对同一地址写入,会被优化为只有最后一次的写入。实际上,网卡的数据发送,就是按顺序连续往一个同地址写入数据,如果被优化,网卡将不能正常驱动。对于外部寄存器的读写,经常用 XBYTE,其实你看一下XBYTE的原型就知道了,里面也是有个volatile的。另一个使用场合是中断。如果一个全局变量,在中断函数和普通函数里都用到过,那最好对这个变量加volatile修饰。否则普通函数里,可能会仅从寄存器里读取这个变量以便加快速度,而不去实际地址读取该变量。
内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速对内存的访问。
编译器优化常用的方法有:将内存变量缓存到寄存器;
由于访问寄存器的速度快于访内存,所以编译器一般
都会作优化以减少访内存。如果变量加上volatile修饰,则编译器就不会对此变量
的读写操作进行优化,即不通过寄存器缓冲而直接访内存。
C语言关键字volatile表明某个变量的值可能在外部被改变,因此对这些变量的存取不能缓存到寄存器,每次使用时需要重新存取。
该关键字在多线程环境下经常使用,因为在编写多线程的程序时,同一个变量可能被多个线程修改,而程序通过该变量同步各个线程,
对于C编译器来说,它并不知道这个值会被其他线程修改。自然就把它cache在寄存器里面。记住,C 编译器是没有线程概念的
volatile 的本意是指:这个值可能会在当前线程外部被改变。
下面有个例子:
volatile是“易变的” 意思
由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。比如:
bit bFlag="0";
int main(void)
{
...
while (1)
{
if (bFlag) dosomething();
}
}
/* 中断程序*/
void ISR(void)
{
bFlag=1;
}
程序的本意是希望ISR中断产生时,在main当中调用dosomething函数,但是,由于编译器判
断在main函数里面没有修改过bFlag,因此
可能只执行一次对从bFlag到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面
的“bFlag副本”,导致dosomething永远也不会被调用。如果将将变量加上volatile修饰,
则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中bFlag也应该如此说
明。
一般说来,volatile用在如下的几个地方:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。
专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们
相关推荐
PHILIPS LPC900微控器的单电池电源
中国数码相机消费需求迎来爆发性增长前夜
英飞凌携手SolarEdge共同推进AI数据中心高效电力基础设施的发展
模拟电子技术 第七讲
中国电源产业的发展与分析
从物理层的角度来看,Wi-Fi 8超高可靠性意味着什么?
模拟电子技术 第十讲
【嵌入式实时多任务微内核核心研究】
SmartDV宣布其MIPI SoundWire I3S℠ 1.0 IP产品组合已向多家客户提供授权
自行车防盗报警器
PHILIPS LPC76X PWM 实例程序
IDC:2025 年第三季度中国智能手机出货量 6846 万台
PHILIPS LPC76X Timer 实例程序
联通“白送”CDMA手机 移动将如何应对?
BOE(京东方)联合英特尔推出首款AI驱动多频显示解决方案
模拟电子技术 第八讲
CAD技术发展历程概览
无线物联网SoC内部有什么?
提高功率密度的多种烧结选项
UDC宣布收购德国默克集团OLED发光专利资产
特斯拉官宣第三代 Optimus 人形机器人产线 2026 年建成投产
由T630/T631组成的报警电路
防抢劫报警器(RCM1A/RCM1B为收发模块)
PHILIPS LPC76X TSSOP封装库
模拟电子技术 第九讲
PHILIPS LPC9xx Measure Datalogger 实...
SX-6型人体感应开关应用电路
降本增效兼顾,imc ARGUS最新推出4款数采测量模块
红外探测多路无线报警电路(TDC1808/TDC1809)
模拟电子技术 第六讲