下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、单片机中 volatile 定义的作用详解摘要:实现了一种全集成可变带宽中频宽带低通滤波器,讨论分析了跨导放大器-电容(OTAC)连续时间型滤波器的结构、设计和具体实现,使用外部可编程 电路对所设计滤波器带宽进行控制,并利用ADS软件进行电路设计和仿真验证。仿真结果表明,该滤波器带宽的可调范围为126 MHz阻带抑制率大于35 dB,带内波纹小于0. 5 dB,采用1. 8 V电源,TSMC 0 18卩m CMO工艺 库仿真,功耗小于21 mV,频响曲线接近理想状态。关键词:Butte一个定义为 volatile 的变量是说这变量可能会被意想不到地改变,这样,编译 器就不会去假设这个变量的值了
2、。精确地说就是,优化器在用到这个变量时必 须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。 下面是 volatile 变量的几个例子:1) . 并行设备的硬件寄存器(如:状态寄存器)2) . 一个中断服务子程序中会访问到的非自动变量 (Non-automatic variables)3) . 多线程应用中被几个任务共享的变量 回答不出这个问题的人是不会被雇佣的。我认为这是区分 C 程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、 RTOS 等等打交道,所用这些都要求 volatile 变量。不懂得 volatile 内容将会带来灾 难。假设被面试者
3、正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微 深究一下,看一下这家伙是不是直正懂得 volatile 完全的重要性。1) . 一个参数既可以是 const 还可以是 volatile 吗?解释为什么。2) . 一个指针可以是 volatile 吗?解释为什么。3) . 下面的函数有什么错误:int square(volatile int *ptr)return *ptr * *ptr;下面是答案:1) . 是的。一个例子是只读的状态寄存器。它是 volatile 因为它可能被意想 不到地改变。它是 const 因为程序不应该试图去修改它。2) . 是的。尽管这并不很常见。一个例子是当
4、一个中服务子程序修该一个指 向一个 buffer 的指针时。3) . 这段代码的有个恶作剧。这段代码的目的是用来返指针 *ptr 指向值的平 方,但是,由于 *ptr 指向一个 volatile 型参数,编译器将产生类似下面的代码:int square(volatile int *ptr)int a,b; a = *ptr; b = *ptr; return a * b;由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:long square(volatile int *ptr) int a;a = *ptr; return
5、 a * a;volatile 的本意是“易变的”由于访问寄存器的速度要快过 RAM ,所以编译器 般都会作减少存取外部 RAM 的优化。比如:static int i=0;int main(void)while (1)if (i) dosomething();/* Interrupt service routine. */void ISR_2(void)i=1;程序的本意是希望 ISR_2 中断产生时,在 main 当中调用 dosomething 函 数,但是,由于编译器判断在 main函数里面没有修改过i,因此 可能只执行 一次对从 i 到某寄存器的读操作,然后每次 if 判断都只使用这
6、个寄存器里面的“副本”导致dosomething永远也不会被调用。如果将将变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中 也应该如此说明。一般说来, volatile 用在如下的几个地方:1、 中断服务程序中修改的供其它程序检测的变量需要加volatile ;2、 多任务环境下各任务间共享的标志应该加volatile ;3、 存储器映射的硬件寄存器通常也要加volatile 说明,因为每次对它的读写 都可能由不同意义; 另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志 读了一半被打断了重写),在 1 中可以通过关中断来实现,2
7、中可以禁止任务调度, 3 中则只能依靠硬件的良好设计了。volatile 的本意是 “易变的 ”由于访问寄存器的速度要快过 RAM ,所以编译器一般都会作减少存取外部 RAM 的优化。比如:static int i=0;int main(void)while (1)if (i) dosomething();/* Interrupt service routine. */ void ISR_2(void)i=1;程序的本意是希望 ISR_2 中断产生时,在 main 当中调用 dosomething 函 数,但是,由于编译器判断在 main 函数里面没有修改过 i ,因此 可能只执行一次对从 i
8、 到某寄存器的读操作,然后每次 if 判断都只使用这个寄 存器里面的“副本”导致dosomething永远也不会被调用。如果将将变量加上 volatile 修饰,则编译器保证对此变量的读写操作都 不会被优化(肯定执行)。此例中 i 也应该如此说明。一般说来, volatile 用在如下的几个地方:1、 中断服务程序中修改的供其它程序检测的变量需要加volatile ;2、 多任务环境下各任务间共享的标志应该加volatile ;3、 存储器映射的硬件寄存器通常也要加volatile 说明,因为每次对它的读写 都可能由不同意义;另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志
9、 读了一半被打断了重写),在 1 中可以通过关中断来实现, 2 中可以禁止任务调度, 3 中则只能依靠硬件的良好设计了。 关键在于两个地方:1. 编译器的优化 ( 请高手帮我看看下面的理解 )在本次线程内 , 当读取一个变量时,为提高存取速度,编译器优化时有时会先 把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值; 当变量值在本线程里改变时,会同时把变量的新值 copy 到该寄存器中,以便 保持一致 当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应 用程序读取的值和实际的变量值不一致 当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用 程
10、序读取的值和实际的变量值不一致 举一个不太准确的例子: 发薪资时,会计每次都把员工叫来登记他们的银行卡号;一次会计为了省事, 没有即时登记,用了以前登记的银行卡号;刚好一个员工的银行卡丢了,已挂 失该银行卡号;从而造成该员工领不到工资 员工 原始变量地址银行卡号 原始变量在寄存器的备份2. 在什么情况下会出现 (如 1 楼所说 )1). 并行设备的硬件寄存器(如:状态寄存器)2). 一个中断服务子程序中会访问到的非自动变量 (Non-automatic variables)3). 多线程应用中被几个任务共享的变量 补充: volatile 应该解释为 “直接存取原始内存地址 ”比较合适, “易
11、变的 ”这种 解释简直有点误导人;“易变 ”是因为外在因素引起的,象多线程,中断等,并不是因为用 volatile 修 饰了的变量就是 “易变 ”了,假如没有外因,即使用 volatile 定义,它也不会变 化; 而用 volatile 定义之后,其实这个变量就不会因外因而变化了,可以放心使用了; 大家看看前面那种解释(易变的)是不是在误导人 简明示例如下:volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译 器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字 声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特 殊地址的稳定访问。使
12、用该关键字的例子如下:int volatile nVint;>>>> 当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的 内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立 刻被保存。例如:volatile int i=10;int a = i;/ 其他代码,并未明确告诉编译器,对 i 进行过操作int b = i;>>>>volatile 指出 i 是随时可能发生变化的,每次使用它的时候必须从 i 的 地址中读取,因而编译器生成的汇编代码会重新从 i 的地址读取数据放在 b 中。而优化做法是,由于编译器
13、发现两次从 i 读数据的代码之间的代码没有对 i 进行过操作,它会自动把上次读的数据放在 b 中。而不是重新从 i 里面读。这 样以来,如果 i 是一个寄存器变量或者表示一个端口数据就容易出错,所以说 volatile 可以保证对特殊地址的稳定访问。>>>> 注意,在 vc6 中,一般调试模式没有进行代码优化,所以这个关键字的 作用看不出来。下面通过插入汇编代码,测试有无 volatile 关键字,对程序最 终代码的影响:>>>> 首先,用 classwizard 建一个 win32 console 工程,插入一个 voltest.cpp 文件,
14、输入下面的代码:>>#include <stdio.h>void main()int i=10;int a = i;printf("i= %d",a);/ 下面汇编语句的作用就是改变内存中 i 的值,但是又不让编译器知道_asm mov dword ptr ebp-4, 20hint b = i;printf("i= %d",b); 然后,在调试版本模式运行程序,输出结果如下:i = 10i = 32然后,在 release 版本模式运行程序,输出结果如下:i = 10i = 10输出的结果明显表明, release 模式下,编译
15、器对代码进行了优化,第二次没 有输出正确的 i 值。下面,我们把 i 的声明加上 volatile 关键字,看看有什么 变化:#include <stdio.h>void main()volatile int i=10;int a = i;printf("i= %d",a);_asm mov dword ptr ebp-4, 20hint b = i;printf("i= %d",b);分别在调试版本和 release 版本运行程序,输出都是: i = 10i = 32 这说明这个关键字发挥了它的作用!volatile 对应的变量可能在你的程序本身不知道的情况下发生改变 比如多线程的程序,共同访问的内存当中,多个程序都可以操纵这个变量 你自己的程序,是无法判定合适这个变量会发生变化 还比如,他和一个外部设备的某个状态对应,当外部设备发生操作的时候,通 过驱动程序和中断事件,系统改变了这个变量的数值,而你的程序并不知道。 对于 volatile 类型的变量,系统每次用到他的时候都是直接从对应的内存当中 提取,而不会利用 cache 当中的原有数值,以适应它的未知何时会发生的变 化,系统对这种变量的处理不会做优化 显然也是因为它的数值
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 工程验收标准与流程培训方案
- 消防给水应急预案(3篇)
- 照明插座施工方案(3篇)
- 电缆接续应急预案(3篇)
- 终端安装施工方案(3篇)
- 节日周边活动策划方案(3篇)
- 西华道路施工方案(3篇)
- 铁塔加固施工方案(3篇)
- 霸屏营销方案(3篇)
- 2026年长沙电力职业技术学院单招职业倾向性测试题库附答案详解(培优b卷)
- 2026年六安职业技术学院单招职业适应性考试题库带答案详解(巩固)
- 2026年春苏科版(新教材)小学劳动技术四年级下册教学计划及进度表
- 2026年佳木斯职业学院单招职业技能测试题库附答案详解(黄金题型)
- 护理案例比赛分析
- 2026年南通职业大学单招职业技能测试题库带答案详解(突破训练)
- 2026年全国普通话水平测试10套真题(含答案及评分要点)
- 纺织服装行业2025年信用回顾与2026年展望-
- 2025年12月青少年机器人技术等级考试理论综合试卷四级真题(含答案)
- 2026年南京信息职业技术学院单招职业技能测试题库带答案详解(满分必刷)
- 集团公司绩效考核方案
- 2026贵州安航机械制造有限公司招聘笔试参考题库及答案解析
评论
0/150
提交评论