DSP學習總結

DSP學習心得筆記

---------------- 白建成.baijc.icekoor

引言:學習DSP的時間有兩個多月了,收穫很多新知識,我們要每天都有進步纔行,以下內容沒有特別的順序,跟具自己的學習情況寫的,如果有不對的地方希望指出來,如果有不懂得也可以問我,大家相互交流很重要,我的一個郵箱:[email protected]歡迎聯繫!

建立新工程過程中:

問題1

 

"GPIO_Study.c", line 61: fatal error: could not open source file "DSP280x_Device.h"

1 fatal error detected in the compilation of "GPIO_Study.c".

解決方法:

因爲project àbuild optionsàcompileràpreprocessor中,要包含的頭文件的地址沒有加進去,你可以找到頭文件的地址,然後加進去。

 

問題2

 

undefined                        first referenced

 symbol                              in file

---------                        ----------------

_c_int00                         D:\DSP study\test3\Debug\DSP280x_CodeStartBranch.obj

FS$$MPY                          D:\DSP study\test3\Debug\DSP280x_CpuTimers.obj

FS$$TOL                          D:\DSP study\test3\Debug\DSP280x_CpuTimers.obj

>>   error: symbol referencing errors - './Debug/test3.out' not built

或者下面的問題:

undefined                        first referenced

 symbol                              in file

---------                        ----------------

_c_int00                         D:\DSP study\GPIO_Study\Debug\DSP280x_CodeStartBranch.obj

>>   error: symbol referencing errors - './Debug/GPIO_Study.out' not built

解決辦法都是下面:

這個問題是因爲沒有加在庫文件,請在project àbuild optionsàlinkeràlibraries中加入rts2800.lib

 

問題3

 

>> warning: creating .stack section with default size of 400 (hex) words.

   Use

            -stack option to change the default size.

>>   error: can't allocate .stack, size 00000400 (page 1) in RAMM1 (avail:

            00000380)

>>   error: errors in input - ./Debug/GPIO_Study.out not built

解決辦法:

這個問題是關於堆棧存儲大小的問題,他是說,創建堆棧段使用與設置400個字,並建議在堆棧操作中改變這。

個與設置。這時,需要進行如下修改就可通過:projectà build optionsàLinkeràbasic,在Stack Size(-stack):填入800或者其他小於1024的數值

調試程序:
在編譯完成之後,要來下載程序並進行功能調試。FileLoad Program,在工程文件夾下面的Debug文件夾下,選中**.out文件,點擊打開,便開始下載程序了。將**.out文件下載到目標板上2812的RAM中。
注意,這裏是調試,所以將程序下載到RAM。等到最後您要固化程序的時候,就得下載到FLASH了,因爲斷電之後,RAM裏面所有的數據都會消失。

(Run和Animate的區別,Run是如果遇到斷點的話它就停下來了。而Animate就算遇到斷點時先停止DSP內核,刷新窗口,然後接着繼續啓動運行,常用來連續刷新變量窗口和生成graph圖形等)——知識儲備。
添加斷點:
加上斷點的方法很簡單,只要在該行代碼前雙擊就行。雙擊之後,這行代碼前面會出現一個紅色圓塊。另外一種添加斷點的方法,就是在剛纔的編譯工具欄上,點一下那個小手圖形的按鈕,前提是你要把光標移動到想要設置斷點的哪一行上。
使用watch window:
Watch window的作用是來觀察程序運行過程中的各個變量的值。調用watch window的方法是點擊菜單欄的"View ","watch window",這時watch window就會顯示在CCS下方的信息區域;
選中所要觀察的變量,然後右鍵,在右鍵菜單中選擇add to watch window。
調試代碼觀察:
我們在調試程序的時候經常想讓程序從Main函數開使運行,點DebugGo main。 既能看到源文件中代碼的執行情況,又能看到彙編指令的執行情況ViewMixed Source/Asm;







關於F2812中用C語言來實現中斷的說明
1.首先在.cmd中定位系統中斷表:
MEMORY
{
PAGE 0 : 
......................................
PAGE 1 : 
......................................
PIE_VECT : origin = 0x000D00, length = 0x000100
...................................... 
}
SECTIONS
{
................................... 
PieVectTable : > PIE_VECT, PAGE = 1
.....................................
}
2.在C中制定該中斷的結構體:
#pragma DATA_SECTION(PieVectTable,"PieVectTable");
struct PIE_VECT_TABLE PieVectTable;(在DSP28_GlobalVariableDefs.C中初始化)
3.用一組常數(按照中斷向量的順序)初始化該名字爲PIE_VECT_TABLE的表:
typedef interrupt void(*PINT)(void);這裏有些一問,一下應該爲函數名??

