C語(yǔ)言是一門(mén)通用計(jì)算機(jī)編程語(yǔ)言,應(yīng)用廣泛。C語(yǔ)言的設(shè)計(jì)目標(biāo)是提供一種能以簡(jiǎn)易的方式編譯、處理低級(jí)存儲(chǔ)器、產(chǎn)生少量的機(jī)器碼以及不需要任何運(yùn)行環(huán)境支持便能運(yùn)行的編程語(yǔ)言。盡管C語(yǔ)言提供了許多低級(jí)處理的功能,但仍然保持著良好跨平臺(tái)的特性。
以一個(gè)標(biāo)準(zhǔn)規(guī)格寫(xiě)出的C語(yǔ)言程序可在許多電腦平臺(tái)上進(jìn)行編譯,甚至包含一些嵌入式處理器(單片機(jī)或稱MCU)以及超級(jí)電腦等作業(yè)平臺(tái)。二十世紀(jì)八十年代,為了避免各開(kāi)發(fā)廠商用的C語(yǔ)言語(yǔ)法產(chǎn)生差異,由美國(guó)國(guó)家標(biāo)準(zhǔn)局為C語(yǔ)言訂定了一套完整的國(guó)際標(biāo)準(zhǔn)語(yǔ)法,稱為ANSI C,作為C語(yǔ)言最初的標(biāo)準(zhǔn)。
控制器(英文名稱:controller)是指按照預(yù)定順序改變主電路或控制電路的接線和改變電路中電阻值來(lái)控制電動(dòng)機(jī)的啟動(dòng)、調(diào)速、制動(dòng)和反向的主令裝置。由程序計(jì)數(shù)器、指令寄存器、指令譯碼器、時(shí)序產(chǎn)生器和操作控制器組成,它是發(fā)布命令的“決策機(jī)構(gòu)”,即完成協(xié)調(diào)和指揮整個(gè)計(jì)算機(jī)系統(tǒng)的操作。
那么C語(yǔ)言如何控制寄存器呢?接下來(lái)我們一起來(lái)了解一下。
C語(yǔ)言控制寄存器
在嵌入式軟件的開(kāi)發(fā)過(guò)程中,我們常用的語(yǔ)言主要是:匯編語(yǔ)言和C語(yǔ)言。相比較于匯編語(yǔ)言,C語(yǔ)言對(duì)我們來(lái)說(shuō),更貼近我們的一些語(yǔ)言習(xí)慣。在DSP的開(kāi)發(fā)過(guò)程中,我們主要還是用C語(yǔ)言,其中最最常用的操作就是對(duì)于DSP各個(gè)寄存器的控制了。
那么如何用C語(yǔ)言對(duì)DSP的寄存器進(jìn)行操作呢?
我們先來(lái)說(shuō)書(shū)單片機(jī)里面是如何操作的:一般寄存器在單片機(jī)頭文件中的宏定義都有如下的形式:
#define TIFR *((volatile unsigned char *)0x58) /*ATmega16的TIFR寄存器*/
在ATmega16中TIFR寄存器的地址是0x0058,我們要實(shí)現(xiàn):
TIFR = 0x01
這條,就是要把0x58這個(gè)地址的內(nèi)容修改成0x01。 而在C語(yǔ)言中,指針就是地址?,F(xiàn)在要告訴編譯器0x58是地址,就要把0x58強(qiáng)制轉(zhuǎn)換成指針(unsigned char *)0x58。 這樣(unsigned char *)0x58就表示TIFR在ATmega16 中的地址了,而*((unsigned char *)0x58)表示這個(gè)地址的內(nèi)容。
然后如果想對(duì)寄存器TIFR單個(gè)的位進(jìn)行下面的操作,
?。?)將寄存器TIFR的第1位置“1”
TIFR |= (1 《《 1);
?。?) 將寄存器REG的第3位清零
TIFR &= ~(1 《《 3);
?。?) 將寄存器REG的第3、5位置“1”
TIFR |= (1 《《 5) | (1 《《 3);
?。?) 將寄存器REG的第3、5位清零
TIFR &= ~( (1 《《 5) | (1 《《 3) );
在單片機(jī)里面是使用宏定義的方式來(lái)對(duì)寄存器進(jìn)行操作。而在DSP里面,是使用位定義+共同體的方式來(lái)定義和操作寄存器。如下:
// 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)。同時(shí)聲明了一個(gè)
struct TCR_BITS類型的變量bit,那么我們就可以通過(guò)bit對(duì)寄存器每個(gè)位進(jìn)行控制,比如
bit.CTRRST2=0;
此時(shí)有一個(gè)問(wèn)題,就是如果我們想對(duì)整個(gè)寄存器進(jìn)行整體的控制該如何呢?我們通過(guò)定義共同體來(lái)實(shí)現(xiàn)既可以對(duì)寄存器的每個(gè)位進(jìn)行控制,又能對(duì)寄存器整體方便的控制。如下:
union ECCTL1_REG {
Uint16 all;
struct ECCTL1_BITS bit;
};
TCR_REG.all=0xxxx; //對(duì)寄存器整體操作
TCR_REG.CTRRST2=0; //對(duì)寄存器單個(gè)位操作
而在DSP里面,某一個(gè)功能是靠一個(gè)模塊來(lái)實(shí)現(xiàn)的,而每一個(gè)功能模塊包含了許多不同的寄存器,比如28335里面CAP脈沖捕獲模塊的寄存器就有以下這么多:
為了方便統(tǒng)一管理和編程開(kāi)發(fā)方便,TI公司將ECap模塊的所有寄存器定義成一個(gè)結(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形式的成員既可以對(duì)寄存器整體操作,又可以對(duì)寄存器進(jìn)行位操作,而定義為Uint16 的成員只能進(jìn)行位操作。
在定義了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表示聲明的是一個(gè)全局變量,關(guān)鍵字volatile代表寄存器的值可以被外部代碼任意改變,比如被中斷改變。
volatile 在 DSP 中的理解:該單詞的意思是可變的,易變的。在 DSP 中一些寄存器的值的變化有兩種情況:
?。?)軟件上的變化,例如對(duì)某個(gè)變量賦值等。
當(dāng)加入了關(guān)鍵字 volatile,對(duì)軟件來(lái)說(shuō),硬件上變化的值是不可預(yù)知的,提示編譯器每次讀取該變量時(shí),都要直接讀取該變量地址中的寄存器,保證了數(shù)據(jù)的正確性。
以上我們回顧一下:經(jīng)過(guò)位定義——共同體——結(jié)構(gòu)體的過(guò)程就是TI公司提供給我們的DSP2833x_ECap.h里面的內(nèi)容。
而28335的寄存器結(jié)構(gòu)是固定不變的,所以這個(gè)頭文件我們?cè)陧?xiàng)目的開(kāi)發(fā)中就可以直接拿來(lái)用了,添加到include中即可。
此外,大家也不必去死記各種各樣的寄存器,因?yàn)镃CS軟件有“感應(yīng)”功能。在我們加載了頭文件之后,輸入寄存器名字之后,輸入 “?!本蜁?huì)彈出可選的下拉列表來(lái)選擇你需要的寄存器。
ECap1Regs.ECCTL1_REG.bit.CAP2POL=0xxxxx;
上面一行代碼從右至左依次代表:
功能模塊結(jié)構(gòu)體——某一個(gè)寄存器——寄存器的某一位;
這樣我們就可以在自己的.c源文件中對(duì)各種各樣的寄存器進(jìn)行配置和操作,來(lái)實(shí)現(xiàn)自己的開(kāi)發(fā)目的。
評(píng)論
查看更多