当前位置:首页 > 单片机 > 单片机
[导读]一个AVR与串口通信的基本程序,部分代码如下:unsigned int flag = 0;……ISR(USART_RXC_vect){flag = 1;}……int main(void){while(0 == flag){code……}}程序在Winavr环境下编译成功,烧写运行后发现,程序并没有按

一个AVR与串口通信的基本程序,部分代码如下:

unsigned int flag = 0;

……

ISR(USART_RXC_vect)

{

flag = 1;

}

……

int main(void)

{

while(0 == flag)

{

code……

}

}

程序在Winavr环境下编译成功,烧写运行后发现,程序并没有按照我预想的那样,出现了这样的现象:程序一直在while里面没有出来,flag的值并没有变化。但是发现,程序确实进入了中断,但是却为什么不能改变变量呢。真是有鬼啦!

一番周折之后,终于在国外的一个网站上找到了相似的问题。于是豁然开朗。

flag变量被编译器在优化的时候认为,它在循环之外不可能被改变,于是编译器就只对它访问一次,而优化(optimize)了其他的访问(就是我们这里对flag在中断中的访问),所以,引用我老师的一句名言,问题就来啦。

这里需要稍微提一下编译器的小知识,我们也许都听过Debug和release吧?一个是调试版本,一个是最终完成版本。可不要被表面的意思给迷惑了。在Debug版本中,有很多的类似

#if Debug

(code)

#else

(other code)

#endif

这样的语句,他们就是为了方便调试用的,当调试成功之后,将debug值设置为0,就有许多代码被忽略了。这里只是简单的说一下两个版本的区别,真正的区别还有更多,更复杂,我才疏学浅,也要好好学习。总之,就是说,release版本会对代码进行非常多的优化,将代码大大简化,效率提高,例如注释,对一个变量的访问次数等等,细致末节都会有差异。

那么,上面的问题怎么解决呢。其实很简单。

将flag变量进行如下声明:

volatile unsigned int flag;

好,我们来看看这个volatile是干什么的,先看如下代码:

int i = 10;

int j = i;

int k = i;

i变量和我们上面所说的flag变量一样,只是“普通的”被声明了一下,没有声明为volatile变量。编译器在编译的时候,看到上面的三句话,i没有被用作左值,也就是i没有被改变,那么“优化”就来啦:在i对j赋值完之后,这个内存并没有被丢掉,而是放到了一个地方。然后继续对k进行赋值。这样做的好处就是只对i的内存进行了一次访问,而不是每次都访问。因为每次访问一个内存也是很累的一件事情。就像你要跑到A和B那里去送一个文件,给了A之后,你难道还想再回家再拿一遍东西给B吗,还是在A的家里把东西复印一下,然后直接送给B?这就是编译器的一个小优化的示例。

而当我们加了Volatile这个关键字之后,就不同了。

volatile int i = 10;

Volatile是容易改变的意思,就是告诉编译器:“这个变量很重要啊,很容易变化啊,你要每次都对他访问哦,保证你读的值一定是当前的值哦!”所以,编译器,就会对i访问两遍,而不是一遍啦。

说到这里,我想你明白了,为什么将flag变量加上这个关键字之后就可以被程序更新值了吧。写的可能有不对之处,欢迎拍砖指教。


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

AVR单片机是1997年由ATMEL公司研发出的增强型内置Flash的RISC(Reduced Instruction Set CPU) 精简指令集高速8位单片机。AVR的单片机可以广泛应用于计算机外部设备、工业实时控制...

关键字: AVR 单片机 计算机

AVR单片机是1997年由ATMEL公司研发出的增强型内置Flash的RISC(Reduced Instruction Set CPU) 精简指令集高速8位单片机。可以广泛应用于计算机外部设备、工业实时控制、仪器仪表、通...

关键字: AVR 单片机 计算机

AVR与传统类型的单片机相比,除了必须能实现原来的一些基本的功能,其在结构体系、功能部件、性能和可靠性等多方面有很大的提高和改善。 但使用更好的器件只是为设计实现一个好的系统创造了一个好的基础和可能性,如果还采用和沿袭以...

关键字: AVR 单片机 硬件

在这篇文章中,小编将为大家带来AVR单片机的相关报道。如果你对本文即将要讲解的内容存在一定兴趣,不妨继续往下阅读哦。

关键字: AVR 单片机

在下述的内容中,小编将会对AVR单片机的相关消息予以报道,如果AVR单片机是您想要了解的焦点之一,不妨和小编共同阅读这篇文章哦。

关键字: AVR 单片机

C语言是一种高级程序设计语言,它提供了十分完备的规范化流程控制结构。因此采用C51语言设计单片机应用系统程序时,首先要尽可能地采用结构化的程序设计方法,这样可使整个应用系统程序结构清晰,易于调试和维护。对于一个较大的程序...

关键字: C51语言 变量 存储

定义一个变量,就是在内存中为你定义的这个变量开辟一段内存空间,如果这个变量没有初始化,那么系统会随机给这个变量赋一个值,这个值我一般称它为"垃圾数"。没有初始化的变量我认为它是没有意义的,是在浪费内存,就比如人刚出生的时...

关键字: 变量 初始化 赋值

如果你是在Linux下做开发,你就必须知道Makefile是什么东西,如果不知道那就可以说你不是一个合格的Linux开发工程师,因为Makefile是必备的一项技能。那么,Makefile到底有什么作用呢?首先,gcc大...

关键字: Linux Makefile gcc

用静态局部变量,还是临时变量,要牵涉到你项目具体情况,比如:RAM资源、代码运行效率等。(临时变量还会有一个数据拷贝过程)所以,该如何分配堆栈,该用静态还是临时变量,需要综合考虑你项目的情况而定。

关键字: 静态局部 变量 项目

杰成医疗(健适医疗成员企业)的"经血管介入生物主动脉瓣膜"在国内首次得到成功应用,两名心脏瓣膜病患者通过经导管主动脉瓣置换术(TAVR)各被植入一枚"杰成经血管介入瓣膜"。杰成医疗已计划对该产品在全球范围内开展多个前瞻性...

关键字: AVR
关闭
关闭