版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第7章C語言編程與混合編程7.1
C語言編程7.2
C程序編譯7.3
C語言與匯編語言混合編程
7.1
C語言編程
7.1.1
C54x支持的基本數據類型
C54xDSP的基本數據類型如表7.1所示,字長為16位或32位。7.1.2常量與變量
常量名和變量名都以字母或下劃線開頭,最多可以有100個字符,不能使用C語言的關鍵字來命名常量名和變量名。常量在編譯后直接嵌入代碼中。變量名經C編譯器編譯后,代表一個變量的內存地址,并自動在變量名前加下劃線(_),
如變量“a”經編譯后,在內存單元顯示為“_a”。這樣的好處就是C語言定義的變量和匯編文件定義的變量可以重名且不會混淆,還有一個好處就是匯編文件可以調用C
語言定義的變量和函數(C語言定義的函數名在編譯后也在函數名前加“_”),以實現(xiàn)混合編程。
符號的常量名通常用大寫字母表示,變量名用小寫字母表示,以示區(qū)別。變量名常采用著名的匈牙利命名規(guī)則,當然,變量較少時,也可以簡單地命名變量。7.1.3運算符與表達式
將常量或變量用運算符連在一起就構成了表達式,再在句末加上分號(;)即成為語句。
(1)賦值運算符:=。對DSP寄存器進行賦值時,先將寄存器定義為指針,然后與C語言變量賦值類似地進行賦值。如中斷屏蔽寄存器(IMR)的地址為0地址,其定義和賦值如下:
#define IMR *(int*)0x0
IMR=0;對外部端口進行賦值時,先用關鍵字ioport和端口地址定義端口名,然后也是與C語言變量賦值類似地進行賦
值,其定義和賦值如下:
ioportunsignedintport8000;//定義一個外部端口,地址為0x8000
port8000=0;
(2)算術運算符:+(加)、-(減)、*(乘)、/(除)、%(取模)。在C54xDSP中,取模運算按分子的符號確定取值的符號,如10%-3=1;-10%3=-1等。類似地,C54xDSP也支持組合運算符,如+=、-=、*=、/=、%=及++、--等。
在表達式中,只能使用小括號改變運算的優(yōu)先順序。
(3)關系運算符:==(等于)、![KG-*2]=(不等于)、>(大于)、>=(大于等于)、<(小于)、<=(小于等于)。
作為關系運算表達式的輸入,0為假,非0為真;作為運算結果,0表示假,1表示真。
(4)位運算符:&(按位與)、|(按位或)、∧(按位異或)、~(取反)、<<(左移)、>>(右移)。
(5)邏輯運算符:&&(邏輯與)、‖(邏輯或)、!(邏輯非)。
(6)三元運算符:“?:”,它有三個參加運算的元素,而且有返回值,其使用格式為
(express)?(val1):(val2);[HT5]
如果express的值為真,則返回表達式val1的值,否則返回val2的值。這條語句也可用if語句代替,可不必記憶。
運算符的優(yōu)先級自高到低為邏輯非、算術運算符、關系運算符、邏輯運算符&&或‖、賦值運算符。7.1.4函數及調用規(guī)則
一個C語言編寫的函數就是一個功能模塊,多個函數可以組成更大的功能模塊。main函數包括除中斷函數外的其他全部函數的功能,DSP程序總從main函數開始執(zhí)行。為了能正確執(zhí)行main函數,需要一個C語言運行環(huán)境。通過適當設置TMS320C54xC/C++編譯器,DSP項目中會自動添加相應的C語言初始化代碼,以適合main函數的執(zhí)行。
1.全局變量和局部變量
在主函數體中定義的變量或主函數體外的變量為全局變量,在編譯時有固定的存儲地址;而在其他函數體中定義的變量稱為局部變量,存儲單元是在堆棧中分配局部變量的,稱為局部幀。一旦函數執(zhí)行完畢,局部幀必須被收回,局部變量就消失了,所以局部變量的作用域僅限于函數體內部。
2.參數傳遞
如果函數存在參數傳遞,則調用者將第一個參數(最左邊)載入累加器A,而將剩下的參數以逆序壓入堆棧,最右邊的先壓棧,最左邊的參數最后一個壓棧,即在最低的地址。
這些壓入堆棧的參數稱為局部幀,參數傳遞就是將實參的值復制到形參的值的過程。若參數為實浮點數或長整型數,則是低字先入棧,高字后入棧。若參數中有結構形式,則調用函數會給結構分配空間,其地址通過累加器A傳遞給被調用函數。一旦函數執(zhí)行完畢,局部幀被收回,形參則消失。
3.函數返回
若函數返回一個值,則被調用函數將返回值載入累加器A中,再從A復制到實參中;如果是返回一個結構體,則將結構體的內容復制到累加器A所指向的存儲空間;如果沒有返回值,則A被置0,然后撤銷局部幀和恢復函數中所有保護的寄
存器。
4.main函數
main函數主要由程序初始化代碼、硬件初始化代碼以及定時掃描代碼等組成。main函數往往是死循環(huán)函數,定義死循環(huán)的語句有for(;;)或while(1)等。
5.中斷函數
中斷函數利用關鍵字interrupt來定義。如定義一個名稱為time的中斷函數如下:
interruptvoidtime();
{
…
}
用C語言編寫的中斷函數,其執(zhí)行效率不高。因為當系統(tǒng)調用中斷函數時,會將所有CPU寄存器的內容壓棧保護,中斷返回時,系統(tǒng)又會將這些CPU寄存器的內容出?;謴?。7.1.5
C語言庫函數
在C5000DSP的C語言編程中,有很多現(xiàn)成的庫函數可以調用。假設CCS默認安裝在c:\ti目錄下,則c:\ti\c5400\cgtools\include和c:\ti\c5500\cgtools\include兩個目錄下的文件即為C/C++庫函數文件。這里對C庫文件進行介紹,C++庫文件從略。在c:\ti\c5400\cgtools\include目錄下的C語言頭文件(.h)有19個,它們分別是access.h、assert.h、ctype.h、errno.h、file.h、float.h、intrindefs.h、iso646.h、limits.h、
linkage.h、math.h、setjmp.h、stdarg.h、stddef.h、stdio.h、stdlib.h、string.h、time.h、unaccess.h。
頭文件中的函數實現(xiàn)存儲在c:\ti\c5400\cgtools\lib\rts.src文件中,打開文件即可以看到具體的實現(xiàn)代碼。
(1)math.h:浮點數學函數。它包含下列函數:
sin(正弦)、cos(余弦)、tan(正切)、asin(反正弦)、acos(反余弦)、atan(反正切)、atan2(兩數商的反正切)、sinh(雙曲正弦)、cosh(雙曲余弦)、tanh(雙曲正切)、ceil(向上取整)、floor(向下取整)、fmod(兩數商的浮點型余數)、fabs(絕對值)、exp(以e為底的指數)、frexp(返回一個數的尾數和以2為底的指數)、ldexp(已知尾數和以2為底的指數,求冪)、log(自然對數)、log10(以10為底的對數)、modf(分解成有符號整數部分和有符號小數部分)、pow(計算x的y次方)、sqrt(開平方)。
(2)stdlib.h:通用函數。它包含下列函數:
abort(非正常程序中止)、abs(求整數絕對值)、labs(長整數絕對值)、atof(字符串轉換為浮點數)、atoi(字符串轉換為整數型)、atol(字符串轉換為長整型)、div(整型除法)、ldiv(長整型除法)、ltoa(長整數轉換為字符串)、rand(產生偽隨機整數)、srand(復位隨機數產生器)、strtod(字符串轉換為浮點值)、strtol(字符串轉換為長整型值)、strtoul(字符串轉換為無符號長整型值)。
(3)ctype.h:字符轉換。它包含下列函數:
isalnum(是否是字母或數字)、isalpha(是否是字母)、iscntrl(是否是控制字符)、isdigit(是否是數字)、isgraph(是否是除空格外的可打印字符)、islower(是否是小寫字母)、
isprint[JP](是否是可打印字符(包括空格))、ispunct(是否是標點符號)、isspace(是否是空格、制表符、回車符、換頁符或換行符)、isupper(是否是大寫字母)、isxdigit(是否是十六進制數)、isascii(是否是ASCII碼字符)、toupper(轉換成大寫字母)、tolower(轉換成小寫字母)、toascii(轉換成一個合法的ASCII碼值)。
(4)其他頭文件。它包括下列函數:
assert.h(診斷信息)、errno.h(出錯報告)、file.h(低級I/O函數)、float.h、limits.h(取值范圍限制)、setjmp.h(非局部跳轉)、stdarg.h(可變參數)、stddef.h(標準定義)、stdio.h(輸入/輸出函數)、string.h(字符串函數)、time.h(時間函數)。7.1.6
DSPLIB匯編庫函數
CCS開發(fā)環(huán)境還為C5400和C5500提供了通用數字信號處理算法庫(DSPLIB庫)。這些庫函數用匯編語言編寫,編譯效率高,多數為16位數據格式,執(zhí)行速度快,采用C函數格式直接調用或略加修改后調用,可大大加快項目的開發(fā)速度。如果采用默認安裝的CCS軟件,則DSPLIB庫在c:\ti\c5400\dsplib目錄下。在此目錄下的\include\dsplib.h頭文件中列出了DSPLIB庫函數的原型,其源程序在c:\ti\c5400\dsplib\54xdsp.src文件或54x_src文件夾中,主要有以下相關函數。
(1)實數或復數FFT算法函數。
cfft8~cfft1024:16位數據的復數FFT算法,點數在8~1024點之間,取2的整數次冪。
rfft8~rfft1024:16位數據的實數FFT算法,點數同上。
cfft8~cfft1024:16位數據的復數IFFT算法,點數同上。
rfft8~rfft1024:16位數據的實數IFFT算法,點數同上。
cfft32_8~cfft32_1024:32位數據的復數FFT算法,點數
同上。
cifft32_8~cifft32_1024:32位數據的復數IFFT算法,
點數同上。
unpacki_16~unpacki_1024:IFFT算法解包裝(unpack)
算法,也就是將一個N/2點的復數IFFT變成N點的實數IFFT算法,點數在16~1024點之間,取2的整數次冪。
cbrev、cbrev32:16位、32位的復數倒位序程序。
(2)數字濾波和卷積函數。
convol:計算2個實序列的卷積。
fir:fir濾波函數。
firs:系數對稱的fir濾波函數。
cfir:復數fir濾波函數。
iircas4:使用直接II型結構計算二階IIR級聯(lián)濾波,其算法如下:
d(n)=x(n)-a1d(n-1)-a2d(n-2)
(7.1)
y(n)=d(n)+b1d(n-1)-b2d(n-2)(7.2)
iircas5:使用直接II型結構計算二階IIR級聯(lián)濾波,其算法如下:
d(n)=x(n)-a1d(n-1)-a2d(n-2)(7.3)
y(n)=b0d(n)+b1d(n-1)-b2d(n-2)(7.4)
iir32:32位數據的二階IIR級聯(lián)濾波。
firdec:帶抽取的fir濾波,允許分段連續(xù)濾波。
firinterp:帶內插的fir濾波,允許分段連續(xù)濾波。
(3)自適應濾波函數。
dlms:帶延遲的自適應LMSfir濾波算法。
(4)相關函數。
acorr_raw、acorr_bias、acorr_unbias:
計算自相關及有偏、無偏處理,僅輸出自相關序列的半邊,而corr函數輸出自相關的全部序列值。
(5)數學函數。
add:向量加法。
sub:向量減法。
neg、neg32:16位、32位數據向量取相反數。
ldiv16:Q31除以Q15的長除法。
recip16:Q15格式浮點數倒數運算。
expn:利用泰勒級數計算一個向量以e為底的指數值。
logn:利用泰勒級數計算一個向量的自然對數值。
log_2、log_10:利用泰勒級數計算一個向量以2為底、以10為底的對數值。
sqrt_16:開平方。
maxidx、minidx:返回一個向量最大值、最小值的索引。maxval、minval:計算一個向量的最大值、最小值。
rand16:向量隨機數產生器。
rand16init:初始化向量隨機數產生器。
mul32:Q31數與Q31數向量乘法,結果為Q31數據。
pow:求平方。
(6)三角函數。
sine:使用泰勒級數計算一個向量的正弦。
(7)矩陣運算函數。
mmul:矩陣乘法。
mtrans:矩陣轉置。
(8)其他雜函數,如數據格式轉換等。
fltoq15:浮點數轉化為Q15格式數。
q15tofl:Q15格式數轉化為浮點數。
在c:\ti\docs\pdf下的spra480b.pdf文檔中,詳細說明了這些函數的用法。在c:\ti\c5400\dsplib\EXAMPLES文件夾中還列出了這些函數的應用示例,閱讀這些函數和應用示例將大大提高對算法的編程和應用能力。
7.2
C程序編譯
C語言開發(fā)的程序具有可移植性好的特點,除底層的硬件控制和對時間有嚴格要求的函數外,一般盡可能用C語言開發(fā),以加快DSP的開發(fā)速度,同時使程序的修改和移植也變得非常容易。
C語言代碼通過C編譯器先轉化為匯編程序,然后由匯編器編譯轉化為機器執(zhí)行碼。在將C語言編譯成匯編程序時,有一些固定的規(guī)則,學習這些規(guī)則對優(yōu)化代碼和混合編程都非常有好處。7.2.1
C編譯器生成的段
C54x有兩種存儲器:程序存儲器和數據存儲器,程序存儲器包含可執(zhí)行代碼,數據存儲器包含外部變量、靜態(tài)變量和系統(tǒng)堆棧等。C編譯器對C語言進行編譯后,生成若干個
可以進行重新定位的代碼和數據塊。除了生成3個基本的段.text、.data、.bss外,還有.cinit、.const、.stack、.sysmem段等。這些段分為兩類:已初始化段和未初始化段。已初始化段主要包含可執(zhí)行代碼和數據表,C編譯器共創(chuàng)建4種已初始化段。
(1).text段:包含可執(zhí)行代碼、字符串及編譯器產生的
常數。
(2).cinit段:包含初始化變量和常數表。
(3).const段:包含字符串和用const定義的常量。
(4).switch段:包含用.switch語句建立的表格。未初始化段用于為變量或函數執(zhí)行分配存儲空間,但沒有初始化,程序利用這些空間在運行時創(chuàng)建和存儲變量,C編譯器共創(chuàng)建3種未初始化段。
(1).bss段:為全局變量和靜態(tài)變量分配存儲空間。在
程序啟動后,C語言初始化引導程序將數據從.cinit段復制到
.bss段。
(2).stack段:為C語言堆棧分配存儲空間,用于傳遞變量、分配局部變量和保護函數現(xiàn)場等。
(3).sysmem段:為動態(tài)存儲器函數malloc、calloc和realloc分配存儲器空間。若C語言沒有用到這些函數,編譯器就不創(chuàng)建這個模塊。
其中堆棧段主要完成以下功能:保護函數的返回地址、分配局部變量、傳遞函數變量、保護調用函數現(xiàn)場及其他一些臨時結果。C編譯器定義的堆棧大小默認為1K字,也可以在連接命令行加上一個stack選項重新定義堆棧大小。C編譯器用堆棧指針(SP)指向堆棧的頂部。通常,.text、.cinit和.switch段必須映射到程序存儲器的PAGE0頁,具體存儲器可以是ROM或RAM;.const段必須映射到數據存儲器的PAGE1頁,具體存儲器可以是ROM或RAM;而.bss、.stack和.sysmem段必須映射到數據存儲器的PAGE1頁,具體存儲器只能是RAM。7.2.2
C編譯器的寄存器規(guī)則
在C語言環(huán)境中,不同的寄存器有不同的使用規(guī)則。在混合編程時,如果遵守這些規(guī)則,可有效地提高編程效率和程序的執(zhí)行效率。
寄存器在使用上分兩類:進入保存和調用保存。進入保存是由被調用函數負責保存,調用函數自由使用;調用保存是由調用函數分組保存,被調用函數自由使用。寄存器的使用和保護規(guī)則如表7.2所示。從表7.2中可以看出,被調用函數需保護AR1、AR6和AR7,其余寄存器由調用函數保護,所以調用函數只可自由地使用AR1、AR6、AR7。要使用其他寄存器,需在調用函數前壓棧保護。調用函數執(zhí)行完畢后再恢復為原來的值,而被調用函數則相反。SP無論是在調用函數還是被調用函數中,都不允許自由使用,但可以用匯編指令“FRAME#k”來管理。7.2.3
C程序的系統(tǒng)初始化
C程序在運行之前,必須創(chuàng)建C語言的運行環(huán)境,創(chuàng)建過程由C初始化程序完成,其函數名為c_int00。
這個函數包含在rts.lib的運行支持庫中,rts.lib庫中函數的源代碼都包含在rts.src中。要調用c_int00函數,只需在鏈接器使用“l(fā)rts.lib”選項即可,也可手動將其加入到項目中。c_int00初始化C語言運行環(huán)境時主要完成以下工作:
(1)為系統(tǒng)堆棧定義.stack段,并初始化堆棧指針。
(2)將.cinit段的初始化數據復制到.bss段中,對全局變量和靜態(tài)變量進行初始化。
(3)調用main()函數,開始運行程序。
7.3
C語言與匯編語言混合編程
C語言是一種通用編程語言,適用于對時間要求不高的場合。但如果運算時間非常緊張,C編譯器則很難充分利用DSP獨特的硬件結構來提高執(zhí)行效率,如充分利用循環(huán)尋址、位反轉尋址等。另外,C語言對底層的硬件操作比較困難,甚至無法實現(xiàn),而用匯編語言編程則比較容易,如初始化McBSP接口等。因此,采用C語言與匯編語言混合編程能充分發(fā)揮兩者的優(yōu)勢,達到最佳的效果。7.3.1混合編程方式
(1)獨立編寫C程序和匯編程序,只要兩者的接口滿足函數調用要求,就不會相互影響。如FFT程序一般先用匯編語言編寫,然后在C程序中調用。只要調用函數和FFT函數都滿足函數調用規(guī)則就能實現(xiàn)混合編程,達到優(yōu)勢互補的目的。(2)直接在C程序的相應位置插入匯編語句。這類匯編語句一般是對硬件進行操作,要求不能對C環(huán)境造成影響。如下面一條語句是在C程序中設置開中斷:
asm(″ RSBXINTM″); //開中斷7.3.2
C程序訪問匯編變量
C文件定義的變量名在編譯時均在名稱前加一下劃線“_”,以區(qū)別匯編文件定義的變量名,C文件中定義的函數名也如此。這樣即使兩種文件的變量名和函數名相同,也不
會產生沖突。變量名和函數名經編譯后都代表變量的存儲地址和函數的入口地址,由此可推出C文件與匯編文件相互訪問的方法。要使C文件能訪問匯編變量和函數,則需要在匯編文件定義這些變量名和函數名時,在其名稱前加下劃線“_”,而在C文件引用時不要加下劃線,具體實現(xiàn)方式如下:
(1)在匯編文件.bss段定義匯編全局變量。
①用.bss段定義變量,并在變量前加一下劃線;
②用.global命令聲明外部變量;
③在C文件中聲明外部變量。例7.1
C程序訪問匯編變量。
①匯編文件定義:
.global_input;聲明全局變量,名稱必須包含“_”
.bss_input,1
②C文件引用:
externintinput//聲明外部變量及數量類型,變量名要去掉“_”input=ioport0002;//讀外部端口0x0002到input中
(2)訪問匯編常數表。
①用.sect段定義常數表,并在變量前加一下劃線;
②用.global命令聲明外部變量;
③在C文件中聲明外部指針。
聲明的指針像C文件定義的指針一樣使用。例7.2
C程序訪問匯編常數表。
①匯編文件定義:
.global_sine;聲明全局變量,名稱必須包含“_”
.sect″sine_table″
_sine:
.word0x0,0x5a82,0x7fff,0x5a82,0x0,0xa57f,0x8002,0xa57f
;8點正弦表②C文件引用:
externintsine[]//聲明外部指針及數量類型,變量名要去掉“_”
for(i=0;i<8;i++)
x=sine[i];
(3)訪問匯編常數。
①用.set定義常數,并在變量前加一下劃線;
②用.global命令將其聲明為外部變量;
③在C文件中用#define聲明常數。常數名前去掉“_”,但在其前加“&”,表示取地址。匯編文件定義的常數像C文件定義的常數一樣使用。例7.3
C程序訪問匯編常數。
①匯編文件定義:
.global_table_size,_sine
_table_size .set8//匯編文件定義的常數
_sine:
.word0x0,0x5a82,0x7fff,0x5a82,0x0,0xa57f,0x8002,0xa57f
;8點正弦表②C文件引用:
externintsine[]
#defineTABLE_SIZE(int)(&table_size)//C文件引用匯編常數
for(i=0;i<TABLE_SIZE;i++)
x=
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- GB/T 45137-2024畜禽基因組編輯育種技術規(guī)程
- 2025年度緊急避難場所標示牌設計與施工合同3篇
- 2024物業(yè)服務合同補充:社區(qū)物業(yè)智能化改造協(xié)議3篇
- 2024水廠給排水設備采購與維護服務合同
- 腦梗死健康宣教
- 2024年水利樞紐建設勞務承包合同
- 專業(yè)個人道路運輸協(xié)議樣式2024
- 2024年財產質押擔保合同模板6篇
- 福建省南平市萬安中學2022年高一生物下學期期末試題含解析
- 色彩之旅模板
- 《診斷學》實訓指導
- 靜療并發(fā)癥護理
- 七年級上冊音樂試題附答案
- 2022年一級建造師《機電》考試寶典
- 2023年高考數學專項練習痛點問題之概率統(tǒng)計經典解答題含解析
- 物業(yè)管理勞務外包合同范本
- 消費者心理與行為分析PPT(第四版)完整全套教學課件
- 《財務共享實務》課程期末考試題庫及答案
- 小學四年級語文下冊全書背誦內容
- 新能源汽車技術高水平專業(yè)群建設項目建設方案
- ncv65系列安裝金盤5發(fā)版說明
評論
0/150
提交評論