第一篇: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 optionscompilerpreprocessor中,要包含的头文件的地址没有加进去,你可以找到头文件的地址,然后加进去。
问题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 optionslinkerlibraries中加入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学习心得笔记
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 optionscompilerpreprocessor中,要包含的头文件的地址没有加进去,你可以找到头文件的地址,然后加进去。
问题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 optionslinkerlibraries中加入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 optionsLinkerbasic,在Stack Size(-stack):填入800或者其他小于1024的数值。
调试程序:
在编译完成之后,要来下载程序并进行功能调试。FileLoad 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函数开使运行,点DebugGo main。既能看到源文件中代码的执行情况,又能看到汇编指令的执行情况ViewMixed 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 optionscompilerpreprocessor中,要包含的头文件的地址没有加进去,你可以找到头文件的地址,然后加进去。
问题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 optionslinkerlibraries中加入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 optionsLinkerbasic,在Stack Size(-stack):填入800或者其他小于1024的数值。
调试程序:
在编译完成之后,要来下载程序并进行功能调试。FileLoad 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函数开使运行,点DebugGo main。既能看到源文件中代码的执行情况,又能看到汇编指令的执行情况ViewMixed 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 optionsLinkerbasic,在Stack Size(-stack):填入800或者其他小于1024的数值。以免以后有出些不明的问题。
第四篇: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%,实际编程时尽可能地使用