博文
关于volatile关键字的说明以及测试(2008-05-08 13:54:00)
摘要:词性及解释
a. 挥发性的, 可变的, 不稳定的, 飞行的, 轻快的, 爆炸性的n. 有翅动物, 挥发物【计】 易失的【医】 挥发性的【经】 不稳定的, 易变的
volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如
操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行
优化,从而可以提供对特殊地址的稳定访问。
使用该关键字的例子如下:
int volatile nVint;
当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指
令刚刚从该处读取过数据。而且读取的数据立刻被保存。
例如:
volatile int i=10;int a = i;。。。//其他代码,并未明确告诉编译器,对i进行过操作int b = i;
volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的
汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间
的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来,如果
i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问
。
注意,在vc6中,一般调试模式没有进行代码优化,所以这个关键字的作用看不出来。下面通过插入汇编
代码,测试有无volatile关键字,对程序最终代码的影响:
首先用classwizard建一个win32 console工程,插入一个voltest.cpp文件,输入下面的代码:
#include <stdio.h>void main(){ int i=10; int a = i;
printf("i= %d\n",a); //下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道 __asm { mov dword p......
FIFO(2008-05-08 09:55:00)
摘要:一、先入先出队列(First Input First Output,FIFO)这是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令。1.什么是FIFO?FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。2.什么情况下用FIFO?FIFO一般用于不同时钟域之间的数据传输,比如FIFO的一端时AD数据采集,另一端时计算机的PCI总线,假设其AD采集的速率为16位 100K SPS,那么每秒的数据量为100K×16bit=1.6Mbps,而PCI总线的速度为33MHz,总线宽度32bit,其最大传输速率为1056Mbps,在两个不同的时钟域间就可以采用FIFO来作为数据缓冲。另外对于不同宽度的数据接口也可以用FIFO,例如单片机位8位数据输出,而DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。3.FIFO的一些重要参数FIFO的宽度:也就是英文资料里常看到的THE WIDTH,它只的是FIFO一次读写操作的数据位,就像MCU有8位和16位,ARM 32位等等,FIFO的宽度在单片成品IC中是固定的,也有可选择的,如果用FPGA自己实现一个FIFO,其数据位,也就是宽度是可以自己定义的。FIFO的深度:THE DEEPTH,它指的是FIFO可以存储多少个N位的数据(如果宽度为N)。如一个8位的FIFO,若深度为8,它可以存储8个8位的数据,深度为12 ,就可以存储12个8位的数据,FIFO的深度可大可小,个人认为FIFO深度的计算并无一个固定的公式。在FIFO实际工作中,其数据的满/空标志可以控制数据的继续写入或读出。在一个具体的应用中也不可能由一些参数算数精确的所需FIFO深度为多少,这在写速度大于读速度的理想状态下是可行的,但在实际中用到的FIFO深度往往要大于计算值。一般来说根据电路的具体情况,在兼顾系统性能和FIFO成本的情况下估算一个大概的宽度和深度就可以了。而对于写速度慢于读速度的应用,FIFO的深度要根据读出的数据结构和读出数据的由那些具体的要求来确定。满......
意大利运动品牌kappa公然出售藏独衫(2008-05-07 19:29:00)
摘要:
http://newspic.cn.yahoo.com/news/article/index.html?type=gallery_show&p=88590......
C语言高效编程的的四招技巧(2008-05-06 20:23:00)
摘要:引言:
编写高效简洁的c语言代码,是许多软件工程师追求的目标。本文就工作中的一些体会和经验做相关的阐述,不对的地方请各位指教。
第一招:以空间换时间
计算机程序中最大的矛盾是空间和时间的矛盾,那么,从这个角度出发逆向思维来考虑程序的效率问题,我们就有了解决问题的第1招--以空间换时间。
例如:字符串的赋值。
方法a:通常的办法:
#define len 32char string1 [len];memset (string1,0,len);strcpy (string1,"this is a example!!");
方法b:
const char string2[len] ="this is a example!";char * cp;cp = string2 ;
使用的时候可以直接用指针来操作。
从上面的例子可以看出,a和b的效率是不能比的。在同样的存储空间下,b直接使用指针就可以操作了,而a需要调用两个字符函数才能完成。b的缺点在于灵活性没有a好。在需要频繁更改一个字符串内容的时候,a具有更好的灵活性;如果采用方法b,则需要预存许多字符串,虽然占用了大量的内存,但是获得了程序执行的高效率。
如果系统的实时性要求很高,内存还有一些,那我推荐你使用该招数。该招数的变招--使用宏函数而不是函数。举例如下:
方法c:
#define bwmcdr2_address 4#define bsmcdr2_address 17int bit_mask(int __bf) { return ((1u << (bw ## __bf)) - 1) << (bs ## __bf);}void set_bits(int __dst, int __bf, int __val){ __dst = ((__dst) & ~(bit_mask(__bf))) | (((__val) << (bs ## __bf)) & (bit_mask(__bf))))}
set_bits(mcdr2, mcdr2_address, registernumber);
方法d:
#define bwmcdr2_address 4#define bsmcdr2_address 17#de......
51读写x5045存储器的程序(2008-04-24 21:38:00)
摘要:X5045是一种集看门狗、电压监控和串行EEPROM 三种功能于一身的可编程控制电路.特别适合应用在需要少量存储器,并对电路板空间需求较高场合,
X5045具有电压监控功能,可以保护系统免受低电压的影响,当电源电压降到允许范围(4.2V)以下时,系统将复位,直到电源电压返回到稳定值为止。X5045的存储器与CPU 通过串行通信方式接口(SPI),可以存放512个字节数据.可擦写100万次,数据可保存100年.
下图是X5045与具有手动复位的8051微控制器的连接
下边是51读写x5045存储器的程序
//x5045和51的连接方法sbit CS = P1^0; sbit SO = P1^3;sbit SI = P1^1;sbit SCK = P1^2; //定义寄存器指令#define WREN 0x06 // 写入使能指令(WREN)#define WRDI 0x04 // 写入禁止指令(WRDI)#define WRSR 0x01 // 写入状态寄存器指令(WRSR)#define RDSR 0x05 // 读取状态寄存器指令(RDSR)#define WRITE 0x02 // 写入存储器指令(WRITE)#define READ 0x03 // 读取存储器指令(READ) #define STATUS_REG 0x00 // 要写入到状态寄存器的值 #define MAX_POLL 0x99 // 最在查询次数m number of
void outbyte(unsigned char write_data){ unsigned char i; for(i = 0; i < 8; i++) { &n......
X5045 电路及其应用(2008-04-24 21:37:00)
摘要:摘要: X5045是一种集看门狗、电压监控和串行EEPROM 三种功能于一身的可编程控制电路。文中介绍了它的主要特点和工作原理,同时结合8051 单片机给出了MPU 与X5045的接口电路与相应的读写程序。
关键词:看门狗; 8051 ;微控制器;X5045
X5045是一种集看门狗、电压监控和串行EEPROM 三种功能于一身的可编程电路。这种组合设计减少了电路对电路板空间的需求。
X5045中的看门狗对系统提供了保护功能。当系统发生故障而超过设置时间时,电路中的看门狗将通过RESET信号向CPU 作出反应。X5045提供了三个时间值供用户选择使用。它所具有的电压监控功能还可以保护系统免受低电压的影响,当电源电压降到允许范围以下时,系统将复位,直到电源电压返回到稳定值为止。X5045的存储器与CPU 可通过串行通信方式接口,共有4096个位,可以按512 x 8个字节来放置数据。
1 引脚介绍
X5045的管脚排列如图1 所示,它共有8个引脚,各引脚的功能如下:
CS :电路选择端,低电平有效;
SO :串行数据输出端;
SI :串行数据输入端;
SCK:串行时钟输入端;
WP :写保护输入端,低电平有效;
RESET :复位输出端;
VCC :电源端;
VSS :接地端。
2 工作原理
2.1 上电复......
交流电(2008-04-23 21:24:00)
摘要:简称“交流”。一般指大小和方向随时间作周期性变化的电压或电流。它的最基本的形式是正弦电流。我国交流电供电的标准频率规定为50赫兹。交流电随时间变化的形式可以是多种多样的。不同变化形式的交流电其应用范围和产生的效果也是不同的。以正弦交流电应用最为广泛,且其他非正弦交流电一般都可以经过数学处理后,化成为正弦交流电的迭加。正弦电流(又称简谐电流),是时间的简谐函数i=Imsin(ωt+φ0)当线圈在磁场中匀速转动时,线圈里就产生大小和方向作周期性改变的交流电。现在使用的交流电,一般是方向和强度每秒改变52赫兹。我们常见的电灯、电动机等用的电都是交流电。在实用中,交流电用符号"~"表示。 电流i随时间的变化规律,由此看出:正弦交流电需用频率、峰值和位相三个物理量来描述。交流电所要讨论的基本问题是电路中的电流、电压关系以及功率(或能量)的分配问题。由于交流电具有随时间变化的特点,因此产生了一系列区别于直流电路的特性。在交流电路中使用的元件不仅有电阻,而且有电容元件和电感元件,使用的元件多了,现象和规律就复杂了。【交流电的频率和周期】频率是表示交流电随时间变化快慢的物理量。即交流电每秒钟变化的次数叫频率,用符号f表示。它的单位为周/秒,也称赫兹常用“Hz”表示,简称周或赫。例如市电是50周的交流电,其频率即为f=50周/秒。对较高的频率还可用千周(kC)和兆周(MC)作为频率的单位。1千周(kC)=103周/秒1兆周(MC)=10千周(kC)=106周/秒例如,我国第一颗人造地球卫星发出的讯号频率是20.009兆周,亦即它发出的是每秒钟变化20.009×106次的交变讯号。交流电正弦电流的表示式中I = Imsin(ωt+φ0)中的ω称为角频率,它也是反映交流电随时间变化的快慢的物理量。角频率和频率的关系为ω=2πf。交流电随时间变化的快慢还可以用周期这个物理量来描述。交流电变化一次所需要的时间叫周期,用符号T表示。周期的单位是秒。显然,周期和频率互为例数,即由此可见,交流电随时间变化越快,其频率f越高,周期 T越短;反之,频率f越低,周期T越长。【交流电流的峰值】 简谐函数(又称简谐量)是时间的周期函数。其简谐电流i=Imsin(εt+α)中的Im叫做电流的峰值,i为瞬时值。应该指出,峰值和位相是按上式中Im为正值的要求定义的。如对下面形式的函数i=-5sin(ωt+α)不应......
C++中const总结(2008-04-17 21:44:00)
摘要:一:对于基本声明 1.const int r=100; //标准const变量声明加初始化,因为默认内部连接所以必须被初始化,其作用域 为此文件,编译器经过类型检查后直接用100在编译时替换. 2.extend const int r=100; //将const改为外部连接,作用于扩大至全局,编译时会分配内存,并且可以不进行 初始化,仅仅作为声明,编译器认为在程序其他地方进行了定义. 3.const int r[]={1,2,3,4}; struct S {int a,b;}; const S s[]={(1,2),(3.4)}; //以上两种都是常量集合,编译器会为其分配内存,所以不能在编译期间使用其中 的值,例如:int temp[r[2]];这样的编译器会报告不能找到常量表达式 二:对于指针 1.const int *r=&x; //声明r为一个指向常量的x的指针,r指向的对象不能被修改,但他可以指向任何 地址的常量. 2.int const *r=&x;//与用法1完全等价,没有任何区别。 3.int * const r=&x; //声明r为一个常量指针,他指向x,r这个指针的指向不能被修改,但他指向的地址 的内容可以修改. 4.const int * const r=&x; //综合1,3用法,r是一个指向常量的常量型指针. 三:对于类型检查 可以把一个非const对象赋给一个指向const的指针,因为有时候我们不想从这个 指针来修改其对象的值,但是不可以把一个const对象赋值给一个非const指针, 因为这样可能会通过这个指针改变指向对象的值,但也存在使这种操作通过的合 法化写法,使用类型强制转换可以通过指针改变const对象: const int r=100; int *ptr=const_cast <int*> (&r);//C++标准,C语言使用:int* ptr =(int*)&r; 四:对于字符数组 如char * name = "china "; 这样的语句,在编译时是能够通过的,但是 "china "是常量字符数组,任何想修改 他的操作也能通过编译但会引起运行时错误,如果我们想修改字符数组的话就要 使用char name[]= "china ";这种形式. 五:对于函数 1.vo......
CONST(2008-04-17 21:40:00)
摘要:C中CONST的使用:const是一个C语言的关键字,它限定一个变量不允许被改变。使用const在一定程度上可以提高程序的健壮性,另外,在观看别人代码的时候,清晰理解const所起的作用,对理解对方的程序也有一些帮助。 虽然这听起来很简单,但实际上,const的使用也是c语言中一个比较微妙的地方,微妙在何处呢?请看下面几个问题。 问题:const变量 & 常量 为什么我象下面的例子一样用一个const变量来初始化数组,ANSI C的编译器会报告一个错误呢? const int n = 5; int a[n]; 答案与分析: 1)、这个问题讨论的是“常量”与“只读变量”的区别。常量肯定是只读的,例如5, “abc”,等,肯定是只读的,因为程序中根本没有地方存放它的值,当然也就不能够去修改它。而“只读变量”则是在内存中开辟一个地方来存放它的值,只不过这个值由编译器限定不允许被修改。C语言关键字const就是用来限定一个变量不允许被改变的修饰符(Qualifier)。上述代码中变量n被修饰为只读变量,可惜再怎么修饰也不是常量。而ANSI C规定数组定义时维度必须是“常量”,“只读变量”也是不可以的。 2)、注意:在ANSI C中,这种写法是错误的,因为数组的大小应该是个常量,而const int n,n只是一个变量(常量 != 不可变的变量,但在标准C++中,这样定义的是一个常量,这种写法是对的),实际上,根据编译过程及内存分配来看,这种用法本来就应该是合理的,只是 ANSI C对数组的规定限制了它。 3)、那么,在ANSI C 语言中用什么来定义常量呢?答案是enum类型和#define宏,这两个都可以用来定义常量。 问题:const变量 & const 限定的内容 下面的代码编译器会报一个错误,请问,哪一个语句是错误的呢? typedef char * pStr; char string[4] = "abc"; const char *p1 = string; const pStr p2 = string; p1++; p2++; 答案与分析: 问题出在p2++上。 1)、const使用的基本形......
机械电能表的工作原理浅释(2008-04-17 21:05:00)
摘要:电能表的工作原理是:当把电能表接入被测电路时,电流线圈和电压线圈中就有交变电流流过,这两个交变电流分别在它们的铁芯中产生交变的磁通;交变磁通穿过铝盘,在铝盘中感应出涡流;涡流又在磁场中受到力的作用,从而使铝盘得到转矩(主动力矩)而转动。负载消耗的功率越大,通过电流线圈的电流越大,铝盘中感应出的涡流也越大,使铝盘转动的力矩就越大。即转矩的大小跟负载消耗的功率成正比。功率越大,转矩也越大,铝盘转动也就越快。铝盘转动时,又受到永久磁铁产生的制动力矩的作用,制动力矩与主动力矩方向相反;制动力矩的大小与铝盘的转速成正比,铝盘转动得越快,制动力矩也越大。当主动力矩与制动力矩达到暂时平衡时,铝盘将匀速转动。负载所消耗的电能与铝盘的转数成正比。铝盘转动时,带动计数器,把所消耗的电能指示出来。这就是电能表工作的简单过程。......