// Define Vector Table:
struct PIE_VECT_TABLE {

// Reset is never fetched from this table. 
// It will always be fetched from 0x3FFFC0 in either
// boot ROM or XINTF Zone 7 depending on the state of
// the XMP/MC input signal. On the F2810 it is always
// fetched from boot ROM. 

PINT PIE1_RESERVED; 
PINT PIE2_RESERVED;
PINT PIE3_RESERVED;
PINT PIE4_RESERVED;
PINT PIE5_RESERVED;
PINT PIE6_RESERVED;
PINT PIE7_RESERVED;
PINT PIE8_RESERVED;
PINT PIE9_RESERVED;
PINT PIE10_RESERVED;
PINT PIE11_RESERVED;
PINT PIE12_RESERVED;
PINT PIE13_RESERVED;

// Non-Peripheral Interrupts:
PINT XINT13; // XINT13
PINT TINT2; // CPU-Timer2
PINT DATALOG; // Datalogging interrupt
PINT RTOSINT; // RTOS interrupt
PINT EMUINT; // Emulation interrupt
PINT XNMI; // Non-maskable interrupt
PINT ILLEGAL; // Illegal operation TRAP
PINT USER0; // User Defined trap 0
PINT USER1; // User Defined trap 1
PINT USER2; // User Defined trap 2
PINT USER3; // User Defined trap 3
PINT USER4; // User Defined trap 4
PINT USER5; // User Defined trap 5
PINT USER6; // User Defined trap 6
PINT USER7; // User Defined trap 7
PINT USER8; // User Defined trap 8
PINT USER9; // User Defined trap 9
PINT USER10; // User Defined trap 10
PINT USER11; // User Defined trap 11

// Group 1 PIE Peripheral Vectors:
PINT PDPINTA; // EV-A
PINT PDPINTB; // EV-B
PINT rsvd1_3;
PINT XINT1; 
PINT XINT2;
PINT ADCINT; // ADC
PINT TINT0; // Timer 0
PINT WAKEINT; // WD

.............
.............
// Group 12 PIE Peripheral Vectors:
PINT rsvd12_1;
PINT rsvd12_2;
PINT rsvd12_3;
PINT rsvd12_4;
PINT rsvd12_5;
PINT rsvd12_6;
PINT rsvd12_7;
PINT rsvd12_8;
};
然後在使我們在.cmd文件中定義的表有以上屬性:
extern struct PIE_VECT_TABLE PieVectTable;(在.h文件中)
4.初始化該表(在.c文件中)使之能夠爲主程序所使用:
const struct PIE_VECT_TABLE PieVectTableInit = {

PIE_RESERVED, // Reserved space
PIE_RESERVED, 
PIE_RESERVED, 
PIE_RESERVED, 
PIE_RESERVED, 
PIE_RESERVED, 
PIE_RESERVED, 
PIE_RESERVED, 
PIE_RESERVED, 
PIE_RESERVED, 
PIE_RESERVED, 
PIE_RESERVED, 
PIE_RESERVED, 


// Non-Peripheral Interrupts
INT13_ISR, // XINT13 or CPU-Timer 1
INT14_ISR, // CPU-Timer2
DATALOG_ISR, // Datalogging interrupt
RTOSINT_ISR, // RTOS interrupt
EMUINT_ISR, // Emulation interrupt
NMI_ISR, // Non-maskable interrupt
ILLEGAL_ISR, // Illegal operation TRAP
USER0_ISR, // User Defined trap 0
USER1_ISR, // User Defined trap 1
USER2_ISR, // User Defined trap 2
USER3_ISR, // User Defined trap 3
USER4_ISR, // User Defined trap 4
USER5_ISR, // User Defined trap 5
USER6_ISR, // User Defined trap 6
USER7_ISR, // User Defined trap 7
USER8_ISR, // User Defined trap 8
USER9_ISR, // User Defined trap 9
USER10_ISR, // User Defined trap 10
USER11_ISR, // User Defined trap 11

// Group 1 PIE Vectors
PDPINTA_ISR, // EV-A
PDPINTB_ISR, // EV-B
rsvd_ISR,
XINT1_ISR, 
XINT2_ISR,
ADCINT_ISR, // ADC
TINT0_ISR, // Timer 0
WAKEINT_ISR, // WD
.............
.............
// Group 12 E Vectors
rsvd_ISR, 
rsvd_ISR, 
rsvd_ISR, 
rsvd_ISR, 
rsvd_ISR, 
rsvd_ISR, 
rsvd_ISR, 
rsvd_ISR, 
};
//---------------------------------------------------------------------------
// InitPieVectTable: 
//---------------------------------------------------------------------------
// This function initializes the PIE vector table to a known state.
// This function must be executed after boot time.
//

