1、F2812 中有大量的外设寄存器, 在具体的应用中,要把这些寄存器根据实际需要进行配置。这也是程序在初始化期间需要做的主要工作,在配置完成后,才可以进入正常的流程,即业务逻辑处理阶段。以我的应用为例,F2812 主要完成下列工作:2 路 A/D 采样,2 路PWM 输出,6 路 GPIO 输出。在此基础上,我将进行运算处理,实现主要功能。 传统的寄存器访问方式,通过 Macro 定义实现。在 TI 提供的头文件中,提供了一种新的方式:bit field 和 struct 方式,即位域加结构的方式。在这种方式中,定义 struct 来表示与某个外设相关的一组寄存器,然后由 Linker 程序负责
2、将寄存器映射到内存中。如对于定时器寄存器,定义: struct CPUTIMER_REGS Uint32 TIM; / Timer counter register Uint32 PRD; / Period register Uint16 TCR; / Timer control register Uint16 rsvd1; / reserved Uint16 TPR; / Timer pre-scale low Uint16 TPRH; / Timer pre-scale high ; 这样,如果 DSP 内有多个定时器,则可以通过声明多个变量实现对三个定时器寄存器的访问,便于代码复用。 利
3、用编译器的 DATA_SECTION #pragma,为每个变量分配一个数据段。然后,通过在 cmd文件,Linker 将每个数据段映射为内存中与该外设寄存器相对应的内存地址。 这时,还不能实现对寄存器,如 TIM 中的每一位的访问。需要对每个寄存器,为其定义位域,使每一位都可以访问,如定义 TCR 的位域: struct TCR_BITS / bits description Uint16 rsvd1:4; / 3:0 reserved Uint16 TSS:1; / 4 Timer Start/Stop Uint16 TRB:1; / 5 Timer reload Uint16 rsvd2
4、:4; / 9:6 reserved Uint16 SOFT:1; / 10 Emulation modes Uint16 FREE:1; / 11 Uint16 rsvd3:2; / 12:13 reserved Uint16 TIE:1; / 14 Output enable Uint16 TIF:1; / 15 Interrupt flag ; 然后,定义一个 Union,允许该寄存器既可以按 bit 访问,也可以作为整体访问: union TCR_REG Uint16 all; struct TCR_BITS bit; ; 在如此这样对每个寄存器都定义好后,重写 struct CPUT
5、IMER_REGS 如下: struct CPUTIMER_REGS union TIM_GROUP TIM; / Timer counter register union PRD_GROUP PRD; / Period register union TCR_REG TCR; / Timer control register Uint16 rsvd1; / reserved union TPR_REG TPR; / Timer pre-scale low union TPRH_REG TPRH; / Timer pre-scale high ; 这时,每个寄存器都可以按 bit 或作为整体访问了。 这样的方式,对于程序员来说,更容易理解,程序也更容易维护。 这样做的坏处:产生的代码长度稍大一些。 另外,对于有些特殊的寄存器,如 WDCR,就没有定义 Bit field 和 Union。 上面讲了这么多,那么我们是否需要将这些寄存器全部自己定义呢?答案是不需要。因为TI 公司已经为我们提供了现成的.H 文件,为我们做好了这些工作。在编程时,我们只需要搞清楚需要把那个头文件包含进来就行了。