Reputation: 89
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.
Upvotes: 2
Views: 2393
Reputation: 4528
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:
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.
Upvotes: 2
Reputation: 7044
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
}
}
Upvotes: 1