小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

用C語言對DSP的寄存器進行操作?

 goandlove 2019-08-09

在嵌入式軟件的開發(fā)過程中,我們常用的語言主要是:匯編語言和C語言。相比較于匯編語言,C語言對我們來說,更貼近我們的一些語言習(xí)慣。在DSP的開發(fā)過程中,我們主要還是用C語言,其中最最常用的操作就是對于DSP各個寄存器的控制了。

那么如何用C語言對DSP的寄存器進行操作呢?

我們先來說書單片機里面是如何操作的:一般寄存器在單片機頭文件中的宏定義都有如下的形式:

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

在ATmega16中TIFR寄存器的地址是0x0058,我們要實現(xiàn):

TIFR = 0x01

這條,就是要把0x58這個地址的內(nèi)容修改成0x01。而在C語言中,指針就是地址。現(xiàn)在要告訴編譯器0x58是地址,就要把0x58強制轉(zhuǎn)換成指針(unsigned char *)0x58。這樣(unsigned char *)0x58就表示TIFR在ATmega16 中的地址了,而*((unsigned char *)0x58)表示這個地址的內(nèi)容。

然后如果想對寄存器TIFR單個的位進行下面的操作,

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

TIFR |= (1 <>

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

TIFR &= ~(1 <>

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

TIFR |= (1 < 5)="" |="" (1=""><>

(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寄存器的數(shù)據(jù)結(jié)構(gòu)。同時聲明了一個

struct TCR_BITS類型的變量bit,那么我們就可以通過bit對寄存器每個位進行控制,比如

bit.CTRRST2=0;

此時有一個問題,就是如果我們想對整個寄存器進行整體的控制該如何呢?我們通過定義共同體來實現(xiàn)既可以對寄存器的每個位進行控制,又能對寄存器整體方便的控制。如下:

union ECCTL1_REG {
Uint16 all;
struct ECCTL1_BITS bit;
};
TCR_REG.all=0xxxx;    //對寄存器整體操作
TCR_REG.CTRRST2=0; //對寄存器單個位操作

而在DSP里面,某一個功能是靠一個模塊來實現(xiàn)的,而每一個功能模塊包含了許多不同的寄存器,比如28335里面CAP脈沖捕獲模塊的寄存器就有以下這么多:

為了方便統(tǒng)一管理和編程開發(fā)方便,TI公司將ECap模塊的所有寄存器定義成一個結(jié)構(gòu)體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

};

我們可以看到,在結(jié)構(gòu)體ECAP_REGS中有的成員是 Uint32形式,有的是union形式,其中定義為union形式的成員既可以對寄存器整體操作,又可以對寄存器進行位操作,而定義為Uint16 的成員只能進行位操作。

定義了ECAP_REGS結(jié)構(gòu)體之后,需要聲明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表示聲明的是一個全局變量,關(guān)鍵字volatile代表寄存器的值可以被外部代碼任意改變,比如被中斷改變。

volatile 在 DSP 中的理解:該單詞的意思是可變的,易變的。在 DSP 中一些寄存器的值的變化有兩種情況:

(1)硬件上導(dǎo)致的變化,例如中斷、ADC 等

(2)軟件上的變化,例如對某個變量賦值等。
當(dāng)加入了關(guān)鍵字 volatile,對軟件來說,硬件上變化的值是不可預(yù)知的,提示編譯器每次讀取該變量時,都要直接讀取該變量地址中的寄存器,保證了數(shù)據(jù)的正確性。?

以上我們回顧一下:經(jīng)過位定義——共同體——結(jié)構(gòu)體的過程就是TI公司提供給我們的DSP2833x_ECap.h里面的內(nèi)容。

而28335的寄存器結(jié)構(gòu)是固定不變的,所以這個頭文件我們在項目的開發(fā)中就可以直接拿來用了,添加到include中即可。

此外,大家也不必去死記各種各樣的寄存器,因為CCS軟件有“感應(yīng)”功能。在我們加載了頭文件之后,輸入寄存器名字之后,輸入?“.”就會彈出可選的下拉列表來選擇你需要的寄存器。

ECap1Regs.ECCTL1_REG.bit.CAP2POL=0xxxxx;

上面一行代碼從右至左依次代表:

功能模塊結(jié)構(gòu)體——某一個寄存器——寄存器的某一位;

這樣我們就可以在自己的.c源文件中對各種各樣的寄存器進行配置和操作,來實現(xiàn)自己的開發(fā)目的。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多