void InitPieVectTable(void)
{
int16 i;
Uint32 *Source = (void *) &PieVectTableInit;
Uint32 *Dest = (void *) &PieVectTable;

EALLOW; 
for(i=0; i < 128; i++)
*Dest++ = *Source++; 
EDIS;

// Enable the PIE Vector Table
PieCtrl.PIECRTL.bit.ENPIE = 1; 

}
5.中斷服務程序:
讓以上的數值指向你所要的服務程序,例如:
PieVectTable.TINT2 = &ISRTimer2;
那麼,ISRTimer2也就成了中斷服務程序,
×××切記:一定要在主程序的開始先聲明該程序:
interrupt void ISRTimer2(void);

.............
.............
然後按照您的需要編制該程序:
interrupt void ISRTimer2(void)
{
CpuTimer2.InterruptCount++;
}

編程中遇到的問題:

1、  line 257: warning: last line of file ends without a newline

解決方法:

點擊出現的問題條,看光標定位在哪裏,然後一點點刪除,直到把編程的文字刪除,最後把刪除的寫出來,回車就行了,因爲回車的格式要在編輯狀態哈哈!

28016的定時器筆記

學過2812的人會知道,2812的定時器和28016的定時器的寄存器很不一樣。但是從功能上將差不多。

關於28016定時器的時鐘的討論

定時器的時鐘是由SYSCLKOUT經過TBCTL中的CLKDIVHSPCLKDIV進行配置;

主要說明,我們應該記得SYSCLKOUTHSPCLK之間還可以分頻,但是在這裏這個寄存器不影響。

關於28016定時器的時鐘同步的討論;

如果我們想使每個PWM模塊具有同步時鐘,我們可以通過軟件強制各個模塊之間同步,設定步驟如下:

   EPwm1Regs.TBCTL.bit.SYNCOSEL = 0  // Pass through

   EPwm2Regs.TBCTL.bit.SYNCOSEL = 0;  // Pass through

   EPwm3Regs.TBCTL.bit.SYNCOSEL = 0;  // Pass through

   EPwm1Regs.TBCTL.bit.SWFSYNC = 1;

   EPwm2Regs.TBCTL.bit.SWFSYNC = 1;

   EPwm3Regs.TBCTL.bit.SWFSYNC = 1;

以上程序是設定PWM1/2/3同步,我們由於我們只採用向上計數,所以不需要設定計數方向位。

接下來如果我們想PWM1PWM2輸出相位不一樣,保持某個相位差,我們可以通過寄存器設定;

EPwm1Regs.TBCTL.bit.PHSEN = TB_ENABLE;

   EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE;

   EPwm3Regs.TBCTL.bit.PHSEN = TB_ENABLE;

   EPwm1Regs.TBPHS.half.TBPHS = 0;

   EPwm2Regs.TBPHS.half.TBPHS = 250;   

   EPwm3Regs.TBPHS.half.TBPHS = 500;

首先使能,然後賦予值;

關於一些其他的配置如下:

EPwm3Regs.TBPRD = PWM3_TIMER_TBPRD;

   EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;     // Count up

   EPwm3Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;      // Enable INT on Zero event

   EPwm3Regs.ETSEL.bit.INTEN = PWM3_INT_ENABLE;   // Enable INT

   EPwm3Regs.ETPS.bit.INTPRD = ET_1ST;            // Generate INT on 3rd event

關於28016PWM配置的討論

PWM1A/B的獨立配置;

除了counter-compare比較寄存器,CMPACMPB,主要還是配置控制寄存器CMPCTL,對於影子寄存器的配置,還有影子寄存器的裝載模式。

這裏主要講關於PWMaction qualifier的配置;

模式1

