辽宁对外经贸学院 孙 静
C是一种编译型语言.有高级语言的特点,并具备汇编语言的功能,移植性能好,便于自顶向下结构化程序设计,C语言在单片机中的应用,给开发者带来了很大的方便.软件开发者不需要对单片机硬件的结构有很深人的了解,编译器可以自动完成变量存储单元的分配.使得单片机的程序设计更加简单可靠。指针、地址、数组及其相互关系是C语言中最有特色的部分。在编写单片机的应用程序时,常常需要对端口及存储单元进行寻址.因此,掌握指针在这些寻址过程的工作原理是很有必要的,这有利于编写灵活高效的程序。
C语言中,对于指针的声明采用如下形式:类型标识符*指针变量名;由于单片机存储区的关系,所以单片机C语言的指针声明格式有别于普通C语言指针的声明格式,其格式为:
类型标识符[存储区类型]
指针变量名[指针变量存储区类型]
单片机C语言的指针的定义比普通C语言指针的定义多两个部分:存储区类型是指指针变量所指向的数据的存储区,可以是所有的数据存储类型;指针变量存储区类型是指指针变量的存放区域的数据,可以是data、ldata、xdata或pdata如下声明:unsigned char xdata *data yc;
上声明语句是指在RAM(data)内声明一指针变量yc,该指针变量指向一无符号字符型数据,该无符号型字符存在xdata区内。该指针变量的应用格式如下:
其编译后的的汇编为:MOV 08H,#00H;0x08和0x09是在片内RAM存储区分配的yc指针变量的地址空间。
单片机C语言的数组的寻址和普通C语言的寻址基本上是一样的,只是当数组存储在片内时,由于片内RAM资源十分有限,所以很难有比较复杂的数据结构,而且在编程过程中也尽量避免在片内RAM中使用较大的数组。
这是最基本的寻址方法,比如一个检测系统中,通过A/D转换把外部数据输入单片机中,单片机对这6次采样数据求和,具体程序如下:
指针指向数据存储区其其实质就是C语言中指向函数的指针这一概念,可以利用这种指针来实现函数指针调用函数。指向函数的指针变量定义格式为:类型标识符(*指针变量名)([参数1],[参数2]……);定义好后用(*指针变量名)([参数],[参数]……)即可调用这个函数。例如,主程序中要引用一个键盘扫描函数scan,程序如下所示:
对于工业控制计算机,往往设有看门狗电路,当看门狗动作使计算机复位,这就是热启动。热启动时,一般不允许从头开始,这将导致现有的已测量到或计算到的值复位,导致系统工作异常。因而在程序中必须判断是热启动还是冷启动,常用的方法是:确定某内存单位为标志位(如0x7f位和0x7e位),启动时首先读该内存单元的内容,如果它等于一个特定的值(例如两个内存单元的都是0xaa),就认为是热启动,否则就是冷启动,程序执行初始化部份,并将0xaa赋与这两个内存单元。
根据以上的设计思路,编程时,设置一个指针,让其指向特定的内存单元如0x7f,然后在程序中判断,程序如下:
然而实际调试中发现,无论是热启动还是冷启动,开机后所有内存单元的值都被复位为0,当然也实现不了热启动的要求。这是为什么呢?原来,用C语言编程时,开机时执行的代码并非是从main()函数的第一句语句开始的,在main()函数的第一句语句执行前要先执行一段“起始代码”。正是这段代码执行了清零的工作。C编译程序提供了这段起始代码的源程序,名为“startup.a51”,打开这个文件,可以看到如下代码:
可见,在执行到判断是否热启动的代码之前,起始代码已将所有内存单元清零。如何解决这个问题呢?好在启动代码是可以更改的,方法是:修改startup.a51源文件,然后用编译程序所附带的a51.exe程序对startup.a51编译,得到startup.obj文件,然后用这段代码代替原来的起始代码。具体步骤是(设C源程序名为HOTSTART.C):
修改startup.a51源文件(这个文件在C51LIB目录下)。
执行如下命令:
A51 startup.a51得到startup.obj文件。将此文件拷入HOTSTART.C所在目录。
将编好的C源程序用C51.EXE编译好,得到目标文件HOTSTART.OBJ。
用L51 HOTSTART,STARTUP.OBJ命令连接,得到绝对目标文件HOTSTART。
用OHS51 HOTSTART得到HOTSTART.HEX文件,即可。
对于startup.a51的修改,根据自已的需要进行,如将IDATALEN EQU 80H中的80H改为70H,就可以使6F到7F的16字节内存不被清零。
单片机C语言的应用是十分灵活的,要充分发挥C语言的优势,对内外部数据和程序进行方便自如的操作,必须要掌握好指针的应用。
[1]马忠棒.单片机的C语言应用程序设计[M].北京航空航天大学出版社,2001.
[2]曹聪,岳继光.单片机C语言指针的应用[J].微型电脑应用,2003.