문제

I am having a bit of a problem with struct and defines from an atmega328p.

I have the following code:

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);
}

I want to use my Button_instantRead() to be able to read any port by only giving it an ID number. I use my init function to set which pin is associated to which port. But for some reason when I call my Button_instantRead() function I do not get a 1 even when I press on my switch.

I tried my configuration in my main file using the commented line and everything works perfectly fine.

What am I doing wrong in my return line?

After some Googling I found that char is probably not the right type to reference a port. I think I would be better suited with a pointer to the first element of the address of the port, but again I don't know how to do it and could not find the answer either.

도움이 되었습니까?

해결책

I would recommend looking up the definition of PINB first. I've found this link to a power point presentation that seems to have a reference to the right header files.

Noteworthy files are:

  1. sfr_defs.h
  2. iom328p.h

where all the information you need to define your own pointers to PINB resides.

The following should work as you want it to:

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);
}

Note that the port is a pointer.

Edit:

I had to check myself for volatile struct member use and found this SO question and this other SO question quite interesting.

Edit 2:

If you are using gcc (which I think you are not since it is AVR but I could be wrong) you can skip the step of finding out what the exact type of PINB is and declare your struct as follows:

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

The typeof operator is a gcc extension to the C language so you might not be able to use it but it is good to know about it.

다른 팁

Is PINB volatile? Isn't that the actual read of the port? If so, you read the value of the port in Button_init not in Button_instantRead.

In other words, button[id]->port contains the value of the port when you read it in Button_init, not some reference to PINB that can be used later.

Beware: It's been years since I've done atmega stuff.

You could recode it this way:

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
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top