内江瓷蛋医疗科技有限公司

C語(yǔ)言編程在智能化重力加速度測試儀中的應用

當前位置:首頁(yè) >> 儀器儀表技術(shù)文章

C語(yǔ)言編程在智能化重力加速度測試儀中的應用

摘要在基于單片機的智能化重力加速度測試儀中采用C語(yǔ)言輔程苘化了程序設計任
務(wù),對于匯輔語(yǔ)言難干處理的浮點(diǎn)數運算及扳字打印輸出可通過(guò)C語(yǔ)言箱譯罌的內部庫函數調
用實(shí)現。舟紹了一種專(zhuān)為8051系列單片機設計的C語(yǔ)言輔譯器Franklin C51,它具有代碼優(yōu)化
功能,能產(chǎn)生極高效率的機器碼,并且提供了豐富的內部函數庫。描述了C51函數庫所支持的
IEEE標準浮點(diǎn)數的內存格式 及采用sprintf0函數處理包括漢字在內的各種字符串的方法。給
出了測試儀的輸出結果。電導計| 水分測定儀| 濁度計| 色度計| 粘度計| 折射計| 滴定儀| 密度計| 熱流計| 濃度計| 折射儀| 采樣儀|

單片機在工業(yè)測量控制領(lǐng)域內獲得了十分廣泛的應用-】J。一般在研制單片機應用系統
時(shí)太多采用 編語(yǔ)言作為軟件工具。但是,當程序中需要采用浮點(diǎn)數運算時(shí),用忙編語(yǔ)言編
寫(xiě)程序十分麻煩;如果程序中需要進(jìn)行漢字處理,則用匯編語(yǔ)言編程的效率極低。為了提
高程序的編寫(xiě)效率,只有采用高級語(yǔ)言編程。c語(yǔ)言是目前公認的一種高效率計算機開(kāi)發(fā)用
高級程序設計語(yǔ)言口],它既能象匯編語(yǔ)言那樣直接操作機器硬件,又能很方便地進(jìn)行各種
數學(xué)運算和字符處理。筆者結合實(shí)例介紹采用美國Franklin軟件公司推出的c語(yǔ)言編譯器
一C51開(kāi)發(fā)8051單片機應用系統中浮點(diǎn)數運算和漢字打印程序的原理和方法。
1 C51編譯器的特殊擴充
C51編譯器采用符合ANSI標準的c語(yǔ)言進(jìn)行編程,為了滿(mǎn)足8051系列單片機哈福
結構存儲器的需要[3],C51編譯器擴展了說(shuō)明存儲器類(lèi)型的關(guān)鍵字data:(可直接尋址的內
部RAM 區O~7FH);bdata:(可位尋址的內部RAM 區20H 2FH);iclata;(可閫接尋址
的內部RAM 區0~0FFH);pdata:(分頁(yè)尋址的外部RAM 區256頁(yè)×256字節);xdata:
(外部RAM 區O~0FFFFH);code:(ROM 區0~0FFFFH)。FranklinC51編譯器對于變量
的定義符合ANSI C標準,即可以定義多維數組,可以通過(guò)指針進(jìn)行變量訪(fǎng)問(wèn),可以將若
干個(gè)變量組成為結構和聯(lián)合等。還擴展了可用來(lái)簡(jiǎn)化對8051單片機內部特殊功能寄存器
及可尋址位訪(fǎng)問(wèn)的%bit”和“sfr 數據類(lèi)型 在每個(gè)變量的聲明中可采用上述關(guān)鍵字明確
指定變量的存儲器類(lèi)型。如果在定義變量時(shí)不指定其存儲器類(lèi)型,則按編譯時(shí)給出的存儲
模式來(lái)決定變量的存儲區域。表1列出了Franklin C51編譯器所支持的存儲器模式。這3種存儲器模式各有優(yōu)缺
點(diǎn),SMALL模式下參數
的傳遞是在內部RAM 中
完成的,COMPACT 和
LARGE允許參數傳遞在
外部RAM 中進(jìn)行。由于
衰1 Franklin C51編譯囂的存儲囂橫式
存儲模式 說(shuō) 明
SMALl 參數和局部變量存^可直接尋址的內部RAM(默認值為data)
COMPACT 參數和局部變量存人分頁(yè)外部RAM(默認值為0aat~)
LARGE 參數和局部變量直接存^外部RAM(默認值為xdata)
8051單片機訪(fǎng)問(wèn)內部RAM 的速度比訪(fǎng)問(wèn)模式下外部RAM要快得多,因此可將需要經(jīng)常
使用的變量放在內部RAM 中,而將那些較大及很少使用的變量放在外部RAM 中。另外
若將變量放在外部RAM 中時(shí),還會(huì )使程序編譯后產(chǎn)生的有效代碼加長(cháng)。C51編譯器對于局
部變量采用了靜態(tài)覆蓋技術(shù)來(lái)提高內部RAM 的使用效率,因此在實(shí)際編程時(shí)只要有可
能,應盡量采用局部變量。
2 C51編譯器支持的浮點(diǎn)數格式
C51編譯器支持的浮點(diǎn)數采用關(guān)鍵字float來(lái)進(jìn)行聲明,它是滿(mǎn)足IEEE一754標準的32
位單精度浮點(diǎn)數,占用四個(gè)存儲器單元,在內存中按從低到高的地址順序存儲.格式如下
地址 +0 +1 +2 +3
內容MMMMMMMM MMMMMMMM E MMMMMMM S EEEEEEE
其中,最高位S為符號位,0表示正數,1表示負數。從次高位開(kāi)始的8位EEEEEEEE占用
了兩個(gè)字節,用來(lái)表示浮點(diǎn)數的階碼,為了避免出現負階碼值,并不用實(shí)際指數作為階碼,
而是將實(shí)際指數加上偏移量127之后再作為階碼。指數可正可負,其范圍是一127~+128,
加上127之后便使階碼在o~255的范圍之內。階碼之后是浮點(diǎn)數尾數的小數部分,共23
位,占用3個(gè)字節。尾數的整數部分永遠是1,所以不予表示,但它是隱含存在的,因此尾
數實(shí)際上應視為24位。例如將+124.75用IEEE一754標準的單精度浮點(diǎn)數表示為(16進(jìn)
制數)42F98000H,在內存中的存儲格式為
地址 +0 +1 +2 +3
內容00000000 10000000 1 1111001 0 1000010
C51編譯器提供了大量實(shí)用的庫函數,C語(yǔ)言源程序經(jīng)過(guò)C51編譯器編譯后在連接定
位時(shí),根據源程序中是否使用了浮點(diǎn)運算以及所采用的編譯模式,連接程序L51會(huì )自動(dòng)選
擇正確的浮點(diǎn)函數庫加入到目標代碼中去 ]。
3 浮點(diǎn)數運算結果及漢字打印輸出的實(shí)現
在C51的編譯器函數庫中有一個(gè)十分有用的輸出函數sprintf(),它可將數值或字符串
以ASIIC碼的形式輸出到內存中的某個(gè)地址單元,利用該函數可十分方便地實(shí)現浮點(diǎn)數運
算結果及漢字字符的顯示或打印輸出。sprintf()函數的一般格式為
sprintf(字符指針,格式說(shuō)明,輸出參數表列)
其中,第一個(gè)參數必須是指針,它可以是數組,也可以是變量的地址,用于指定內存單元的
首地址。格式說(shuō)明是一個(gè)用雙引號括起來(lái)的字符串:“ [flag][width][.precision]type”
其中,flag稱(chēng)為標志符,用于控制輸出數據的符號、空格、小數點(diǎn)的位置等;width是
一個(gè)十進(jìn)制的正整數,用來(lái)指定
最小輸出字符的數目;precision
用來(lái)表示輸出數據的精度,由小
數點(diǎn)和一個(gè)非負的十進(jìn)制整數組
成;type稱(chēng)為輸出格式轉換字
符,對于浮點(diǎn)數type可取3種表
示形式,如表2所示。
裹2 type字符豆其意義
type
f
e. E
g.G
數據類(lèi)型 輸出格式
float [一]dddd dddd形式的浮點(diǎn)數
float [一]d.ddddE [sign3 dd形式的浮點(diǎn)數
float e或f形式的浮點(diǎn)數,取其中形式較好者
輸出參數表列是需要輸出的一些數據項,它們可以是變量的值,也可以是照原樣輸出
的字符。由于8051系列單片機存儲器結構的限制,輸出表列中參數的總字節數有一定的限
制,在SMALL和COMPACT模式下,最大可傳遞1 5個(gè)字節的參數(5個(gè)指針,或1個(gè)指
針和3個(gè)long型數據),在LARGE模式下,最多可傳遞4o個(gè)字節的參數。
在C語(yǔ)言源程序中采用浮點(diǎn)數運算時(shí),運算結果是按IEEE一754標準格式存儲在內存
單元中的。這種存儲格式不便于顯示和打印輸出。利用sprint{O 函數可以很容易地將運算
結果轉換成宜于顯示和打印輸出的ASIIC碼。如果單片機應用系統中需要采用漢字輸出,
則可以在漢字操作系統(ga UCDOS)下編寫(xiě)C語(yǔ)言源程序,將要輸出的漢字作為字符串數
組直接定義到ROM 區,則該RoM 區中就存儲了一系列漢字的代碼。從該RoM 區中按順
序取出各個(gè)漢字代碼,輸出到任何一種具有漢字打印功能的打印機上,即可很方便地實(shí)現
漢字的打印輸出 。
4 實(shí) 例
所研制的智能化重力加速度測試儀的監控程序采用C51編程,實(shí)現了復雜的浮點(diǎn)數運
算處理及漢字打印輸出功能 測試儀利用光電轉換器的輸出脈沖觸發(fā)8051單片機的外中斷
0,讀取兩次外部中斷之問(wèn)定時(shí)器0的計數值,通過(guò)計算獲得加速度的值.為了提高計算精
度采用了浮點(diǎn)數運算。測試儀通過(guò)并行口與EPSON—LQ300K打印機相連,可將測量結果
以漢字方式打印輸出。打印機的并行接口為Centronics標準.用8051單片機的P1口作為數
據線(xiàn),P3.3和P3.5分別作為聯(lián)絡(luò )信號STROB和BUSY很容易實(shí)現與打印機的接口。智能
化重力加速度測試儀已經(jīng)研制成功并通過(guò)江漢石油學(xué)院設備處組織的鑒定。該儀器操作簡(jiǎn)
單,一次測量可獲得多個(gè)測量數據, 自動(dòng)計算出最終結果和相對誤差值,并可通過(guò)打印機
接表3格式輸出測量結果。
裹3 重力加速度測試儀的輸出涮■結果
落球法測量結果 單擺法涮量結果
預置高度:H1—100 00 ram-H2—800 00 ram
下落時(shí)問(wèn):T1—65 076 m .T2=297.27 ms
重力加速度:g 9.9042 m/s0
相對誤差:Er一0.0186
單攖攖長(cháng):I,=l309 ram
攖動(dòng)周期;TI,一2288.4 Ills
重力加速度:g一9.8752 m/s
相對誤差;Er 0.0096

下面給出了儀器監控程序中關(guān)于浮點(diǎn)數處理和漢字打印輸出部分的源程序。其中prn
()是浮點(diǎn)數打印輸出函數。對于小于0的浮點(diǎn)數先將其轉換為正數,再調用sprint{()庫
函數將其轉換成ASIIC碼,按浮點(diǎn)數的科學(xué)表示法存于數組array中。如果需要按科學(xué)表示
法打印輸出,可直接從數組array中逐個(gè)取出ASIIC碼數據進(jìn)行打印。本例要求按工程表示
法打印輸出,因此先要根據浮點(diǎn)數的階碼確定小數點(diǎn)的位置。prnint O 是單個(gè)字符打印輸
出函數。它用來(lái)向打印機輸出各種打印控制命令以及漢字的打印輸出。在ROM 區中定義了
若干個(gè)漢字字符串數組,打印漢字時(shí)只要從各個(gè)數組中取出需要輸出的漢字字符串代碼作
為實(shí)際參數來(lái)調用prnint()函數即可。
C語(yǔ)言源程序如下:
#include< reg51.h>
#include< stdio.h>
#indude< math.h>
#include< stdlib.h>
float g,dscountl·El,E2,s1,s2; /*定義浮點(diǎn)型數據變量*/
sbit busy=P3 3 sbit stb=P3 5; /*定義打印機聯(lián)絡(luò )信號*/
uns~ned char bdata flag, /*定義其它類(lèi)型數據變量*/
sbit flagl—Ihg OI
unsigned im clockO,count;
unsigned char dsp[8],array E]o3,
char code head1口一“歡迎使用重力加速度測量?jì)x”} /*定義漢字字符串*/
char code head2[]一“落球法測量結果”;
char code head3口一“單擺測量結果”;
char code hl[]= “硬置高度H1一H2= ;
char codeI1[]= 單擺按長(cháng)L一”;
char codetl[]= 下落時(shí)間TI T2= ”}
char codetI[]= “擺動(dòng)周期TL= ;
char code gg[]; “重力加速度g一”}
char code er[]= “相對誤差Er= ;
exten~char xdata[MtaPortt StaPort; ,*定義8279數據、命令口*,
exter~unsigned char keyval(unsigned char va1)} /} 匯編語(yǔ)言鍵值處理子程序*/
extern unsigned char tedseg(unsigned char x); ‘ /*匯編語(yǔ)言顯示段碼處理子程序*/
xint()interrupt 0 using 1 《
/*外部中斷INT0處理函數*/)
timer0 O interrupt 1 using 1{
/*定時(shí)器TO處理函數*/)
prn (float x){ /*浮點(diǎn)數打印輸出函數*/
unsigned cha r i}
if(x<0)x=l x; /*將浮點(diǎn)數作為正數處理*/
sprintf(array, 4e”+x)} ^ 轉換為ASIIC碼存于數組array中*/
arTay E1o]一array[93=array[93~0x0f; /*取階碼}/
j(array[73一=0x2b){ /*正階碼處理*/
for(1—1}i<一8r陽(yáng)y[93;I++)array[1]=array[i+1]} array[i]一Ox2e,

for(i一0‘i< 6}i+ + )《
P1一array即‘sfb=0‘stb=11 while(busy)})
next; for(1—6‘i<一3‘i一一)array[|]一arrav[j
array[9]一array[9]一1;
if(array[9]>o)goto next i
for(i一2{i—array[10];i++)array[j]一O}
for(i—O{i< 6l i+ + ) {
P1一array[i]‘stb=O}stb=1}while(busy)‘
prnint (unsigned char x){
P1一x}stb—O}stb= 1}while (busy); }
void kbinit()《
/*鍵盤(pán)顯示接口韌始化函數*/)
unsigned char readkey ()f
/*打印輸出*/
rettlrn{ }
1]} /* 負階碼處理*/
/* 打印輸出*/
/* 字符打印輸出函數*/
/*鍵值處理函數*/)
/* 其他處理函數*/
void kg(){ /* 重力加速度及相對誤差計算函數*/
一2.O* ( ( ( (goat)s2) /E2) 一( ( (float)s1)/E1)) / ( (E2一E1) /1000.O)}
dse~mtl—g; /*計算重力加速度*,
if(d~otmt1<9.781){d~eountl一(9.781-dscount1)/9.781}rettlrn;)
dsc~ntl一(dscountl-9.781)/9.781} /*計算相對誤差*/ )
void kel O { /*測量時(shí)間參數El*/
unsigned char data i;
TL0=0‘TH0=0;TMOD=Ox51;"ICON—o)=O; /* 定時(shí)器初始化*/
IE=Ox83~while(!flag1){ /*開(kāi)中斷.等待*/
El一(clock0*65536.O+cotmt)/1000.O} /*計算E1的值*/ }
d ke2(){ /*測量時(shí)間參數E2*/
unsigned char data l}
TL0— 0;TH0— 0;TMOD一0x51;TCON=Ox0
E2一(crock0*65536.O+count) /1000.0; }
void k0rn O {
IE= 0x83;whi~e (1山g1)
unsigned ch丑r i:
prnint (Oxlb);prnint (0x74)}prnint (0x00);
i一0;while(head[i]j一0){prnint(head D]);i++
l一0;while(hl[j]j一0)tprnint(hi[‘])}i++;)
prn (s1);prn (Ox0a)‘
i一0f while(h2[i]l一0){prnint(h2[i])}i++‘)
prn (s2)4 prn (Ox0a)f
o‘while(tl[1]!一o){ornint(tl[i]);j++})
prn (E1)‘prn (0x0a);
0‘while(t2[1]!一o){ornint(t2[j]);i++;)
prn (E2)}orn (OxOa)4
— o;while(gg[i]!一0){prnint(gg[i]) i++f)
orn (g)}orn (OxOa);
/*打印輸出函數*/
/*打印機初始化命令*/
/* 打印漢字*/
/*打印浮點(diǎn)數并換行*/
/*打印漢字*/
/*打印浮點(diǎn)數并換行*/
/*打印漢字*/
/*打印浮點(diǎn)數并換行*/
/*打印漢字*/
/*打印浮點(diǎn)數并換行*/
/*打印漢字*/
/*打印浮點(diǎn)數并換行*/i—o;while(er Ill!
prn (dscount1);prn
code void (code *keytab
void main (void){
kbinit ():IE— O:
while (1)(*keytab
一0){prnint(er[j]);i++
(0x0a)·
[])()一{kg,/*⋯ */}
[readkey()])(); )
打印漢字*/
打印浮點(diǎn)數并換行*/ }
鍵值處理*/
主函數*/

發(fā)布人:2011/12/12 10:54:002101 發(fā)布時(shí)間:2011/12/12 10:54:00 此新聞已被瀏覽:2101次