// Setup shadow register load on ZERO

   EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;

   EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;

   EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;

   EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;  

   // Set Compare values

   EPwm1Regs.CMPA.half.CMPA = EPWM1_MIN_CMPA;    // Set compare A value

   EPwm1Regs.CMPB = 500;              // Set Compare B value

   // Set actions

   EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR;            // Set PWM1A on Zero

   EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;          // Clear PWM1A on event A, up coun

   EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;            // Set PWM1B on Zero

   EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;          // Clear PWM1B on event B, up count

   // Interrupt where we will change the Compare Values

   EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;     // Select INT on Zero event

   EPwm1Regs.ETSEL.bit.INTEN = 1;                // Enable INT

   EPwm1Regs.ETPS.bit.INTPRD = ET_3RD;           // Generate INT on 3rd event  

其中紅色的爲PWM的輸出方式配置,當PWM1.Acounter==0時,輸出爲0,在counter==CMPA時,且在向上計數,輸出爲1;而PWM1.B相反。

模式二:

   // Set actions

   EPwm2Regs.AQCTLA.bit.PRD = AQ_CLEAR;             // Clear PWM2A on Period

   EPwm2Regs.AQCTLA.bit.CAU = AQ_SET;            // Set PWM2A on event A, up count

   EPwm2Regs.AQCTLB.bit.PRD = AQ_CLEAR;             // Clear PWM2B on Period

   EPwm2Regs.AQCTLB.bit.CBU = AQ_SET;             // Set PWM2B on event B, up count

其中紅色的爲PWM的輸出方式配置,當PWM1.Acounter==period時,輸出爲0,在counter==CMPA時,且在向上計數,輸出爲1;而PWM1.B相同;

模式三:

// Set Actions

   EPwm3Regs.AQCTLA.bit.CAU = AQ_SET;         // Set PWM3A on event B, up count

   EPwm3Regs.AQCTLA.bit.CBU = AQ_CLEAR;       // Clear PWM3A on event B, up count

其中紅色的爲PWM的輸出方式配置,當PWM1.Acounter==CMPA時,輸出爲1,在counter==CMPB時,且在向上計數,輸出爲0,也就是計數在CMPACMPB之間時輸出爲1

模式四:

  EPwm3Regs.AQCTLB.bit.ZRO = AQ_TOGGLE;      // Toggle EPWM3B on Zero

此模式強制整個週期輸出高或者輸出地,與CMPACMPB無關,

關於28016PWM死區時間配置的討論

主要與死區有關的是三個寄存器:

Dead-Band Generator Control Register (DBCTL);

Dead-Band Generator Rising Edge Delay Register (DBRED);

Dead-Band Generator Rising Edge Delay Register (DBRED) Field Descriptions;

首先清楚延時時間的計算

爲:DBRED*TBCLK;

然後弄懂DBCTL就可以了。

 

注意理解下圖:

弄懂3個控制位什麼意思;

OUT_MODE,POLSEL,IN_MODE

注意第二位,這位通常用在輸入爲同一個通道時,也就是IN_MODE=0X00/0X03時。

簡單看一些deadband的配置:

EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;

輸出之前,輸入上升沿下降沿都被延時;
   EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HI;

沒有取反過程;
   EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL;

輸入全部爲A,此爲習慣性的配置;
   EPwm1Regs.DBRED =1000;
   EPwm1Regs.DBFED =500;

 

一週解決的爲題:

我的sin()函數能夠正常執行,cos()函數也能正常執行,但是當sin()計算完再計算cos(),仿真環境就會進入邏輯錯誤中斷,請問怎麼解決,是不是該重裝CCS

 

原因:之前一直把程序燒到RAM裏,總是隻能執行一個sin()cos()函數,然後RAM的空間就不夠了,由於也不會改RAM空間的大小,所以就把程序直接下到flash裏面,結果就好了。

 

遇到CCS和仿真器連不上的問題;

Error connecting to the target:

Error 0x80000240/134

Fatal Error during: Initialization, OCS

Unknown Error

Sequence ID: 0

Error Code: 134

Error Class: 0x80000240

I/O Port = 240

解決辦法:

我也試着解決這個問題,重裝了一次,結果沒有用。想着覺得是USB驅動的問題,然後就在設備管理器中,把USB的驅動刪除了,有重新裝了一遍,結果沒問題了。原因應該是以前用的USB口安裝的驅動,又被用於安裝其他的驅動,結果以前的USB驅動不能用了

2011.1.19

我在用dsp中的cos()sin()函數時,對他們的結果做驗證,發現他們有的計算出來的結果,和我用計算器計算出來的結果不一樣,還差不少。

