汇编将寄存器赋值变量_用C语言对DSP的寄存器进行操作?

欢迎FPGA工程师加入官方微信技术群

22d94baa95b32ed0ae739f5cebf887d3.png

在嵌入式软件的开发过程中,我们常用的语言主要是:汇编语言和C语言。相比较于汇编语言,C语言对我们来说,更贴近我们的一些语言习惯。在DSP的开发过程中,我们主要还是用C语言,其中最最常用的操作就是对于DSP各个寄存器的控制了。

那么如何用C语言对DSP的寄存器进行操作呢?

我们先来说书单片机里面是如何操作的:一般寄存器在单片机头文件中的宏定义都有如下的形式:

#define TIFR  *((volatile unsigned char *)0x58)     /*ATmega16的TIFR寄存器*/

在ATmega16中TIFR寄存器的地址是0x0058,我们要实现:

TIFR = 0x01

这条,就是要把0x58这个地址的内容修改成0x01。而在C语言中,指针就是地址。现在要告诉编译器0x58是地址,就要把0x58强制转换成指针(unsigned char *)0x58。这样(unsigned char *)0x58就表示TIFR在ATmega16 中的地址了,而*((unsigned char *)0x58)表示这个地址的内容。

然后如果想对寄存器TIFR单个的位进行下面的操作,

(1)将寄存器TIFR的第1位置“1”

TIFR |= (1 << 1);

(2) 将寄存器REG的第3位清零

TIFR &= ~(1 << 3);

(3) 将寄存器REG的第3、5位置“1”

TIFR |= (1 << 5) | (1 << 3);

(4) 将寄存器REG的第3、5位清零

TIFR &= ~( (1 << 5) | (1 << 3) );

在单片机里面是使用宏定义的方式来对寄存器进行操作。而在DSP里面,是使用位定义+共同体的方式来定义和操作寄存器。如下:

// ECCTL1控制寄存器的位定义如下:
struct ECCTL1_BITS {          // bits   description
Uint16 CAP1POL:1; // 0 Capture Event 1 Polarity select
Uint16 CTRRST1:1; // 1 Counter Reset on Capture Event 1
Uint16 CAP2POL:1; // 2 Capture Event 2 Polarity select
Uint16 CTRRST2:1; // 3 Counter Reset on Capture Event 2
Uint16 CAP3POL:1; // 4 Capture Event 3 Polarity select
Uint16 CTRRST3:1; // 5 Counter Reset on Capture Event 3
Uint16 CAP4POL:1; // 6 Capture Event 4 Polarity select
Uint16 CTRRST4:1; // 7 Counter Reset on Capture Event 4
Uint16 CAPLDEN:1; // 8 Enable Loading CAP1-4 regs on a Cap Event
Uint16 PRESCALE:5; // 13:9 Event Filter prescale select
Uint16 FREE_SOFT:2; // 15:14 Emulation mode
};


struct ECCTL1_BITS  bit;

在上面的代码中我们用位域的方式表示了 TCR寄存器的数据结构。同时声明了一个

struct TCR_BITS类型的变量bit,那么我们就可以通过bit对寄存器每个位进行控制,比如

bit.CTRRST2=0;

此时有一个问题,就是如果我们想对整个寄存器进行整体的控制该如何呢?我们通过定义共同体来实现既可以对寄存器的每个位进行控制,又能对寄存器整体方便的控制。如下:

union ECCTL1_REG {
Uint16 all;
struct ECCTL1_BITS bit;
};
TCR_REG.all=0xxxx;    //对寄存器整体操作
TCR_REG.CTRRST2=0; //对寄存器单个位操作

而在DSP里面,某一个功能是靠一个模块来实现的,而每一个功能模块包含了许多不同的寄存器,比如28335里面CAP脉冲捕获模块的寄存器就有以下这么多:

ee387024426ef642cc78bf3729deb85b.png

为了方便统一管理和编程开发方便,TI公司将ECap模块的所有寄存器定义成一个结构体ECAP_REGS,如下:

