劉國云
摘要:C語言作為一種結構化的程序設計語言,其不但具有高級語言的相關特點,還具有匯編語言的相關功能,其能夠直接對計算機的硬件進行很好的操作。C語言不但具備豐富的庫函數,還具有較強的功能性、較好的移植性、較快的運算速度和較高的編譯效率,所以成了單片機系統最為常用的編程語言。在單片機性能不斷提高的情況下,C語言編程方法的應用,成為開發出優秀單片機系統的關鍵,同時對于編程者而言,C語言編程方法也具有十分重要的作用。對于單片機而言,在使用[C51]進行多字節乘法運算時,常常會忽略相應的問題。本作者對該問題出現的原因進行了分析,并提出了相應的解決辦法。同時本文對單片機C語言的概念和特點進行了概述,并對單片機C語言編程的優點進行了分析,探討了單片機C語言編程的多位乘法運算編程方法。
關鍵詞:單片機;C語言;編程;多位乘法運算
中圖分類號:TP3? ? ? 文獻標識碼:A
文章編號:1009-3044(2019)24-0242-02
開放科學(資源服務)標識碼(OSID):
單片機作為一種典型的嵌入式微控制器,具有多種構成組件,其整體相當于一個微型的計算機,目前單片機已經普遍應用到我們生活的各個領域,尤其是在工業領域中,單片機的應用更為廣泛。在教育領域中,單片機也是相關專業必學的課程,其中就涉及較多的編程語言,在眾多的編程語言中,C語言成為單片機最重要的編程語言,在單片機系統中,常常會應用到多種算法,而本文的研究主要在于單片機多位乘法的算法分析和編程方法。C語言作為一種重要的結構化的程序設計語言,具有較強的功能性、結構性和較好移植性等特點,這也使得其成為單片機系統的編程語言。本文的研究中利用到了[C51]進行單片機系統的開發,其繼承了C語言強大的表達數據的能力,并且具有豐富的運算符、強大的數據處理能力和數學運算庫函數,能夠方便解決復雜的數學運算。
1 單片機C語言及特點概述
單片機C語言也具有高級語言的功能以及完善的模塊化程序結構,能夠為單片機軟件系統的開發提供有力的保障,對于C語言存在的編譯資源有限的情況,單片機C語言能夠很好地解決這類問題。單片機C語言能夠提供較為復雜的數據類型,能夠極大增強相關程序的處理能力和靈活性,同時能夠有效利用單片機上有限的RAM資源空間,對相應的數據進行專業性的處理,從而有效避免單片機系統在運行期間出現非異步的破壞[1]。
單片機C語言能夠提供常用的標準函數庫,用戶可以進行直接使用,相關程序員在進行編程的時候,不需要仔細了解單片機的相關指令集,就可以編寫出完美并符合硬件實際需求的單片機程序。使用單片機C語言進行程序的編寫,要比使用匯編語言方便得多,編程人員不需要與硬件進行相應的接觸,只需要考慮相應的功能和算法,這就極大地減少了系統開發和調試的時間。單片機C語言具有良好的程序結構,非常適合于模塊化程序的設計,在進行單片機應用系統程序設計時,相關編程設計人員應該盡可能地使用結構化的程序設計方法,將單片機系統功能模塊化,通過使用不同的模塊來完成不同的功能,這樣能夠使得單片機系統具有十分清晰的程序結構,也方便后期的調試和維護。對于不同功能的模塊而言,其具有相對應的入口參數和出口參數,對于需要重復調用的程序可以將其編寫成相應的函數,這樣不但能夠減少程序代碼的長度,同時也便于管理整個程序,增強程序的可讀性和移植性。
2 單片機C語言編程的優點分析
2.1 單片機C語言的數據類型
單片機C語言編譯器能夠支持多種類型的數據,其相關的數據類型一般包括char類型、long長整型、sft特殊功能寄存器、float浮點型以及int整型等等。使用sft特殊功能寄存器,能夠對單片機內部的所有特殊功能寄存器進行相應的訪問。單片機C語言編程一般與程序存儲器進行結合,而程序的存儲器一般體現出單片機系統資源的有限性[2]。對于浮點型數據而言,一般需要具有相應的內部程序或者函數進行支持,但在一定程度上會生成較長的代碼,因此在進行單片機系統程序的編寫時,相關編程人員要盡可能多地使用char和int等數據類型,并且減少程序中使用到的數據類型,通過合理選擇應用的數據類型,可以有效減少程序中生成的代碼長度。
2.2 單片機C語言的算法描述
一般控制結構和原操作構成一個算法,兩者的綜合效果決定著該算法的執行時間,對于同一個算法而言,如果相關編程語言的級別越高,那么其執行的效率就越低。由于單片機資源存在的限制,單片機C語言不僅要考慮程序的相關具體功能,還要考慮程序代碼的長度。程序的算法的長度不是越短越好,這需要根據其調用的子程序和函數來決定,在進行程序設計的時候,一般采取一些優化算法以減少代碼的生成長度。
2.3 數據存儲器的分配
對于單片機的數據存儲器而言,其是由讀寫存儲器RAM組成,該存儲器可以進行相應的擴容,能夠對實時輸入的數據進行儲存。在存儲器的實際應用中,應該首先使用內部的存儲器,單片機C語言采用的是存儲器的覆蓋技術,所以在進行程序連接的時候,可以對存儲器空間的一些程序段進行釋放,重新定義給另一個程序段使用。對于在程序開始處就定義的全局變量,其作用域是整個程序,所以不能夠被釋放,同樣的對于靜態存儲變量,在程序運行期間其存儲空間固定不變,其在函數的調用中具有專用性,所以也不能夠被釋放,能夠被釋放的只有局部變量中的動態變量,所以在進行程序設計的時候,要盡可能地使用局部變量。
2.4 單片機C語言的代碼優化
存儲期一般包含三種不同的模式,其中SMALL是小模式,所有的變量都存儲在一定額地址范圍內,該模式能夠將所有的變量定義為data類型的內存。不同的模式會對程序代碼的長度和執行的速度產生直接的影響,當程序中需要應用到較多的變量時,可以在存儲器空間中存放部分變量,使用編譯器對相關變量進行定位后,可能會增加代碼的長度,影響到程序的執行效率,這時候就可以將很少訪問的變量定義為xdata類型,并將其存放在外部的RAM中。
3 單片機C語言編程中多位乘法運算分析
3.1 單片機C語言編程中多位乘法運算問題的提出
在[C51]編譯器中,其能夠直接支持不同數據類型的變量,比如bit類型、char類型等,而兩個unsigned char類型的數據進行相乘,也正好符合匯編指令中的“MUL AB”。使用[C51]進行多位乘法運算編程,在這個過程中只需要使用相應的乘法表達式進行編譯就行,只要通過相應的編譯,[C51]就可以自動尋找相應的存儲器并且把運行的結果存放在存儲器空間中[3]。所以在使用[C51]進行乘法運算的時候,編程人員只需要編寫一個乘法表達式并且將乘積的結果賦值給一個存儲單元就可以,但是如果乘法運算中的乘數不是unsigned char類型的變量,及時乘法表達式再簡單,也需要調用[C51]中的庫函數;而如果乘法運算中的乘數是大于255的常量,[C51]就會將這個乘數以對應的類型自動存儲起來。對于大于255的常量而言,因為unsigned char類型的變量是8位的,所以其和其他類型的變量一樣需要調用[C51]的庫函數,所以在這種情況下,如果還是用乘法表達式進行相應的編譯,那么得到的運算結果就有可能和實際的結果存在一定的差異。例如下面一段程序,其運行之后的結果gg的值不等于[9?10000]所得的值。
#include
main()
{
Unsigned char aa;
Unsigned long gg;
aa=9;
gg=([aa?10000]);? ?}
3.2 關于問題的分析
在使用[C51]編譯器進行相應的優化處理時,往往希望用工作寄存器來存儲相應的局部變量,按照[C51]的相關存儲規則,程序在執行aa=9語句時,可以得到的結果為[R7=9],在執行[aa?10000]時,根據[C51]的要求,進行算數運算的數據類型需要相同時,該語句中的10000的存儲方式是以兩個字節的unsigned char方式存儲的,這就需要將aa的儲存進行擴展為兩個字節的unsigned char方式。所以[C51]在使用兩個寄存器對[aa=9]進行儲存時,需要先存儲低字節,然后再存儲高字節,這就使得在執行[aa?10000]時,乘法運算就變成了兩個雙字節數相乘,按照[C51]的運算規則,改程序的代碼會少一次運算,其中有數據沒有進行相應的乘法運算,而且在執行的過程中,沒有把經過第三次運算得到的結果的高8位進行儲存,而運算結果的低8位存放在[R7],而次低8位存放在[R6],所有得到的運算結果就會不正確。
3.3 相應的優化方案
針對上述提到的關于乘法運算的問題,本文提出了幾種進行優化的算法,其包括引入中間變量法、分布運算法以及強制類型轉換法。
3.3.1 引入中間變量法
在進行乘法運算的過程中,可以通過增加一個中間變量來對算法進行優化,但對于這個中間變量而言,其數據類型必須要能夠存儲相乘之后的得到的結果,上述中的程序就可以改寫為:
#include
Main()
{
Unsigned char aa;
Unsigned long gg,bb;
aa=9;
bb=10000;
gg=(aa*bb);? ?}
從該程序中就可以發現,程序中的aa是char類型,而bb是long類型,按照[C51]的相關運算規則,aa的數據類型先改變為與long一樣的,那運行的結果也是long類型的,而且[C51]能夠對[9?10000]這個數據進行自動存儲,運行結果就不會出錯。
3.3.2 分布運算法
除了上述算法外,編程人員也可以使用分布運算法進行優化,可以將一個16位的數據分成兩個數據的乘積,而對于這兩個數據來說,其都是8位數,結果儲存在能夠進行存儲相乘之后得到的結果的儲存單元中,最上面的程序就可以改為:
#include
Main()
{
Unsigned char aa;
Unsigned long gg;
aa=9;
gg=(aa*100);
gg=100;? ?}
通過對該程序進行分析可以發現,進行修正后的程序運算的得到的結果為long類型,并且可以對[9?10000]這個數進行存儲,所以最后的運算結果也是正確的。
3.3.3 強制類型轉換法
在[C51]編譯器中,強制類型轉換運算符可以使用“()”表示,其作用就是將相關表達式或者標量的類型進行強制轉換為所需要的類型,在[C51]中一般存在隱式轉換和顯式轉換兩種轉換方式。在使用隱式轉換式對程序進行編譯時,編譯器能夠進行自動處理,但在本文的研究中運用的是顯示類型轉換方式,使用該方法將aa強制轉換成可以進行存儲運算結果的類型,那么最上面的程序就可以改為:
#include
Main()
{
Unsigned char aa;
Unsigned long gg;
aa=9;
gg=((unsigned long)aa)*10000;? ?}
在該程序中,aa轉換成了可以存儲[9?10000]的數據類型,所以得到的結果也是正確的。
4 結語
綜上所述,C語言作為一種結構化的程序設計語言,成為單片機最重要的編程語言,單片機C語言也具有高級語言的功能以及完善的模塊化程序結構,能夠為單片機軟件系統的開發提供有力的保障。在單片機系統中,常常會涉及多種算法,而本文研究主要是單片機程序設計中的多位乘法的相關算法,并對多位乘法運算中存在的問題以及解決方法進行了相應的研究。
參考文獻:
[1] 嚴克劍,張淼,黃先偉.單片機C語言編程中多位乘法運算問題探討[J].廣東工業大學學報,2006(4):23-26.
[2] 譚炳菊,富鈺.單片機C語言編程方法探討[J].遼寧高職學報,2010,12(4):43-44.
[3] 黃皎,劉建國,高敏.單片機C語言編程應注意的若干問題[J].微計算機信息,2003(7):58-59.
【通聯編輯:張薇】