c語言就是其中之壹。對於習慣匯編的人來說,總覺得高級語言的‘可控性’不好,不如匯編自由。
但是,只要我們有壹定的C語言知識,有些東西還是很容易做出來的。以下是筆者在實際工作中遇到的壹些問題,希望對C51的初學者有所幫助。
壹、C51熱啟動代碼的編譯
對於工業控制計算機,通常有壹個看門狗電路。當看門狗動作時,計算機復位,這是熱啟動。
壹般情況下,熱態啟動時不允許從零開始,這會導致現有的測量值或計算值被重置,從而導致系統運行異常。
所以當壹個程序必須判斷是熱啟動還是冷啟動時,常見的方法有:確定某個內存單元為標誌位(如0x7f位和0x7e位),
啟動時,首先讀取存儲單元的內容,如果它等於特定值(例如,兩個存儲單元都是0xaa),則認為是熱啟動。
否則就是冷啟動,程序執行初始化部分,給這兩個存儲單元賦值0xaa。
按照上面的設計思路,在編程的時候,設置壹個指針指向壹個特定的存儲單元,比如0x7f,然後在程序中進行判斷。該計劃如下:
voidmain()
{ chardata * hot point =(char *)0x7f;
if((* hot point = = 0x aa)& amp;& amp(*( - HotPoint)==0xaa)
{/*熱啟動的處理*/
}
其他
{ HotPoint = 0x7e/*冷啟動處理
* HotPoint = 0xaa
*(++ hot point)= 0x aa;
}
/*正常工作代碼*/
}
但在實際調試中發現,無論是熱啟動還是冷啟動,啟動後所有存儲單元的值都被重置為0,當然也無法實現熱啟動的要求。這是為什麽呢?原來,用C語言編程時,啟動時執行的代碼並不是從main()函數的第壹句話開始,在main()函數的第壹句話執行之前,應該先執行壹段‘啟動代碼’。正是這個代碼執行清除工作。c編譯器提供了這個初始代碼的源程序,命名為CSTARTUP。A51。打開這個文件,您可以看到下面的代碼:
。
IDATALENEQU80HthelengthofIDATAmemoryinbytes。
。
STARTUP1:
IFIDATALEN & lt& gt0
MOVR0,#IDATALEN-1
CLRA
IDATALOOP:MOV@R0,A
IDATALOOP,DJNZR0
ENDIF
。
可以看出,初始代碼在執行代碼判斷是否熱啟動之前,已經清空了所有的存儲單元。如何解決這個問題?幸運的是,可以通過修改startup.a51的源文件,然後用編譯器附帶的a51.exe程序編譯startup.a51,得到startup.obj文件,然後用這段代碼替換原來的啟動代碼,來改變啟動代碼。具體步驟是(設C源程序命名為HOTSTART。c):
修改startup.a51源文件(該文件位於C51LIB目錄中)。
執行以下命令:
A51startup.a51獲取startup.obj文件。將該文件復制到HOTSTART的目錄中。C
用C51編譯編譯好的C源程序。以獲取目標文件HOTS。
酸酸的。OBJ .
連接L51HOTSTART,啟動。OBJ命令獲得絕對目標文件熱啟動。
獲得快速啟動。帶OHS 51熱啟動的十六進制文件。
startup.a51的修改要根據自己的需求進行。比如IDATALENEQU80H中的80H改為70H,6F到7F的16字節內存就不能清零。
第二,直接調用EPROM中的固化程序。
作者使用的模擬器由6位數碼管顯示,顯示子程序放在存儲器DE00H中。只要把要顯示的數字放在顯示緩沖區中,然後調用這個子程序。組裝說明如下:
LCALL0DEOOH
用C語言編程如何實現這個功能?C語言中有壹個函數指針的概念,可以用函數指針來調用函數。函數指針變量的定義格式為:
類型標識符(*指針變量名)();
定義指針後,可以給指針變量賦值以指向函數的起始地址,然後使用
(*指針變量名) ()可以調用這個函數。例如:
voidmain(無效)
{
void(* disp buffer)();/*定義指向函數的指針*/
disp buffer = 0x de 00;/*分配*/
for(;;)
{ Key();
disp buffer();
}
}
3、將浮點數轉換成字符數組
作者在編寫應用程序時有這樣壹個要求:運算結果(浮點數)存儲在EEPROM中。我們知道,浮點數在C語言中是以IEEE格式存儲的,壹個浮點數占用四個字節。例如,浮點數34.526存儲為(160,26,10,66)。在EEPROM中存儲壹個浮點數,實際上就是存儲這四個數。那麽如何在程序中得到壹個浮點數的組成呢?
存儲浮點數時,它們存儲在連續的字節中。只要妳試著找到存放地點,就能得到這些數字。可以定義壹個void的指針,將指針指向要存儲的浮點數,然後將指針強制轉換為char類型,這樣就可以使用指針獲得構成浮點數的每個字節的值。具體程序如下:
# defineuncharunsignedchar # defineintunsigned void ftoc(void)
{ floata
uchari,*px
uchar x[4];/*定義壹個字符數組來存儲四個字節的浮點數*,
void * pf
px = x;/*指針/*px指向數組x*/
pf = & ampa;/*空指針指向浮點數的第壹個地址*/
a = 34.526
for(I = 0;我& lt4;i++)
{ *(px+I)= *(char *)pf+I);/*強制void指針指向char,因為*/
}/*void指針不能操作*/
}
如果號碼已經存在EEPROM中,就要取出來合並,方法相同。請參考以下程序。
# defineuchuransignedchar # defineuintunsignedint
void of(無效)
{ floata
uchari,*px
ucharx[4]={56,180,150,73 };
void * pf
px = x;
pf = & ampa;
for(I = 0;我& lt4;i++)
{ *((char *)pf+I)= *(px+I);
}
}
上面用的C語言是FRANKLINC51VER3.2。