李文昭,王虹,李慶
(1.河北大學 靜電研究所, 河北 保定 071002;2.河北大學 電子信息工程學院, 河北 保定 071002)
隨著電子技術的不斷發展,在控制領域廣泛使用的8051系列單片機也有了長足的發展,一些采用新技術的8051系列單片機不斷出現,如NXP的LPC900系列[1]、STC的1T系列[2]、SiLabs的C8051F[3]系列等,這些產品的計算能力較傳統8051系列單片機有了幾十倍甚至上百倍的提升.曾經以控制為主的單片機,已有能力進行一些相對復雜的計算.然而目前針對8051的各種C語言編譯器在數據類型上僅支持到float型變量[4].Keil作為目前國內使用最廣泛的單片機集成開發環境,雖然支持了“double”關鍵字,但是其對double類型的變量仍然只是轉為float型處理[4],實際計算精度并沒有達到IEEE-754雙精度浮點數的標準.針對目前C51編譯器的不足,采用數組分部處理數據[5],在Keil C51環境下設計了符合IEEE-754雙精度標準的浮點庫,實現基本的四則運算,滿足了在控制領域中需要進行高精度計算的特殊要求.
IEEE-754二進制浮點數算術標準定義了浮點數的表示格式,是目前廣泛使用的浮點數格式標準,被多數CPU和浮點運算器采用.在IEEE-754標準中規定了單精度(32位)、擴展單精度(43位以上,不常用)、雙精度(64位)和擴展雙精度(79位以上)[6-8]4種浮點數的表示方式.IEEE-754二進制浮點數算術標準利用科學計數法來表示實數,一個符合IEEE-754的浮點數F被劃分為3個字段,表示為如下形式:
F=(-1)S×M×2E,
(1)
其中,F是所表示的浮點數.S是符號位,占用1位二進制數寬度,E是階碼,也就是指數,用移碼表示,在雙精度浮點數中階碼占用11位二進制數寬度.M是尾數,通常都是規格化表示,即非“0”的有效位最高位總是“1”,然而在IEEE-754標準中是一個純小數,有效位形式為“1.MMM…MMM”,在實際表示中整數位的“1”被省略,稱為隱藏位,對于雙精度浮點數而言M的寬度是52位二進制數,加上1位隱藏位共53位[6-8].由于
253= 9,007,199,254,740,992,
故雙精度浮點數可以得到15~16位有效數字,常用的浮點數格式如表1所示.

