2013-09-24 2 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 = 0을 전달해야합니다. 필수 임베디드 헤더 파일에서 PINB4 및 PINB의 크기와 유형을 다시 확인하고 일치하는지 확인하십시오. – DanielV

+0

죄송합니다. 아마도 BUTTONS_ID_1 = 0이라고 가정해야합니다. – DanielV

+0

'PINB4'가 0 ~ 31 범위를 벗어난 것으로 의심됩니다. 그렇다면'1 << PINB4'는 원하는 것이 아닙니다. – chux

답변

0

:

당신은 이런 식으로 코딩 할 수있다. 나는 오른쪽 헤더 파일에 대한 참조가있는 것처럼 보이는 파워 포인트 프리젠 테이션에 this link을 발견했습니다.

주목할만한 파일은 다음과 같습니다 iom328p.h

모든 정보는 PINB가있는에 자신의 포인터를 정의 할 필요가 sfr_defs.h

    1. . 포트 포인터입니다

      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 :

      것은 당신이 어떤 정확한 유형을 찾는 단계를 건너 뛸 수 있습니다 (나는 그것을 AVR하지만 내가 잘못 될 수 있기 때문에 당신이없는 생각) GCC를 사용하는 경우 PINB이며, 다음과 같이 구조체를 선언 : 당신이 그것을 사용하지 못할 수도 있으므로

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

      typeof operator은 C 언어에 GCC 확장이지만 그것에 대해 알고하는 것이 좋다.

  • +0

    typeof 연산자가 잘 작동하도록 avr-gcc를 사용하고 있습니다. –

    1

    PINB은 휘발성인가요? 포트를 실제로 읽지 않습니까? 그렇다면 Button_init에있는 포트 값을 Button_instantRead이 아닌 값으로 읽습니다.

    다른 말로, button[id]->port에는 나중에 사용할 수있는 PINB에 대한 참조가 아닌 Button_init에서 읽을 때 포트의 값이 포함됩니다.

    주의 : atmega 항목을 작성한 지 수년이되었습니다. 내가 처음 PINB의 정의를 찾는 것이 좋습니다

    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

    분명히 깔끔한 해결 방법이지만 여전히 button.port에 PINB를 할당 할 수 있도록하려면 어떻게해야하는지 알고 싶습니다. 내 입력 포트의 상태에 따라 true 또는 false를 반환 할 수 있습니다. –

    +0

    찾기 #define for PINB. 헤더 파일 중 하나에 있습니다. 과제의 오른쪽에 PINB가 있으면 포트를 읽습니다. 따라서 '나중에 읽을 수 있습니다'또는 일부 관련 개념으로 지정할 수 없습니다. 포트를 읽을 때 PINB를 참조해야합니다. –

    +0

    @CharlieBurns 그러나 'PINB'에 대한 포인터를 사용하여 'PINB'자체를 읽고 여분의 switch 문을 피할 수 있습니다. – nonsensickle

    관련 문제