知識貼|大牛精心總結的C51編程經驗三則

(1)C51熱啟動代碼的編制

工業控制計算機,往往設有看門狗電路,看門狗動作,計算機復位,這就是熱啟動。熱啟動時,一般不允許程序從頭開始,因為這將使測量或計算值復位,導致系 統工作異常。故程序必須判斷是熱啟動還是冷啟動。常用的方法是:設定某內存單位為標志位(如0x7f位和0x7e位),啟動時首先讀該內存單元的內容,如 果它等于一個特定的值(例如兩個內存單元的都是0xaa),就認為是熱啟動,否則就是冷啟動,程序執行初始化部分,并將0xaa賦予這兩個內存單元。

根據以上的設計思路,編程時,設置一個指針,指向特定的內存單元如0x7f,然后在程序中根據特定內存單元的值判斷冷/熱啟動,程序如下:

void main()

{  char data*HotPoint=(char*)0x7f;

if((*HotPoint==0xaa)&&(*(--Hot

Point)==0xaa))

{     /*熱啟動的處理   */

}

else

{  HotPoint=0x7e; /*冷啟動的處理

*HotPoint-0xaa;

*(++HotPoint)=0xaa;

}

/*正常工作代碼*/

}

實際調試中發現,無論是熱啟動還是冷啟動,開機后所有內存單元的值都被復位為0,實現不了熱啟動的要求。這是為什么呢?原來,用C語言編程時,開機時執 行的代碼并非是從main()函數的第一語句開始的,在main()函數的第一語句執行前要先執行一段‘起始代碼’。正是這段代碼執行了內存清零的工作。 C編譯程序提供了這段起始代碼的源程序,名為CSTARTUP A51,打開這個文件,可以看到如下代碼:

IDATALEN EQU 8011 the length of IDATA memory m bytes

STARTUP1:

IF IDATALEN0

MOV R0,#IDATALEN-I

CLR A

IDATALOOP:  MOV @R0,A

DJNZ R0,IDATALOOP

ENDIF

可見,在執行到判斷是否熱啟動的代碼之前,起始代碼已將所有內存單元清零。如何解決這個問題呢?好在起始代碼是可以更改的,方法是:修改 startup.a51源文件,然后用編譯程序所附帶的a51.exe程序對startup.a51編譯,得到startup.obj文件,用這段代碼代 替原來的起始代碼。具體步驟是(設C源程序名為HOTSTART C):

1. 修改startup.a51源文件(這個文件在C51/LIB目錄下)。

2. 執行如下命令:A51 startup.a51得到startup.obj文件。將此文件拷入HOTSTART C所在目錄。

3.將編好的C源程序用C51 EXE編譯好,得到目標文件HOTSTART OBJ。

4.用L51 HOTSTART,STARTUP OBJ命令連接,得到絕對目標文件HOTSTART。

5.用OHS51 HOTSTART得到HOTSTART HEX文件,即可完成啟動代碼的修改。

對于startup.a51的修改,根據自己的需要進行,如將IDATALEN EQU 80H中的80H改為70H,就可以使6F到7F的16字節內存不被清零。

(2)直接調用EPROM中已固化的程序

筆者用的仿真機,由6位數碼管顯示,在DE00H處存放顯示子程序,只要將顯示的數存入顯示緩沖區,然后調用顯示子程序就可以了,匯編指令為:

LCALL 0DE00H

在用C語言編程時,如何實現這一功能呢?C語言中有指向函數的指針這一概念,可以用來實現用函數指針調用函數。指向函數的指針變量的定義格式為:

類型標識符(*指針變量名)();

在定義好指針后就可以給指針變量賦值,使其指向某個函數的開始地址,然后用(*指針變量名)()即可調用這個函數。程序如下例:

void main(void)

{

void (*DispBuffer)();/*定義指向函數指針*/

DispBuffer=0xde00; /*賦值*/

for(;;)

{ Key();

DispBuffer();

}

}

(3)將浮點數轉化為字符數組

筆者在編制應用程序時有這樣的要求:將運算的結果(浮點數)存入E2PROM中。我們知道,浮點數在C語言中是以IEEE格式存儲的,一個浮點數占四個 字節。例如浮點數34 526存為160、26、10、664個數。要將該浮點數存入E2PROM,實際上就是要存這四個數。如何在程序中得到一個浮點數 的組成數呢?

浮點數在存儲時,是存儲在連續的字節中的,只要設法找到存儲位置,就可以得到這些數了。可以定義一個void指針,將此指針指向需要存儲的浮點數,然后再將此指針強制轉化為char型。這樣,利用指針就可以得到組成該浮點數的各個字節的值了。具體程序如下:

#define uchar unsigned char

#define uint unsigned int

void FtoC(void)

{  float a;

uchar I,*px

uchar x[4];/*定義字符數組,準備存儲浮點數的四個字節*/

void *pf;

px=x; /*px指針指向數組x*/

pf=&a;/*void型指針指向浮點數首地址*/

a=34.526;

for(I=0;I { *(px+I)=*((char *)pf+I);/*強制void型指針轉成char型,因為void型指針不能運算*/

}

}

如果已將數存入E2PROM,要將其取出合并,方法也是一樣,可參考下面的程序。

#define uchar unsigned char

#define uint unsigned int

void CtoF(void)

{  float a;

uchar I,*px

uchar x[4]-{56,180,150,73};

void *pf;

px=x;

pf=&a;

for(I=o;I { *((char *)pf+I)=*(px+I)

}

}

以上程序所用C語言為FRANKLIN C51 VER 3 2。

本文轉載自:21ic電子網

免責聲明:本文系網絡轉載,版權歸原作者所有。如涉及作品版權問題,請與我們聯系,我們將根據您提供的版權證明材料確認版權并支付稿酬或者刪除內容。

the end

評論(0)