表1 常用的浮點數表示格式
加減法運算是最基本的運算,因為A1-A2=A1+(-A2),故把加法運算和減法運算放在一起討論.計算過程主要分為6步:1)0操作數檢查;2)對階;3)尾數相加;4)結果規格化;5)舍入處理;6)溢出處理.其中省略了2個和算法不相關的步驟,即進行第1步之后第2步之前需要分別把符號位、階碼、尾數從64位二進制串中提取出來;當進行完第6步后還要把這3部分組合成一個符合IEEE-754標準的64位二進制串.
1)0操作數檢查.對2個操作數進行0檢測,只要有1個操作數為0即可簡化加法運算,此時只要返回另1個操作數,節省了運算時間.
2)比較階碼大小并完成對階.如果2個操作數都不為0,則要進行階碼比較.當其中1個操作數的階碼遠遠大于另1個操作數的階碼時,也會在很大程度上簡化運算.因為尾數的精度有限,當階碼之差大于尾數寬度時,說明其中1個操作數遠大于另外1個,即使相加,結果也不會保留到那么高的精度,所以在這種情況下,會得到和0操作數檢查幾乎相同的運算時間消耗,只要返回較大的操作數就可以了.在64位計算中階碼之差要大于54才能簡化運算.當階碼之差小于54時,就需要進行對階和實際的加法計算.對階操作時,要遵循小階向大階看齊的原則,否則會影響計算精度.具體的做法是先求出階差,然后階小的尾數進行右移位操作,每右移1位,階碼加1,直到2個操作數的階碼相等為止,此時右移的次數剛好等于移位前的階差.
3)尾數相加.對階完成后即可將2個尾數按定點加法運算規則進行運算.
4)結果規格化.當計算完畢,結果可能已經不是“1.XX…X”的形式,這時就需要進行規格化處理,即通過對尾數進行左移或右移操作并相應的修改階碼,使結果為規格化表示.
5)舍入.由于尾數的位數被限制為52位,所以在進行右移操作時可能造成低位數的丟失,這就需要進行舍入處理.本程序采用了較為精確的0舍1入法,當丟失的部分最高位為0時不作處理,當丟失的部位最高位為1時,則向最低位加1.
6)溢出處理.溢出分為4種情況:階碼上溢,一般認為是±∞;階碼下溢,一般將其認為是0;尾數上溢和尾數下溢,需要對尾數重新進行規格化處理[7].
浮點數的乘法相對于加法要復雜一些,2個浮點數相乘,乘積的階碼為2個乘數階碼之和,乘積的尾數為2個乘數尾數之積.例如,設2個浮點數A,B:A=2EA×MA,B=2EB×MB, 則A和B的乘積為
A×B=2(EA+EB)×(MA×MB).
(2)
因此,浮點數的乘法操作可以由4步完成:1)0操作數檢查;2)階碼求和;3)尾數求積;4)尾數規格化并進行舍入處理.
1)0操作數檢查.和加法操作一樣,只要有一個操作數為0則可以直接返回0結果.
2)階碼求和.把2個乘數的階碼相加,結果為乘積的階碼,相加完畢后要進行溢出判斷.溢出判斷的方法是在原有移碼的基礎上再加上一位符號位,如果計算后此位為1則說明有溢出,溢出后,原符號位為0說明結果上溢;原符號位為1說明結果下溢.如果沒有溢出,那么原符號位為0說明結果為負;原符號位為1說明結果為正.
3)尾數求積.尾數求積可采用定點乘法運算的原理.由于尾數加上隱藏位一共是53位,所以需要一個至少106位的空間存儲乘積.而C51最大只支持2個16位數相乘,因此,需要把尾數分別存儲在2個數組中,把尾數分為幾段,進行計算的時候把每段和另一個尾數相乘,采用嵌套循環進行乘法處理然后再進行相加得到計算結果.求積計算是整個乘法運算中最耗時的操作.
4)尾數規格化并進行舍入處理.尾數求積后得到的結果受到長度限制,只能取前53位,然后進行舍入處理.舍入處理通常有2種方法:一種是截斷處理,把剩余的低位數據全部作丟棄處理;另一種辦法是0舍1入.同加法一樣,為了提高計算精度,這里采用了0舍1入的處理方式.
除法是四則運算里面最復雜的,也是最耗時的[9-10].除法是乘法的逆運算,正如乘法可以用移位相加實現一樣,除法可以通過一系列的移位相減實現.浮點除法的運算規則是
A/B=2(EA-EB)×(MA/MB).
(3)
商的階碼是兩數階碼之差,商的尾數是兩數尾數之商.因此,浮點數的除法操作和乘法一樣可以由4步完成:1)0操作數檢查;2)階碼求差;3)尾數求商;4)尾數規格化及舍入處理.
尾數求商是浮點除法運算的關鍵,原碼除法通常采用“恢復余數法”和“加減交替法”.設計參考了恢復余數法并針對8051單片機計算速度慢的特點對循環減算法進行了改進優化,恢復余數法的特點是當除數為負時,需加上除數,將其恢復成原來的余數;循環減的特點是先判斷是否夠減,然后再進行相應的操作.而商的符號位由除數和被除數的符號進行異或運算得到,即
SIGN商=SIGN被除數⊕SIGN除數.
尾數的除法同樣在Keil C51環境下遇到無法用一個變量表示的問題,解決的方法是用2個數組分別存儲2個尾數,所以在用數組進行除法運算的時候要不斷注意借位問題,以免造成計算錯誤.通過除數尾數對被除數尾數進行54次循環減之后,就得到了商.最后把計算好的階碼和符號位同商的尾數組合成標準的64位浮點數放在指定的存儲空間,浮點除法計算就完成了.
程序的運行效率是用戶比較關心的問題,如果運行時間太長,那么64位浮點計算也就失去了意義.可以通過一組數據對加、乘、除分別測試,表2是經過多次測試得到的一組平均數據,可以看到3種運算的時間消耗都可以令人滿意.

