- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
WIN AVR AVR-GCC 中如何使用 volatile 关键字volatile 的字面含义是易变的,那么将一个变量指示为 volatile是什么意思呢?是告诉编译器这个变量是易变的?事实上也是如此。在多任务、中断等环境下,变量可能被其他的任务改变,而编译器无法发现,volatile 就是告诉编译器这个变量在其它任务(或中断)中可能要修改。使用 volatile是与编译器优化有关系的。先看看下面的例子:#include avr/io.hunsigned char g_Flag=0;int main(void){g_Flag=1;g_Flag=0;while(1);}main程序中对g_Flag先赋值1,后赋值0, 显然g_Flag=1是没有意义的,聪明的编译器发现这个后就产生了如下的代码:int main(void){5c: cf e5 ldi r28, 0x5F ; 955e: d4 e0 ldi r29, 0x04 ; 460: de bf out 0x3e, r29 ; 6262: cd bf out 0x3d, r28 ; 61g_Flag=1;g_Flag=0;64: 10 92 60 00 sts 0x0060, r1while(1);68: ff cf rjmp .-2 ; 0x68 main+0xc编译器没有生成 g_Flag=1 的机器码, 在优化过程中 g_Flag=1被忽略了。在一般的 C程序中这是没有问题的,但是如果 g_Flag 是个单片机 I/O口变量那就麻烦了,本来想从 I/O口输出一逻辑正脉冲的程序就这样被编译器优化掉了,显然不是我们所希望的。这时候该怎么办呢?请拿出利剑 volatile,他能处理我们所遇到的麻烦。将 unsigned char g_Flag=0; 该为 volatile unsigned char g_Flag=0;后编译所产生的汇编代码如下:int main(void){5c: cf e5 ldi r28, 0x5F ; 955e: d4 e0 ldi r29, 0x04 ; 460: de bf out 0x3e, r29 ; 6262: cd bf out 0x3d, r28 ; 61g_Flag=1;64: 81 e0 ldi r24, 0x01 ; 166: 80 93 60 00 sts 0x0060, r24g_Flag=0;6a: 10 92 60 00 sts 0x0060, r1while(1);6e: ff cf rjmp .-2 ; 0x6e main+0x12在 《AVR 单片机 GCC 程序设计》第二章中我们展开了 PORTB 这个宏, 对于 AT90S2313它等同于 *(volatile unsigned char *)(0x38) ,现在你一定相信这里的 volatile是必不可少的。尽管如此,有人会认为 “在一般的程序中不需要定义端口宏,因为 avr-libc 都为我们定义好了,我只要包含 io.h 就可以了,在用户程序中 volatile 是无关紧要的” ,那么让我们再来看一下 volatile必不可少的另一种情况。#include avr/io.h#include avr/interrupt.hunsigned char g_Flag=0;//串口接收标记ISR(SIG_UART_RECV){... ...g_Flag=1;}int main(void){... ...while(!g_Flag);//等待串口接收到数据... ...}上面的程序看似没有任何问题,实际上 main 函数是永远也发现不了串口接收数据的。由于编译器的优化,while(!g_Flag)将生成一个非常有意思的代码,它首先从 g_Flag 对应的内存读一次数据到一个寄存器中,之后不停的测试此寄存器是否为非零,即使中断程序中已经改变了 g_Flag 对应内存的值,它还是始终检查一个不再更新的寄存器。那么如何让 while循环每次都要从内存读取后再测试它是否为零呢?你应该猜到了,就是将 g_Flag 变量指示为 volatile,告诉编译器 g_Flag 是易变的,要对它进行保守处理。volatile 是一种优化指示,编译器优化操作使用一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,从而可以消除死代码。但有时这优化不是程序所希望的,这时可以用 volatile 关键字关闭这个优化开关。最后提醒读者,没有必要将所有的变
您可能关注的文档
最近下载
- COLMO洗衣机工程师资格认证考试题及答案.doc VIP
- 《合理用药与用药安全》课件.ppt VIP
- 配件部经理岗位职责(24篇).docx VIP
- (人教2024版)英语八年级上册Unit 4 大单元教学设计(新教材).docx
- TCECS 179-2023 健康住宅建设技术规程.pdf VIP
- 数字孪生及车间实践第二篇数字孪生研究体系.pptx VIP
- 2025年四川省绵阳市初中学业水平考试语文真题试卷含参考答案与习作例文精品.pdf VIP
- 2024版行政管理培训课件.pptx VIP
- 《公安机关互联网安全监督检查规定》培训与解读课件.pptx VIP
- 数字孪生及车间实践第一篇数字孪生的内涵及研究应用现状.pptx VIP
文档评论(0)