P.11
实验名称: DSP实验综合报告 姓名: 学号:
void InitPll(void)函数用于锁相环初始化,初始化PLL模块;
如果外部晶振为30MHz,计算得SYSCLK为30MHz*10/2=150MHz。 3 程序段○
void InitPeripheralClocks(void) { EALLOW; }
设置高速外设时钟预定表寄存器HISPCP和HSPCLK,使高速外设时钟频率=SYSCLK/(HSPCLK*2)=150MHz/2=75MHz;
设置低速外设时钟预定表寄存器LOSPCP的LSPCLK,使低速外设时钟频率=SYSCLK/(LSPCLK*2)=150MHz/4=37.5MHz;
SysCtrlRegs.HISPCP.all = 1; // HISPCLK= SYSCLK /HISPCP *2 SysCtrlRegs.LOSPCP.all = 2; // LOSPCLK= SYSCLK / LOSPCP *2 SysCtrlRegs.PCLKCR.all = 0;// 开启部分外设 EDIS;
装 向PCLKCR写入0x909,用来使能EVA,ADC,SPI,SCIB 等外设时钟。 4 程序段○
void DisableDog(void) { EALLOW; }
void DisableDog(void)该函数用于关闭看门狗;
设置看门狗控制寄存器WDCR的WDDIS(位6)为1屏蔽看门狗模块。 5 程序段○
void InitSysCtrl(void) { }
void InitSysCtrl(void)函数用来初始化系统控制;
包括关闭看门狗,设置初始化始终频率,初始化外设时钟频率。 6 程序段○
订 线 SysCtrlRegs.WDCR = 0x0068; //关闭看门狗;; EDIS;
DisableDog(); InitPll();
InitPeripheralClocks();
P.12
实验名称: DSP实验综合报告 姓名: 学号:
void InitCputimer(void) { EALLOW; CpuTimer0Regs.TPR.all = 149; CpuTimer0Regs.TPRH.all= 0; CpuTimer0Regs.PRD.all = 999; CpuTimer0Regs.TCR.all =0xf000; }
void InitCputimer(void)函数用于初始化CPU定时器;
设定CPU定时器的频率,预定标寄存器写入149,将系统时钟分频为1MHz,TIMER0TPRD写入99999 时钟周期值为1s;
TIMER0TCR的14,15位置位,清除中断标志位、中断使能。 7 程序段○
interrupt void INT_1_7(void); EDIS;
装 void InitPIE(void)
{ EALLOW; }
void InitPIE(void)函数用于初始化PIE控制器;
清零PIEIFR寄存器和PIERER寄存器,使能PIE中断向量表,清零中断标志位 8 程序段○
void main(void) { InitSysCtrl();
订 PieCtrlRegs.PIEIFR1.all=0x0000; PieCtrlRegs.PIEIER1.all=0x0040; PieCtrlRegs.PIECRTL.bit.ENPIE=0x1; PieCtrlRegs.PIEACK.all =0x1; EDIS;
线 IOinit(); InitCputimer(); InitPIE(); EALLOW;
PieVectTable.TINT0= & INT_1_7;// asm(\ and IFR,#00H\asm(\ or IER,#01H\asm(\ EINT\
P.13
实验名称: DSP实验综合报告 姓名: 学号:
}
SysCtrlRegs.LPMCR0.all=0x0; EDIS;
for(;;){asm(\
void main(void)为程序主函数。
扩展内容:
定义变量无符号整形变量led,写入组号。 程序段
unsigned int led;
interrupt void INT_1_7(void) {led=0x0014; LedOut(led); }
装 void LedOut(Uint16 led) { Uint16
i;
EALLOW;
//将GPIOB8~GPIOB15配置为输出,D0~D7 } 实验现象:
第5个红灯和第3个红灯被点亮。
GpioMuxRegs.GPBDIR.all = GpioMuxRegs.GPBDIR.all|0xff00; EDIS;
//显示高8位
GpioDataRegs.GPEDAT.all = 0xfffb; //LEDB选通 GpioDataRegs.GPBDAT.all = ~led;
for (i=0; i<100; i++){} //延时 GpioDataRegs.GPEDAT.all = 0xfffa; //LEDA选通 GpioDataRegs.GPBDAT.all = ~(led<<8);//显示低8位 for (i=0; i<100; i++){}
订 线
GpioDataRegs.GPEDAT.all = 0xffff; //锁存高8位
GpioDataRegs.GPEDAT.all = 0xffff; //锁存低8位
(2)将红灯按规则点亮:2ms亮一次,七次为一个周期。
1 程序段○
P.14
实验名称: DSP实验综合报告 姓名: 学号:
void InitCputimer(void) { }
初始化PLL模块中外部晶振为30MHz,计算得SYSCLK为30MHz*10/2=150MHz,预定标寄存器写 入149,将系统时钟分频为1MHz,TIMER0TPRD写入999,时钟周期值为1ms。TIMER0TCR的14,15位置位,清除中断标志位、中断使能。 2 程序段○
中断函数程序:
EALLOW; CpuTimer0Regs.TPR.all = 149; CpuTimer0Regs.TPRH.all= 0; CpuTimer0Regs.PRD.all = 999; CpuTimer0Regs.TCR.all =0xf000; EDIS;
装 interrupt void INT_1_7(void) {k++;
if(k==0) {led=0x0000;LedOut(led);} if(k==1){led=0xfefe; LedOut(led);} if(k==2){led=0x0000;LedOut(led);} if(k==3){led=0xfcfc; LedOut(led);} if(k==4){led=0x0000;LedOut(led);} if(k==5){led=0xf8f8;LedOut(led);} if(k==6){led=0x0000; LedOut(led);} if(k==7){led=0xf0f0;LedOut(led);} if(k==8){led=0x0000; LedOut(led);} if(k==9){led=0xe0e0; LedOut(led);} if(k==10){led=0x0000; LedOut(led);} if(k==11){led=0xc0c0; LedOut(led);} if(k==12){led=0x0000; LedOut(led);} if(k==13){led=0x8080; LedOut(led);} PieCtrlRegs.PIEACK.all =0x1; CpuTimer0Regs.TCR.all =0xf000;}
根据led位置和显示情况将对应的十六进制值赋给led变量,通过if语句实现预期功能。 3 程序段○
void LedOut(Uint16 led)
订 线 P.15
实验名称: DSP实验综合报告 姓名: 学号:
{
Uint16 i; EALLOW;
GpioMuxRegs.GPBDIR.all = GpioMuxRegs.GPBDIR.all|0xff00; EDIS;
GpioDataRegs.GPEDAT.all = 0xfffb; GpioDataRegs.GPBDAT.all = ~led; for (i=0; i<100; i++){} GpioDataRegs.GPEDAT.all = 0xfffa; GpioDataRegs.GPBDAT.all = ~(led<<8); for (i=0; i<100; i++){}
GpioDataRegs.GPEDAT.all = 0xffff;
GpioDataRegs.GPEDAT.all = 0xffff; }
六、讨论、心得与感想
装 订 1、4次程序实验的运行原理与区别联系。
实验一是仅仅利用了2个文件(主函数和一般性C语言非外设的连接文件)就实现了对GPIO的控制,同时没有使用TI定义的结构体进行对寄存器的操作。变量指针地址全部都是自己申明的。函数也全部都是自己自定义的。这样操作的化简单明了,不用纠结于文件之间的关系。但是这种编程方法不适合大规模编程,同时对寄存器的操作也比较复杂,可读性差。所以只能当是入门级别的编程方法。在以后的实验中我们大可以通过引用调用TI提供的资源文件简化编程的进程和自己编写的代码量,省略很多不必要的步骤,同时引用统一的函数和变量能大大提高可读性和移植性,提高编写大型项目程序的简洁性和难度。
实验二也是和实验一一样仅仅使用两个文件实现的项目,在这次的实验中我们通过对提供源码的修改,了解学习的中断函数的编程步骤和运行过程,复习了之前学过的定时器的使用方法。这种方法如上所述是入门级别的编写方法。也是可以通过引用TI的相关的资源文件实现对中断向量表的控制,和中断向量的定义等等功能,实现中断函数编程的标准化。
实验三是利用了了 TI 的头文件,不再去申明变量地址指针,变量按 TI 要求书写。另外,利用了寄存器连接命令文件,全局变量说明文件。所以主函数中省略了变量地址指针的定义。
之所以能省略指针变量的定义是因为在项目中包含了头文件device.h中引用了大量相关资源的头文件如:DSP281X_Gpio.h等。然后在在这些文件中已经定义好了很多的寄存器结构联合体,这些结构联合体的内部元素寄存器指针已经定义好了赋值为相应的地址。
关于DSP281x_GlobalVariableDefs.c和DSP281x_Headers_nonBIOS.cmd这两个文件的功能感想分析在后面有说。
线 P.16
实验名称: DSP实验综合报告 姓名: 学号:
实验三的第二种实现方法是利用了 TI 的头文件及初始化程序。部分函数可以省去。在led_InitPll.c文件中注析了函数InitPll(void)、InitPeripheralClocks(void)、DisableDog(void)、 InitSysCtrl(void)等等函数。这是因为在TI资源文件中DSP281x_GlobalPrototypes.h中让相关的函数全局化定义了,同时还包含了一些TI的初始化程序文件如DSP281X_Gpio.c、DSP281X_SysCrl文件等。让主函数可以轻松调用相关的函数。
同时值得注意的是项目中包含了DSP281x_GlobalVariableDefs.c这个文件,简而言之,这个文件是用来对.h文件中定义的结构联合体进行在块(section)中分配地址空间的,一旦使用了TI定义的结构联合体控制寄存器就必须使用这个.c文件。还有实验三的两种实现方案中出现了DSP281x_Headers_nonBIOS.cmd这个连接命令文件,根据我个人对这个文件内容的解读,我认为DSP281x_GlobalVariableDefs.c中建立了结构联合体实例与XXXFile的联系,而这个连接命令文件就建立了XXXFile(section块)与相应功能的存储空间之间的联系或者说与开发板的存储空间之间的地址映射。同时也可以省略了地址指针变量的定义。
2、实验过程中遇到的问题及解决方案
(1)实验一和实验二较容易,只要做好相应GPIO口初始化和CPU定时器的初始化,并且赋值正确就可以比较顺利地完成试验。
(2)实验三思路与程序设计难度不大,但在调试过程中遇到了比较大的问题,编译通过后下载到TMS
装 实验板上运行时出现错误,分析并请教老师后得知,原因是程序编译下载操作有误,应当在编写或修改程序后进行“Reset CPU”操作后重新装载再下载并运行。
(3)除了操作问题外,编写程序时也遇到了一些问题。在设计实验三的程序时,在中断函数中加入了for循环,导致程序下载后运行出现问题,在助教老师的指导讲解下明白了在中断函数中不应加入循环,原因是中断函数本身就是循环。
订 线