2013-09-24 81 views
1

我遇到了一點結構問題,並從atmega328p定義。如何定義一個指向端口地址的指針

我有以下代碼:

typedef struct { 
    char port; 
    unsigned char pin; 
    unsigned long timestamp; 
} BUTTONS; 

BUTTONS button_1; 
BUTTONS button_2; 
BUTTONS button_3; 

BUTTONS* button[BUTTONS_ID_COUNT] = {&button_1,&button_2,&button_3}; 

void Button_init(void){ 

    button[BUTTONS_ID_1]->port = PINB; 
    button[BUTTONS_ID_1]->pin = PINB4; 
    button[BUTTONS_ID_1]->timestamp = 0; 
} 

unsigned char Button_instantRead(int id){ 
    //return PINB & (1 << PINB4); 
    return button[id]->port & (1 << button[id]->pin); 
} 

我想用我的Button_instantRead()能夠通過只給它一個ID號來讀取任何端口。我使用我的init函數來設置哪個引腳與哪個端口關聯。但由於某種原因,當我打電話給我的Button_instantRead()功能時,即使按下我的開關,也不會收到1。

我在我的主文件中使用註釋行嘗試了我的配置,一切正常。

我在return行中做錯了什麼?

一些谷歌搜索後,我發現char可能不是引用端口的正確類型。我想我會更適合指向端口地址的第一個元素的指針,但我不知道該如何去做,也找不到答案。

+0

猜測:確保讀取引腳,您傳遞ID = 0,而不是ID = 1。仔細檢查您的強制性嵌入式頭文件中的PINB4和PINB的大小和類型,確保它們匹配。 – DanielV

+0

糟糕,我應該說假設BUTTONS_ID_1 = 0這可能是。 – DanielV

+0

懷疑'PINB4'在0到31之間。如果是這樣,'1 << PINB4'不是你想要的。 – chux

回答

0

我會建議仰視的PINB第一定義。我發現this link到一個功能點的演示文稿,似乎有正確的頭文件的參考。

值得注意的文件是:

  1. sfr_defs.h
  2. iom328p.h

,你需要PINB駐留定義自己的指針的所有信息。

以下應該工作,你希望它:

typedef struct { 
    volatile uint8_t * port; 
    uint8_t pin; 
    unsigned long timestamp; 
} BUTTONS; 

BUTTONS button_1; 
BUTTONS button_2; 
BUTTONS button_3; 

BUTTONS* button[BUTTONS_ID_COUNT] = {&button_1,&button_2,&button_3}; 

void Button_init(void){ 
    button[BUTTONS_ID_1]->port = &PINB; 
    button[BUTTONS_ID_1]->pin = PINB4; 
    button[BUTTONS_ID_1]->timestamp = 0; 
} 

unsigned char Button_instantRead(int id){ 
    //return PINB & (1 << PINB4); 
    return *(button[id]->port) & (1 << button[id]->pin); 
} 

注意,端口是一個指針。

編輯:

我不得不檢查自己的volatile結構成員使用,發現this SO questionthis other SO question相當有趣。

編輯2:

如果你正在使用GCC(我想你是不是因爲它是AVR但我可能是錯的),你可以跳過發現什麼的確切類型的步驟PINB是並宣佈你的結構如下:

typedef struct { 
    typeof(PINB)* port; 
    uint8_t pin; 
    unsigned long timestamp; 
}; 

typeof operatorGCC延伸到C語言,所以你可能無法使用它,但它是很好的瞭解它。

+0

我正在使用avr-gcc,所以typeof運算符應該工作得很好。 –

1

PINB易失性?這不是港口的實際讀取嗎?如果是這樣,您可以讀取Button_init中的端口值,而不是Button_instantRead

換句話說,button[id]->port包含您在Button_init中讀取端口時的端口值,而不是稍後可以使用的某些PINB引用。

請注意:我已經完成了atmega的工作多年。

你可以重新編寫這樣說:

unsigned char Button_instantRead(int id){ 
    switch(id) { 
     case ID_A: return PINA & (1 << button[id]->pin); 
     case ID_B: return PINB & (1 << button[id]->pin); 
     // etc 
    } 
} 
+0

這顯然是一個整潔的解決方法,但我仍然想知道我需要做什麼,以便我可以將PINB分配給我的button.port,並且能夠根據我的輸入端口的狀態返回true或false –

+0

Find PINB的#define。它在一個頭文件中。當您在任務的右側有PINB時,它會讀取端口。因此,您不能將其分配爲「稍後閱讀」或某些相關概念。當你想讀取端口時,你需要引用PINB。 –

+0

@CharlieBurns但是你總是可以使用'PINB'指針來讀取'PINB'本身並避免額外的switch語句。 – nonsensickle

相關問題