第一篇:DSP學習心得筆記
DSP學習心得筆記
----------------白建成.baijc.icekoor 建立新工程過程中: 問題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 studytest3DebugDSP280x_CodeStartBranch.obj FS$$MPY
D:DSP studytest3DebugDSP280x_CpuTimers.obj FS$$TOL
D:DSP studytest3DebugDSP280x_CpuTimers.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中的CLKDIV和HSPCLKDIV進行配置;
和
主要說明,我們應該記得SYSCLKOUT和HSPCLK之間還可以分頻,但是在這里這個寄存器不影響。
關于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同步,我們由于我們只采用向上計數,所以不需要設定計數方向位。
接下來如果我們想PWM1與PWM2輸出相位不一樣,保持某個相位差,我們可以通過寄存器設定;
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配置的討論
PWM1的A/B的獨立配置;
除了counter-compare比較寄存器,CMPA,CMPB,主要還是配置控制寄存器CMPCTL,對于影子寄存器的配置,還有影子寄存器的裝載模式。這里主要講關于PWM中action 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.A在counter==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.A在counter==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.A在counter==CMPA時,輸出為1,在counter==CMPB時,且在向上計數,輸出為0,也就是計數在CMPA與CMPB之間時輸出為1;
模式四:
EPwm3Regs.AQCTLB.bit.ZRO = AQ_TOGGLE;
// Toggle EPWM3B on Zero 此模式強制整個周期輸出高或者輸出地,與CMPA與CMPB無關,關于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驅動不能用了。
第二篇:DSP學習心得筆記
DSP學習心得筆記
----------------白建成.baijc.icekoor 引言:學習DSP的時間有兩個多月了,收獲很多新知識,我們要每天都有進步才行,以下內容沒有特別的順序,跟具自己的學習情況寫的,如果有不對的地方希望指出來,如果有不懂得也可以問我,大家相互交流很重要,我的一個郵箱:baijc@163.com歡迎聯系!
建立新工程過程中: 問題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 studytest3DebugDSP280x_CodeStartBranch.obj FS$$MPY
D:DSP studytest3DebugDSP280x_CpuTimers.obj FS$$TOL
D:DSP studytest3DebugDSP280x_CpuTimers.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中的CLKDIV和HSPCLKDIV進行配置;
和
主要說明,我們應該記得SYSCLKOUT和HSPCLK之間還可以分頻,但是在這里這個寄存器不影響。
關于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同步,我們由于我們只采用向上計數,所以不需要設定計數方向位。
接下來如果我們想PWM1與PWM2輸出相位不一樣,保持某個相位差,我們可以通過寄存器設定;
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配置的討論
PWM1的A/B的獨立配置;
除了counter-compare比較寄存器,CMPA,CMPB,主要還是配置控制寄存器CMPCTL,對于影子寄存器的配置,還有影子寄存器的裝載模式。
這里主要講關于PWM中action 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.A在counter==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.A在counter==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.A在counter==CMPA時,輸出為1,在counter==CMPB時,且在向上計數,輸出為0,也就是計數在CMPA與CMPB之間時輸出為1;
模式四:
EPwm3Regs.AQCTLB.bit.ZRO = AQ_TOGGLE;
// Toggle EPWM3B on Zero 此模式強制整個周期輸出高或者輸出地,與CMPA與CMPB無關,關于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 studyADC_StudyDebugADC_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 是我程序內部的 兩個變量,也就是SVPWM的t1,t0,記得前面加 &,不然結果不對,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
studyDSP_PerfectDsp_Perfect_110121WPerfectDebugPerfect.obj”;
redefined in “D:DSP
studyDSP_PerfectDsp_Perfect_110121WPerfectDebugSCI_485.obj” 解決辦法:
這個問題是系統編譯以后,在perfect.c和SCI_485.c中分別有main();結果編譯會報錯。
2011.01.22 “D:DSP studyDSP_PerfectDsp_Perfect_110121WcmdF28016.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的數值。以免以后有出些不明的問題。
第三篇:DSP學習心得筆記(更新20140717)
DSP學習心得筆記
----------------白建成.baijc.icekoor 引言:學習DSP的時間有兩個多月了,收獲很多新知識,我們要每天都有進步才行,以下內容沒有特別的順序,跟具自己的學習情況寫的,如果有不對的地方希望指出來,如果有不懂得也可以問我,大家相互交流很重要,我的一個郵箱:baijc@163.com歡迎聯系!
建立新工程過程中: 問題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 studytest3DebugDSP280x_CodeStartBranch.obj FS$$MPY
D:DSP studytest3DebugDSP280x_CpuTimers.obj FS$$TOL
D:DSP studytest3DebugDSP280x_CpuTimers.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 inputCobing LiuCSDN.pdf》
第四篇:Dsp學習筆記
GPIO作為通用I/O口使用
a)EALLOW;//防止私自寫或覆蓋寄存器的內容,加了這句,接下來可以操作寄存器了 b)GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0;// GPIO0復用為普通I/O功能 c)GpioCtrlRegs.GPADIR.bit.GPIO0 = 1;// 1,設置為輸出;0設置為輸入 d)EDIS;//加了這句,接下來不可以操作寄存器
注:EALLOW,EDIS總是成對出現中斷過程(代碼以配置SCIB模塊的接收中斷為例,LSPCLK是37.5MHz)
中斷共分三級,1,外設級;2,PIE級;3,CPU級;外設級的中斷標志必須手動清零;PIE級和CPU級的中斷標志位由硬件自動清零。中斷響應例程:
第一步,配置中斷源,即允許產生什么類型點中斷。例如,定時器中斷,串口中斷,外部中斷等。ScibRegs.SCICTL2.bit.RXBKINTENA =1;允許接收中斷
第二步,配置PIE(外部中斷擴展)
a)InitPieCtrl();//初始化Pie控制
b)InitPieVectTable();//初始化Pie向量表控制
c)EALLOW;
d)PieVectTable.SCIRXINTB=&scibreceive;//指定中斷服務程序地址e)EDIS;
f)PieCtrlRegs.PIECTRL.bit.ENPIE=1;//使能從PIECTRL中讀取中斷向量 g)PieCtrlRegs.PIEIER9.bit.INTx3=1;//使能SCIB的接收中斷
h)IER |= M_INT9;//允許外部中斷
i)EINT;
j)ERTM;
第三步,中斷響應
在中斷服務程序里,必須用PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;//清楚中斷已響應標識,再寫自己等程序代碼串口配置
InitScibGpio();scib_echoback_init();AD轉換
InitAdc();//允許ADC時鐘,帶隙和參考電路上電,核中模擬電路上電
AdcRegs.ADCTRL2.all = 0x2000;//ADC模塊開始轉換
程序在FLASH運行時,需要加如下兩句代碼:(不知道具體原因)
MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);InitFlash();
第五篇:dsp學習心得
一.我是已經從事DSP開發有幾年了,看到許多朋友對DSP的開發非常感興取,我結合這幾年對DSP的開發寫一寫自己的感受,一家之言,歡迎指教。我上研究生的第一天起根據老板的安排就開始接觸DSP,那時DSP開發在國內高校剛剛開始,一臺DSP開發器接近一萬還是ISA總線的,我從206開始240、2407A都作過產品,對5402、2812、5471在產品方案規劃制定和論證時也研究過。由于方向所限對6X、8X系列沒有接觸。我發現在國內無論在公司或高校許多地方為了加快開發周期往往把一個產品開發分為硬件和軟件兩個相對獨立部分,由不同的人完成。這在具有一定技術和管理基礎的公司,由總設計師統一規劃協調,分任務并行完成的情況下是可行的,也是符合現代產品開發規律的。但是在高校人員的流動很大,研究生的有效科研時間很短、基礎差(許多研究生起步時對電熔、電阻、三極管的分類和選型都很困難,我也是這樣過來的)更不用說系統規劃設計了,況且許多老板自己也不太懂,師兄有自己的任務,他們搞明白時也畢業了。在許多高校做DSP就是找一個算法加到自己的主程序里,在板子上跑一下,基本達到效果就可以了,至于可靠性是次要的,產業化無從談起,這已經算不錯的了。其實我覺得一個系統的完成,系統的規劃是最重要的,在規劃時對硬件設計的知識和認識是決定性的,它可以讓你知道什么是可行的,什么是不可行的,當你同時具有軟件設計能力時,就可以合理的分配系統功能,完成使用VHDL進行系統行為描述-―系統功能劃分―― 系統子結構設計這樣的自頂向下的設計規劃流程,成為系統設計專家、項目經理,否則只是硬件工程師、軟件工程師。無論作51、196、還是DSP都是這樣。下面分別談談我對硬件和軟件設計的感受硬件設計是系統設計的關鍵,國內和國外產品的差距往往是硬件設計水平高低決定的,任何軟件設計思想沒有可靠的物理載體都是空中樓閣,紙上談兵。學校的研究生很多都想避開硬件設計,對于一個全新的設計與其說不屑不如說不敢。試想一下燒幾個片子的壓力要比跑飛幾段程序的壓力大的多,尤其是功率器件,一旦燒掉,弄不好火光沖天,人的自信都沒了。況且改一次板周期長,經費高,還不知行不行。其實在國外實力一般的公司也是盡量避免硬件的更新設計,產品一旦定型往往通過軟件升級,這是公司的發展策略,對個人而言物以希為貴,培養一個硬件設計師往往要比軟件設計師時間長花費多。在設計dsp硬件時,開始設計最小系統板,系統按功能分板設計調試,注意分板電路的穩定性可能不如整板電路,要多加入抗干擾環節,分板間的引線包括電源線地線要短,盡量在10公分以內,實在不行加入光耦隔離、采用隔離電源。切記電源線、地線的干擾遠比信號干擾對系統的危害大得多,又常常被人忽視。電路板工作正常的先決條件就是電源正常!當分板電路正常后再更居情況設計整板電路。在調試時發現的問題一定要找到原因解決,即使是飛線,割線,不要寄希望于下一板改了再看,除非原理性錯誤。每一個功能環節多準備幾套方案。DSP的選型要根據系統功能而定,2000是一個功能比較全的控制器,但運算性能相對低,但目前大部分控制類、家電類包括中低層次的工業總線通信產品足夠了,281X不錯但太貴,而且開發技術不成熟。54XX更像一個協處理器,其實高端產品5471就很好,功能完*,但BGA封裝對產品的開發有一定難度。如果沒有從事過嵌入式系統開發的朋友其實可以從51看起,許多思想是共通的,51很經典沒有哪一款微處理器像51那樣使用持久和普遍。在硬件設計時更多的精力放在外圍電路設計上,外圍電路設計的靈活性要比DSP本身高得多,難度大得多。建議多考慮CPLD。軟件設計上,著眼點不要僅局限于某種算法和控制策略,而是軟件系統框架的制定,即操作系統的選擇和實現,算法和控制策略只是其中技巧性很強的子程序和子程序間參數相互關系,建議設計軟件時能具有操作系統、數據結構和編譯原理方面的知識,特別是使用C。對DSP的內部硬件結構一定要掌握,特別是中斷結構和流程、流水線操作,不然飛都不知道怎么飛的。在語言選擇上我當時是這么給自己規定的先編20個左右的匯編程序,每個代碼量超過4K,使用語句范圍覆蓋全部語句的60%-70%,在此基礎上使用C。現在發現用C構建程序的主體框架(操作系統)比較快而其不容易出錯,(我現在正在用ASM根據UCOSII的思想重寫自己的操作系統)但對系統實時性影響比較大的運算算法一般采用MATLAB――C――ASM的辦法仿真調試優化,這里的優化不單單是利用優化器優化,而是根據數據的特點改變運算方法,以除法為例C里的/號其實掩蓋了許多技巧,當除數為常數時就可以放大倒數移位相乘移位的辦法進行,精度高速度快。這些辦法只有掌握了ASM語言并用ASM語言思考才會熟練應用。另外我想告訴一些作算法特別是控制算法的朋友,千萬不要隨意評判一個算法的優劣,在程序中程序和代碼優化的程度往往影響了控制效果好壞,而不是算法本身的思想。其實在實際中往往PID甚至PI、PD就夠了,神經元、模糊、小波適用于研究和寫論文,模糊在實際中用的多一點,主要是小日本用的比較成熟,我再恨日本人,這點也服氣,小日本就是滑,許多物理現象搞不透,就用這法,還管用,題外話。最后我想說的是,當我們面對市場要求時,產品往往考慮的是可靠性、性能、價格而不是你用的什么芯片,在滿足性能的基礎上結構越簡單就越可靠,芯片越通用價格就越低,能用51就不用196,能用2407就不用2812,除非把芯片本身作買點利用高成本贏取高利潤。無論2000還是5000、6000系列都有市場前景,關鍵是要做深做透獲取知識的方法、處理項目的能力是相通的,具體的說就是不要把目光盯在做硬件還是做軟件上,用ASM還是C,要勤動手打好基礎,提高自己對系統總體設計的能力,從系統的眼光看問題。為什么都是做DSP的有的畢業拿3000,有的5000、8000,除了運氣和關系外,重要的是你對事物的認識深度和高度。我一直都記住這句話:有前途的人做什么都有前途,沒前途的人做什么都沒前途。二.與其說是鉆在里面,畢業設計是搞240,在老師的壓力做出了一點東西,這期間主要是對DSP的各種基礎知識的熟悉與理解,對DSP的真正深入是在公司工作以后。當初進公司,因為正有一個項目需要用5410要我接手。說實話,在學校期間我5000的書都沒有看過一眼,可沒辦法,只能靠自己了。不過好的是我2000DSP的基礎很好。接過項目后,我第一個星期就全部看的是5000的指令,DSP的結構倒沒怎么看,因為項目硬件已成型,主要是算法。這樣,花了一個星期熟悉指令與項目相關的程序,第二個星期也就開始編程了。半個月以后我對5410也就用很熟了的,當然主要還是講在算法方面。這個項目太概做了四個月吧,系統程序是我編寫的,主要有如64位加減乘除乘方開方、及時域方面的一些算法。現在又做一個控制系統,用2407開發的,硬件主要有直交變頻,并把2407的所有外設資源全部用到了。現在我可以這樣自夸一句吧:TI的2000系列與5000系列的我都熟悉,要我去以此做個系統,沒問題。上面是把我搞DSP的經歷簡單說了一下的吧,在這里我想對正在學及想學DSP的難兄們說一句的是,DSP并不是很難。當然,這個前提是你的基礎要好,我單片機,接口都還行,當初就是從單片機改成DSP的。有了單片機的基礎再去學2000第列的DSP(下面的DSP單指2000系列,另有說明為止),你就可以把DSP看成一個super microcontroller了。相比之下,DSP除了比單片機多了更豐的外設接口(SPI,SCI、CAN、PWM、CAP、QEP等等),他就是一塊單片機,只不過在單片機來說你要另加芯片的工作,DSP全部把它做在一塊芯片去了,我現在看DSP也真就這么簡單。前面有人提到DSP主要是做算法,這句話有一定的片面性: TI有很多系列的DSP,現在主流的DSP主要為2000系列、3000系列、4000系列、5000系列、6000系列。除了2000與5000系列是定點DSP外,其余的均為浮點系列。TI的2000系列主要長處是在用于控制系統,因為它的資源非常豐富,前面提到,在控制系統中用到的一些外設2000系列均在片內集成了。TI的5000系列主要長處是用于數字信號的算法處理,這里所講算法處理主要是指在數字信號處理時的一些算法,如FIR、IIR、FFT等等。5000系列的DSP的速度比2000快,2407最快只能到40M,2800系列除外,5410的DSP可以達到160M,如現在我們主要用來做數字信號方面的處理以及簡單的靜態圖像處理等這樣一些在資源需要處于中等的一些算法。TI的6000系列主要是用在實時圖像處理,這個就更則重于算法處理。一般的硬件很少自制,我們是用TI的DSK板再加上自主板相結合。三.使用C/C++語言編寫基于DSP程序的注意事項
1、不影響執行速度的情況下,可以使用c或c/c++語言提供的函數庫,也可以自己設計函數,這樣更易于使用“裁縫師”優化處理,例如:進行絕對值運算,可以調用fabs()或abs()函數,也可以使用if...else...判斷語句來替代。
2、要非常謹慎地使用局部變量,根據自己項目開發的需要,應盡可能多地使用全局變量和靜態變量。
3、一定要非常重視中斷向量表的問題,很多朋友對中斷向量表的調用方式不清楚。其實中斷向量表中的中斷名是任意取定的,dsp是不認名字的,它只認地址!中斷向量表要重新定位。這一點很重要。
4、要明確dsp軟件開發的第一步是對可用存儲空間的分析,存儲空間分配好壞關系到一個dsp程序員的水平。對于dsp,我們有兩種名稱的存儲空間,一種是物理空間,另一種是映射空間。物理空間是dsp上可以存放數據和程序的實際空間(包括外部存儲器),我們的數據和程序最終放到物理空間上,但我們并不能直接訪問它們。我們要訪問物理空間,必須借助于映射空間才行!但是映射空間本身是個“虛”空間,是個不存在的空間。所以,往往是映射空間遠遠大于實際的物理空間,有些映射空間,如io映射空間,它本身還代表了一種接口。只有那些物理空間映射到的映射空間才是我們真正可訪問(讀或寫)的存儲空間。
5、盡可能地減少除法運算,而盡可能多地使用乘法和加法運算代替。
6、如果ti公司或第三方軟件合作商提供了dsplib或其他的合法子程序庫供調用,應盡可能地調用使用。這些子程序均使用用匯編寫成,更為重要之處是通過了tms320算法標準測試。而且,常用的數字信號處理算法均有包括!
7、盡可能地采用內聯函數!而不用一般的函數!可以提高代碼的集成度。
8、編程風格力求簡煉!盡可能用c語言而不用c++語言。我個人感到雖然c++終代碼長了一些,好象對執行速度沒有影響。
9、因為在c5000中double型和float型均占有2個字,所以都可以使用,而且,可以直接將int型賦給float型或double型,但,盡可能地多使用int數據類型代替!這一點需要注意!
10、程序最后至少要加上一個空行,編譯器當這個空行為結尾提示符。
11、大膽使用位運算符,非常好用!
12、2003年6月份從ti的網站上下到了關于tms320c67x系列dsp的快速算法庫,于是,tms320c5000和c6000全系列的快速算法庫都問世了,這些算法庫均可供c/c++語言直接調用,優化程度100%,實際編程時盡可能地使用