为了对一个外设进行编程,通常我们只需要对其控制寄存器(一般为xxxcon这样的命名)的整体或者相应的位进行编程。更为直接的方式是,直接把一个十六进制的数值写到外设所对应的存储器地址;但是在多次操作并且写不同控制值的时候,这样的写方式显然是重复度很高但是低效率的。在DSP2833x的编程中,为了使我们的源程序更加简介、模块化,往往把一些寄存器的描述、全局变量、结构体、一些模块化定义的参数放在头文件中,并且在多个源程序中都可以进行引用,极大地方便我们的编程与程序的修改调试。DSP2833x C代码的头文件是C函数、宏、外设的结构及变量定义等,这一套文件被称为“头文件”。在这种方式下,寄存器和它们的位用结构体和共用体来进行预定义,并使用C代码写的函数和宏进行结构体的初始化,本质上即对寄存器的相应位进行操作。 下面先举例子看看传统方式与新方法的对比:
传统的寄存器操作方法:
#define ADCTRL1 (volatile unsigned int*)0x00007100
#define ADCTRL2 (volatile unsigned int*)0x00007101
... void main(void)
{
*ADCTRL1 = 0x1234;//write entire register *ADCTRL2 |= 0x4000;//reset sequencer #1 }
在以前的DSP编程中,比如在TMS320LF2407A那一代的芯片编程中,一般都使用这样的方法。这种方法是有一定的优点的,比如:
- 代码比较简洁,输入起来也比较简单;
- 变量的名字就是寄存器的名字,方便了从datasheet上面查找相应的信息,更容易理解代码的含义,同时**起来也比较方便;
其不足之处在于:
- 需要使用单独的掩码来分别操作独立的位,比如上面代码的“*ADCTRL2 |= 0x4000”这一句,为了只操作寄存器的第14位,而不对其余的位产生影响,需要使用|=这样麻烦的操作,而且一不小心写错位的话就会产生错误的结果;
- 在调试时,无法很方便的直接在watch window里面输入寄存器名字后就直接读出相应位的值;
- 代码的效率不够高,比如在需要对ADCTRL2的多个位分别进行操作的时候,需要写很多行*ADCTRL2 |=*****这样的代码。
|