2014-10-12 42 views
2

我正在嘗試使用C在PIC24F MCU上將參考傳遞給I/O引腳作爲函數參數。對於PIC,設備頭文件提供對I/O緩衝區的訪問PIC通過特殊功能寄存器地址在C中運行

LATAbits.LATA2 = 0; // sets the pin (RA2 in this case) low. 
if (PORTAbits.RA3) { // reads the state of the pin. (RA3) 

我想要做這樣的事情:通過寄存器

int main() { 
    Configure();      // Sets up peripherals, etc. 
    WaitForHigh(PORTAbits.RA3);   // waits for pin RA3 to go hi. 
    ... 

    return 0; 
} 

void WaitForHigh(?datatype? pin_reference) { 

    while(!pin_reference);   // Stays here until the pin goes hi. 
} 

所以我在想在這裏通過什麼數據類型?當我調查這個引腳時,究竟發生了什麼?下面,我從PIC24F器件頭中複製相關部分,以防萬一。

#define PORTA PORTA 
extern volatile unsigned int PORTA __attribute__((__sfr__)); 
typedef struct tagPORTABITS { 
    unsigned RA0:1; 
    unsigned RA1:1; 
    unsigned RA2:1; 
    unsigned RA3:1; 
    unsigned RA4:1; 
    unsigned RA5:1; 
} PORTABITS; 
extern volatile PORTABITS PORTAbits __attribute__((__sfr__)); 

提前致謝!

回答

1

請注意,PORT位值是通過位域獲得的,所以,回答你的問題,你不能。位域沒有地址,所以你不能將它作爲指向函數的指針傳遞。

相反,你可以使用宏:

#define WaitForHigh(p) do{while(!(p));}while(0) 

這是事實,宏已是借鑑代碼的可讀性背上,但是,考慮到適當的小心,有些情況下,他們是最好的情況下,解。如果宏這個Q & A的最佳解決方案是有爭議的,但有一點很重要。


感謝評論者提出的改善宏觀安全性的建議。

+1

我明白了。這似乎是我提出的問題的一個簡單而好的解決方案,但更一般地評估[宏與功能](http://stackoverflow.com/questions/9104568/macro-vs-function-in-c),它似乎對某些任務使用宏存在缺點。 – 2014-10-12 09:16:00

+2

我會建議'#define WaitForHigh(p)do {while(!(p));} while(0)'既強制執行預期的'p'評估並防止代碼被意外包含在循環中, ;'被省略了。兩個*更多*原因宏需要特別的關心,並且可能是最好的避免。 – Clifford 2014-10-12 10:11:46

4

作爲使用宏的替代方法,函數可以接受PORT寄存器地址(或鎖存寄存器地址,例如在配置爲輸出的引腳情況下的LATA)以及寄存器中位的掩碼是必要的。例如:

#include<p24FV32KA301.h> // defines both PORTA and _PORTA_RA3_MASK 

void WaitForHigh(volatile unsigned int * port, pin_mask) { 

    while(!(*port & pin_mask));   // Stays here until the pin goes hi. 
} 


int main() 
{ 
    ... 
    WaitForHigh(&PORTA, _PORTA_RA3_MASK);   // waits for pin RA3 to go hi. 
    ... 

    return 0; 
} 
+1

在* main之前,你應該嚴格地使用'WaitForHigh'的原型或者定義它*。宏的一個問題是缺少數據類型檢查,但是通過省略原型,您不會檢查任何情況。如果你的編譯器支持,你也可以聲明'_inline'(它們總是這樣做);在這種情況下,它可能會和宏一樣高效。檢查生成的代碼是否很重要(甚至只是感興趣)。 – Clifford 2014-10-12 09:56:53

+1

同意,@Clifford。編輯完整性。 – 2014-10-12 10:44:25

0

您可以將預處理器處理與一個函數結合起來,以獲得您在編譯時檢查符號的過程。例如:

#define PORT_FUNC(f, p, b) f(p, b) 
#define WaitForHigh(p, b) PORT_FUNC(WaitForHighImp, &p, _ ##p## _ ##b## _MASK) 

void WaitForHighImp(volatile unsigned* p, unsigned char mask) 
{ 
    while (!(*p & m)) 
     ; 
} 

int main() 
{ 
    WaitForHigh(PORTA, RA3); 
} 

這種方法的好處是,你在網上說:「PORTA」一次,在調用的時候「RA3」一次,你要確保該位名稱存在於港口,並在位存在。