解決辦法:

         首先堅信CCS的函數計算不會輕易的出錯,然後我就去查程序的問題,查不好長時間覺得沒問題,就繼續看程序運行的結果,結果發現有些計算正確,有些不正確,就在想執行過程中難道有隨機性,結果突然想到中斷的問題,我是在中斷中作了個旋轉矢量,通過中斷來使它旋轉,而直接把中斷中的值,拿來在每個sin,cos中用,所以纔出問題的。

         結果改動了一點就行了,將中斷中的值,在用的地方,重新付給另一個變量,這樣就能解決了。因爲sin,cos執行需要時間較長,而普通的賦值卻不是。

Flash API Error #65535:

The device is in limp mode, operation failed。以前一直沒有問題,不知道怎麼突然就這樣了。

解決辦法:

         燒寫的插件(網上這麼叫)沒有裝好的原因,我覺得就是仿真器第一次沒連接好,拔掉再連接幾次就行了。

2011.1.20

fatal error: file "D:\\DSP study\\ADC_Study\\Debug\\ADC_Study.obj" has a

   Tag_Memory_Model attribute value of "2" that is different than one

   previously seen ("1"); combining incompatible files

解決辦法:

         問題的出現可能是你lib下的庫有所改變引起的,project->built options->linker->libraries->rts2800_ml.lib,因爲之前一直用它,後來改成rts2800.lib就出現這個問題了,改回去就可以了。

data verification failed at address 0x8000
        Please verify target memory and memory map

解決方法:

可能是gel的問題,重新載入幾次,如果不行的話,就把仿真器重新接幾次,問題就應該沒有了,多數是硬件的問題。

針對CCS的圖像顯示,一個方式爲對程序中的某些變量畫圖,另一種方式是對DSP採集的數據畫圖,兩者在方法上有所不同。

         首先聲明畫圖很簡單,只要把重要的記住就可以了,其他的嘗試怎麼用就OK了,不用刻意去學,浪費時間;

至於這張圖中各個欄代表什麼,你隨便找個資料就給你

說得很清楚,但是沒有一份資料教你怎麼用的,這就是

網上資料的弊端。

你只要把右圖畫綠線的看懂就總夠了,其他的試着改變參

數,看看結果你就明白了。

 

 

 

接下來給你看看我的配置:

Dual time single time的區別在於顯示幾個波形

Svpwm_Time1 Svpwm_Time0 是我程序內部的

兩個變量,也就是SVPWMt1t0,記得前面加

&,不然結果不對,Acquisition Buffer Size設爲1

因爲我想通過終端來調試,每次終端,然後刷新

一次數據,這樣很方便,找點資料看,這裏不詳

細說明了,還有采樣時間,根據你的要求來定。

波形如下:

 

 

 

 

 

 

 

 

 

 

 

 

 


是不是很matlab中一樣哈!

另一種方式,不能採用中斷了,因爲中斷時間太長,影響採樣速度。

建議:在程序中建一個大的數組,然後運行一段時間,再將數組顯示在CCS中,Acquisition Buffer Size 此時不能爲1了,要和你的數組一樣長,Display Data Size等於Acquisition Buffer Size就可以,顯示出來就可以了。

如下圖:這是我AD採樣的波形,採集一個正弦波形,採用兩個通道。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


2011.01.24

error: symbol "_main" redefined: first defined in "D:\\DSP

   study\\DSP_Perfect\\Dsp_Perfect_110121W\\Perfect\\Debug\\Perfect.obj";

   redefined in "D:\\DSP

   study\\DSP_Perfect\\Dsp_Perfect_110121W\\Perfect\\Debug\\SCI_485.obj"

解決辦法:

         這個問題是系統編譯以後,在perfect.cSCI_485.c中分別有main();結果編譯會報錯。

2011.01.22

"D:\\DSP study\\DSP_Perfect\\Dsp_Perfect_110121W\\cmd\\F28016.cmd", line 125: error:

   run placement fails for object ".ebss", size 0x3ba (page 1).  Available

   ranges:

   RAMM1        size: 0x380        unused: 0x380        max hole: 0x380    

error: errors encountered during linking; "./Debug/Perfect.out" not built

解決辦法:

         雙擊錯誤提示,進入錯誤的地方,原因是我們申明的變量數,超過了RAMM1的聲明的大小,所以找過RAMM1,然後把size擴大就可以了,  RAMM1       : origin = 0x000480, length = 0x000400     /* on-chip RAM block M1 */,注意但是不能超過1024,也就是說最大是0x000400。同時也把projectà build optionsàLinkeràbasic,在Stack Size(-stack):填入800或者其他小於1024的數值。以免以後有出些不明的問題。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章