struct ECAP_REGS {
Uint32 TSCTR; // Time stamp counter
Uint32 CTRPHS; // Counter phase
Uint32 CAP1; // Capture 1
Uint32 CAP2; // Capture 2
Uint32 CAP3; // Capture 3
Uint32 CAP4; // Capture 4
Uint16 rsvd1[8]; // reserved
union ECCTL1_REG ECCTL1; // Capture Control Reg 1
union ECCTL2_REG ECCTL2; // Capture Control Reg 2
union ECEINT_REG ECEINT; // ECAP interrupt enable
union ECFLG_REG ECFLG; // ECAP interrupt flags
union ECFLG_REG ECCLR; // ECAP interrupt clear
union ECEINT_REG ECFRC; // ECAP interrupt force
Uint16 rsvd2[6]; // reserved

};

我们可以看到,在结构体ECAP_REGS中有的成员是 Uint32形式,有的是union形式,其中定义为union形式的成员既可以对寄存器整体操作,又可以对寄存器进行位操作,而定义为Uint16 的成员只能进行位操作。

在定义了ECAP_REGS结构体之后,需要声明ECAP_REGS类型的变量,而28335有6路的ECap,所以声明如下:

extern volatile struct ECAP_REGS ECap1Regs;
extern volatile struct ECAP_REGS ECap2Regs;
extern volatile struct ECAP_REGS ECap3Regs;
extern volatile struct ECAP_REGS ECap4Regs;
extern volatile struct ECAP_REGS ECap5Regs;
extern volatile struct ECAP_REGS ECap6Regs;

其中extern表示声明的是一个全局变量,关键字volatile代表寄存器的值可以被外部代码任意改变,比如被中断改变。

volatile 在 DSP 中的理解:该单词的意思是可变的,易变的。在 DSP 中一些寄存器的值的变化有两种情况:

(1)硬件上导致的变化,例如中断、ADC 等

(2)软件上的变化,例如对某个变量赋值等。
当加入了关键字 volatile,对软件来说,硬件上变化的值是不可预知的,提示编译器每次读取该变量时,都要直接读取该变量地址中的寄存器,保证了数据的正确性。 

以上我们回顾一下:经过位定义——共同体——结构体的过程就是TI公司提供给我们的DSP2833x_ECap.h里面的内容。

而28335的寄存器结构是固定不变的,所以这个头文件我们在项目的开发中就可以直接拿来用了,添加到include中即可。

此外,大家也不必去死记各种各样的寄存器,因为CCS软件有“感应”功能。在我们加载了头文件之后,输入寄存器名字之后,输入 “.”就会弹出可选的下拉列表来选择你需要的寄存器。

ECap1Regs.ECCTL1_REG.bit.CAP2POL=0xxxxx;

上面一行代码从右至左依次代表:

功能模块结构体——某一个寄存器——寄存器的某一位;

这样我们就可以在自己的.c源文件中对各种各样的寄存器进行配置和操作,来实现自己的开发目的。

9878fab4006984a8998c15c4d60381e3.png

欢迎通信工程师和FPGA工程师关注公众号

9dd4477fe7a492e69f3c01018092fa05.png

FPGA微信技术群

欢迎大家加入全国FPGA微信技术群,这里有一群热爱技术的工程师,在这里可以一起交流讨论技术!

402d3a8d73df3fbb903d44e2a664559d.png

用手指按住就可以加入FPGA全国技术群哦

FPGA IP核服务:各类优质IP核服务商,服务到位,有保障!有需求的可以直接联系群主!

FPGA技术群平台自营:Xilinx Altera 镁光、三星、海力士、ADI TI ST NXP 等品牌的优势代理分销商,欢迎大家有需求随时发型号清单,我们将在第一时间为您提供最优竞争力的报价!价格低于您原有供应商5%以上!欢迎询价-直接把需求发给群主!

FPGA技术群官方鸣谢品牌:Xilinx、 intel(Altera)、microsemi(,Actel)、LattIC e,Vantis,Quicklogic,Lucent等

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值