如何把自己所定义的结构体放在一个主程序中使用 我原打算定义一个结构体方便自己对一些变量方便使用,下面是我对定义体的总结: 首先,应该把该头文件加入到DSP_28Device.h的头文件当中去,再到DSP28_GlobalVariableDefs.c文件中写入相应的定义段,并在CMD文件中定义一个区域就可以使用了,针对我自己的结构体(见如下定义所写的),我所写的定一段是 #pragma DATA_SECTION(BaseRegs,"BaseRegFile"); 以下是我写的一个结构体定义:(以下代码本人保密,如有需要,请联系本人) 以下是我在一个".h"文件中定义的一个结构体: ////////////////////////数字输入输出功能定义的结构体//////////////////////////////// struct DIO_REG{ struct USERDIO_BITS{ union USERDI_REG union USERDO_REG struct UserDIO_REGS extern volatile struct UserDIO_REGS UserDIORegs; 定义完后还需要在DSP28_GlobalVariableDefs.c中加入的语句是: #pragma DATA_SECTION(UserDIORegs,"UserDIORegFile"); 然后在".cmd"文件中加入的区间定义: UserDIORegFile :> PAR_REG, PAGE = 1 ************************************************************************************************************** 以上都编写进DSP的程序后就可以使用自己所定义的结构体作变量了
几本值得参考的2812数据说明手册 第一本是C281x C/C++ 头文件和外设示例,里面有TI标准的CMD文件,查询号是SPRC097, 网址是http://focus./cn/docs/toolsw/folders/print/sprc097.html,里面主要介绍了头文件的定义和外设的一些只要例程,非常值得编译人员参考的。 第二本是TMS320x281x Boot ROM Reference Guide (Rev. C) ,查询号是SPRU095,里面主要介绍了如何引导相关ROM操作的问题。也很值得参考。 网址 DSP-F2812的C语言心得记录6-SCI通信发送模块中FIFO增强特性的使用方法 在SCI通信发送的过程中,有两种发送的方式供选择,一种是利用SCI模块的普通功能(即查询等待标志位的方式进行),另一种是利用F2812的增强特性FIFO功能进行数据的传送。比较这两种数据发送的方式发现,前一种查询等待的方式在发送一个字节的过程中会占用一个周期中的1ms时间(这是波特率为9600bps时候的情况),而后一种方式则基本不占用系统的周期等待时间,直接往Buf里面写数据就会自动的往外发送。 以下是FIFO功能的增前特性描述: 我在编程序的时候只用到增强特性中FIFO的发送功能,通过将SCIFFTX寄存器中的SCIFFEN位置1,使能FIFO模式。在任何操作状态下SCIRST都可以复位FIFO模式。 本人对寄存器的设置是 ScibRegs.SCIFFTX.all=0xE040; //1(写1表示SCI FIFO可以恢复发送或接收)/1(使能SCI FIFO增强功能)/1(重新使能发送FIFO操作)/00000(发送FIFO是空的)/0(没有TXFIFO中断)/1(清除TXFFINT标志位)/0(中断被禁止)/00000(中断级别为0) ScibRegs.SCIFFCT.all=0x00; //禁止串口自动检测波特率 for(temp=1;temp<TXindex1;temp++) { ScibRegs.SCITXBUF=DateReceiveBuf[temp]; } //然后FIFO就会把所要发送的数据都会自动的发送出去 ScibRegs.SCIFFTX.bit.SCIFFENA=0; //禁止FIFO功能,以确保利用回SCI的通信接收中断功能 上述的FIFO功能设置并不占用其它定时器中断的时间,这样可以有效的提高周期的资源利用率。提高了通信的效率。 对于第一种查询等待的方式,其中的设置是要等待一个字节完全的发送出去才能够进行其它模块的工作,这样的话是非常耗用时间和DSP的资源利用率的,而且其它模块的时间根本得不到保证,以下是我在调试时的一些相关设置: ScibRegs.SCITXBUF=DateReceiveBuf[temp]; while(!((1<<6) & ScibRegs.SCICTL2.all)); //等待这个字节的数据完全的发送出去,该指令按照波特率为9600bps来算的话,发送一个字节的时间将耗时1ms,这样是很浪费资源的,其它模块的功能根本执行不了。 根据上述的比较会发现,利用FIFO的功能进行通信是非常合理的,而且资源利用效率高。 链接命令文件(.cmd文件)通过段定位控制命令,分配程序代码和数据运行存储空间。 链接命令文件有两个重要的指令:MEMORY和SECTIONS。 (1)、MEMORY 指出目标系统中物理上存在的存储空间的范围,即可供程序使用的存储空间范围。在默认状态下,PAGE0代表程序空间,PAGE1代表数据空间。 (2)、SECTIONS 1)、描述输入段如何组合成输出段。 2)、定义可执行程序的输出段。 3)、指出输出段存放在存储空间中的位置。 4)、允许重命名输出段。 .cmd文件编写的目的 确定程序和数椐的装载运行空间,校验数据和程序代码的长度,定义输入/输出文件,安排系统中可用的存储器,程序段、数据段、堆栈以及复位向量和中断向量的地址空间。 链接命令文件通过段定位控制命令,分配程序代码空间、数据代码空间、程序运行空间、堆栈空间。 u .CMD文件命令格式 MEMORY:定义目标板物理存储空间分配,默认状态下,PAGE0为程序空间, PAGE1为数据空间。 SECTIONS:定义程序连接过程中各个输入段与输出段之间的关系,并给出输出段地址。① 给出输入段组合成输出段的方式; ② 定义可执行程序的输出段;③ 指出输出段存放在存储空间中的位置④ 允许重命名输出段。 例如 .cmd文件应用 MEMORY { PAGE 0: PROG: origin = 0x1400, len = 0x ;第0页程序空间开始地址0x1400,空间长度0x VECT: origin = 0x0080, len = 0x80 ;第0页中断向量开始地址0x0080,空间长度0x80 PAGE 1: REGS: origin = 0x60, len = 0x ;第1页寄存器空间开始地址0x60,空间长度0x IDATA: origin = 0x80, len = 0x1380 ;第1页数据空间开始地址0x80,空间长度0x1380 EDATA: origin = 0x1400,len = 0x8000 ;第1页扩展数据空间开始地址0x1400,空间长度0x8000 EDATA1: origin = 0x9400,len = 0x ;第1页扩展数据空间开始地址0x9400,空间长度0x } SECTIONS { .vectors: {}> VECT PAGE 0 ;中断向量在第0页 .text: {}> PROG PAGE 0 ;程序代码在第0页 .cinit: {}> PROG PAGE 0 ;初始化变量在第0页 .pinit: {} > PROG PAGE0 ;初始化参数在第0页 .bss: {} > IDATA PAGE1 ;非初始化变量在第1页 .far: {} > IDATA PAGE1 ;长调函数在第1页 .const: {} > IDATA PAGE1 ;常数在第1页 .switch: {} > IDATA PAGE1 ;数据交换空间在第1页 .sysmem: {} > IDATA PAGE1 ; .cio: {} > IDATA PAGE 1 ;C语言I/O调用在第1页 .stack: {} > IDATA PAGE 1 ;堆栈在第1页 .csldata: {} > IDATA PAGE 1 ;C语言宏调用在第1页 } 分别用C语言和汇编语言进行程序设计,计算正弦函数值,并比较代码效率。 1)C语言编程 #include <math.h> #define NX 180 //最大正弦角度 #define pi 3.14159 short i; double x[NX] //定义输入正弦角度数组(弧度值) double r[NX] //定义输出正弦结果数组 void main(void) { for (i=0;i<NX;i++) //将角度转换为弧度 { x[i] =pi*i/180; r[i]=sin(x[i]); //计算正弦值 } return; } 程序编译连接通过后,加载生成的.out文件,点击“Run”图标运行程序。我们在“Watch”窗口中可以观察输出的正弦值数组r[i] 。(见图1) 利用CCS图形工具可以观察这段数据的波形。注意CCS图像显示参数设置中,正确填入数据的起始地址,数据长度设为180,数据类型要设为32位浮点数。(见图2) 2)汇编语言编程 用汇编语言计算正弦值,一般采用泰勒级数展开的方法。角度正弦值的泰勒级数展开式如下:(见图3) 其中:x为弧度值。 注意: l x从0~1,原因是CPU寄存器ST1中的FRCT位为1,CPU处于小数模式。 l 程序文件中所有标号左对齐。 l 编译器默认的程序起始标号_c_int00。 3)汇编程序如下: .mmregs ;伪指令,定义C54x寄存器符号 .def _c_int00 ;伪指令,声明在当前模块中定义的标号 .def sin_start ;;;;;;;;;;;;;;;;;"coeff"段开始;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; d_coff .sect "coeff" .word .word 030bh ;1/42 *(215-1) .word 0666h ;1/20 *(215-1) .word 1556h ;1/6 *(215-1) ;;;;;;;;; 预留中间运算结果存储空间段;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; d_x .usect “sin_vars”,1 ;伪指令,在 "sin_vars"段中预留1个字的空间 d_squr_x .usect "sin_vars",1 d_temp .usect "sin_vars",1 d_sinx .usect "sin_vars",1 C_1 .usect "sin_vars",1 ;;;;;;;;;;;.text段开始;;;;;;;;;;;;;;;;;;;;;;;;;;; .text _c_int00: CALL sin_start sin_start: SSBX FRCT ; ST1中的FRCT位置1 STM #d_coff,AR3 STM #d_x,AR2 STM #C_1,AR4 LD #d_x, DP ST #06487h,d_x ; input x = PI/4 ST #7fffh,C_1 SQUR *AR2+,A ; A = x^2 ST A,*AR2 ; AR2 = x^2 || LD *AR4,B ; B = C_1 MASR *AR2+,*AR3+,B,A ; A = (1-x^2/72), T = x^2 MPYA A ; A = T*A = x^2*(1-x^2/72) STH A,*AR2 ; d_temp = A = x^2*(1-x^2/72) MASR *AR2-,*AR3+,B,A ; A = 1-x^2/42(1-x^2/72), ; T = x^2(1-x^2/72) MPYA *AR2+ ; B = x^2*(1-x^2/42(1-x^2/72)) ST B,*AR2 || LD *AR4,B MASR *AR2-,*AR3+,B,A ; A = 1-x^2/20(1-x^2/42(1-x^2/72) MPYA *AR2+ ; B = x^2*(1-x^2/20(1-x^2/42(1-x^2/72)) MASR *AR2-,*AR3+,B,A ; A = 1-x^2/6(1-x^2/20(1-x^2/42(1-x^2/72)) MPYA d_x ; B = x(1-x^2/6(1-x^2/20(1-x^2/42(1-x^2/72))) STH B, d_sinx ; d_sinx = sin(x) RET .end ;;;;;;;;;;;;;;;;;.text段结束;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4)算法分析 l 运算速度:CCS主界面选择 Profile->Enable Clock,启动时钟分析 Profile->View Clock,观察分析结果 C语言执行时间(见图4) 汇编语言执行时间(见图5) l 代码长度:Profile->Start New Sessions 输入name_profile ,--〉Range 分析程序代码长度。 (见图6、7) 图1: 图2: 图3: 图4: 图5: 图6: 图7: F2812的运行过程 1)上电运行时根据MP/MC引脚的状态决定是从片外的3fffc0处读取复位向量或者从片内的rom的3fffc0处读取复位向量。MC方式下从片内读取,MP方式下从片外读取。
2)一般我们用的是MC方式,即从片内读取复位向量,在片内的rom 3fffc0处有一个地址为3ffc00。 3)复位后处理器从3fffc0处读取3ffc00这个地址,所以程序从3ffc00处开始执行 4)3ffc00处开始的就是initboot过程,根据IO管脚的状态判断该进入哪一种引导方式 5)在SCITXA引脚为高电平时就是flash boot方式,此时置PC=3F7FF6 6)在片内flash的3F7FF6和3F7FF7处有一个跳转指令,该跳转指令就是LB _c_int00 7)执行这个跳转指令后程序就开始运行c_int00这个函数了 8)这个函数就是建立一个c程序的运行环境,等建立完c运行环境后c_int00调用main函数 9)main函数开始就是我们自己编写的应用程序了。 |
|