表2 3種運算的耗時對比
CPU:AT89C51,OSC CLOCK:12 MHz
由上表可以看出即使是12 MHz的普通8051單片機進行除法計算耗時也僅需40 ms左右,如果使用基于CIP-51核等一些新型的單片機那么3種計算的時間將會少于10 ms,由此看出8051系列的單片機完全能夠勝任實時性要求不高的64位浮點計算.
當庫函數完成以后,可利用Keil C51軟件提供的庫管理程序生成庫文件,并為浮點庫編寫相應的頭文件,以方便在以后的工程中調用.
針對目前最廣泛使用的Keil C51平臺下無法進行雙精度計算的實際問題,提出了一種可行的解決方案.在進行理論分析后,設計并實現了四則運算的64位雙精度計算方法.
方案采用分部存儲的方法,將較大的64位數據分成幾個部分存儲在內存空間,將各部分分別計算后再整合成需要的計算結果,其中大量使用指針,在充分分析時間和空間矛盾的基礎上,針對8051核單片機有限的內存容量和較低的運算速度對程序進行了優化設計,和傳統計算方法相比提高了程序運行效率,節省了存儲空間.
在采用最普通的8051核單片機AT89C51的情況下,測試中加減法進行一次運算僅需要1.6 ms,乘法和除法單次運算也只需27.4 ms和36.2 ms,可以滿足絕大多數實時性要求不高的工程需要,解決了目前Keil C51平臺下無法進行高精度計算的難題,為8051系列單片機提供了更廣泛的應用空間,同時避免了使用ARM等32位高端處理器帶來的人力和財力支出.
參 考 文 獻:
[1] 張立群,李鐵才,連全斌.基于單片機P89LPC932A1的微功耗設計[J].自動化技術與應用,2006,25(11):30-33.
ZHANG Liqun, LI Tiecai, LIAN Quanbin. A low power design based on MCU P89LPC932A1[J]. Techniques of Automation & Applications,2006,25(11):30-33.
[2] 宏晶科技.宏晶科技STC12C5410AD系列單片機器件手冊[EB/oL].〔2011-9-9〕(2013-1-23).http://www.stcncu.com/datasheet/stc/STC-AD-PDF/STC12C5410AD.PDF
[3] 鐘磊,盧文壯,左敦穩,等.C8051F單片機的IAP系統設計與實現[J].微處理機,2009,03:9-11.
ZHONG Lei, LU Wenzhuang, ZUO Dunwen, et al. In-application programming system design and realization ofC8051F MCUs[J].Microprocessors,2009,03:9-11.(2013-1-23)〔2012-8-9〕www.keil.com
[4] KEIL Cx51 User’s Guide[EB/OL].Keil An ARM Company.2012.
[5] 狄光智,趙同林.數組實現高精度計算的方法研究[J].電腦編程技巧與維護,2009,10:126-127.
DI Guangzhi, ZHAO Tonglin.The study of high-precision computation using arrays[J]. Computer Programming Skills & Maintenance,2009,10:126-127.
[6] IEEE. IEEE Standard for Binary Floating-Point Arithmetic[S]. IEEE Std 754-2008:6-38
[7] 白中英.計算機組成原理[M].北京:科學出版社, 2008:22-71.
[8] BRYANT, O’HALLARON.深入理解計算機系統.[M].龔奕利,雷迎春,譯.北京:機械工業出版社,2011:50-81.
[9] 陳森林,田華.快速浮點除法運算及其在單片機上的實現[J].陜西師范大學學報:自然科學版,2004,32(2):43-45.
CHEN Senlin, TIAN Hua. Rapid floating point division algorithm and its implementation on MCS-51 series single chip computer[J]. Journal of Shanxi Normal University: Natural Science Edition, 2004,32(2):43-45.
[10] 郭松,徐世亮,萬里勇.巧用數組實現除法的高精度計算[J].計算機與信息技術, 2007,36:442,422.
GUO Song, XU Shiliang, WAN Liyong.Using array to achieve high precision of division[J].Science & Technology Information,2007,36:442,422.