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