fra77x
1
Is it possible to put the names of ports in an array?
I'm looking something like:
const ??? my_ports_config[8]= { PORTB, PORTD, PORTB, PORTB, PORTD, PORTB, PORTB, PORTD };
So to do (direct register bit set):
my_ports_config[i] |= _BV(7);
Is it possible?
EDIT:
This solution worked fine (proposed by @Coding Badly)
byte volatile * const port_config[] = { &PORTD, &PORTB, &PORTB, &PORTD, &PORTB, &PORTB, &PORTB, &PORTD };
LarryD
2
What happened when you tried?
.
const byte* PortConfigs[] = { PORTB, PORTD, PORTB, PORTB, PORTD, PORTB, PORTB, PORTD };
*PortConfigs[2] = _BV(7);
I guess
fra77x
4
Great thank you very much!
Port names are actually numbers like ints. So make your array by an array of ints. Then it should work I think.
fra77x
6
@septillion answer compiles and uploads ok but does not work. I will try now @papaFred idea, i'm not really sure how to make it an integer array...
fra77x
8
I tried this and doesn't work: (I think arduino hungs)
uint8_t port_config[8] = { PORTD, PORTB, PORTB, PORTD, PORTB, PORTB, PORTB, PORTD };
also tried
int port_config[8] = { PORTD, PORTB, PORTB, PORTD, PORTB, PORTB, PORTB, PORTD };
also tried
volatile byte* port_config[8] = { PORTD, PORTB, PORTB, PORTD, PORTB, PORTB, PORTB, PORTD };
and
volatile byte* port_config[] = { PORTD, PORTB, PORTB, PORTD, PORTB, PORTB, PORTB, PORTD };
unfortunately nothing worked. Arduno seems to hung after compile.
fra77x
10
This works:
if( pulse[0] == 4095 && !oneStep[0]){ oneStep[0] = true; PORTD |= _BV(7); } else
if( oneStep[0] && !pulse[0] ){ oneStep[0] = false; PORTD &= ~(_BV(7)); }
this doesn't: (compiles and uploads ok but arduino hangs, everything stops working)
if( pulse[0] == 4095 && !oneStep[0]){ oneStep[0] = true; *port_config[0] |= _BV(7); } else
if( oneStep[0] && !pulse[0] ){ oneStep[0] = false; *port_config[0] &= ~(_BV(7)); }
fra77x
12
@Delta_G
I don't understand what you are saying. Try what without the array?
I managed to make it work by using the ternary operator:
( ( i == 0 || i == 3 || i == 7 ) ? PORTD : PORTB ) |= _BV( pins_config[i] );
Any ideas how to make it work from an array are still welcomed.
Thanks!
fra77x
14
I tried this:
volatile byte* ports_config[] = {PORTD,PORTB};
now this compiles and uploads ok but does not work:
if( pulse == 4095 && !oneStep){ oneStep = true; ( ( i == 0 || i == 3 || i == 7 ) ? PORTD : ports_config[1] ) |= BV( pins_config ); }
(only PORTD works which is directly assigned)*_
fra77x
16
You are right. I'm a bit tired now to test it right.
I tried also without the array like:
volatile byte* ports_config = PORTB;
But the compiler complained about the ternary: "needs lvalue".
I will try again tomorrow when I will be less tired.
Thanks for your help.
I don't have an AVR to try this. But, assuming an Uno, the address of PORTB is 0x25. So, this might work:
volatile uint8_t *myport = (volatile uint8_t *) 0x25;
and access it with:
*myport = *myport | _BV(7);
If this works, you can then move on to building your array. Get the addresses from the datasheet.
PORTa is essentially a reference Try this...
volatile byte* port_config[] = { &PORTD, &PORTB, &PORTB, &PORTD, &PORTB, &PORTB, &PORTB, &PORTD };
You are welcome.
For the fanatics...
byte volatile * const port_config[] = { &PORTD, &PORTB, &PORTB, &PORTD, &PORTB, &PORTB, &PORTB, &PORTD };
(Will also give the optimizer a leg up.)
fra77x
22
Thanks people. @Coding Badly solution worked fine.
Regards,
John
Lot of replies when I was out. And yes, of course a address operator was needed, I forgot :
Using an int would just be stupid... Call it what it is. And using the name is a lot easier to read (and port!) then 0x25...
I had considered the &PORTn notation, but wasn’t exactly sure how it would parse. As far as I can tell PORTB is a macro that resolves to:
*(volatile uint8_t *) 0x25
So, putting a ‘&’ in front results in:
&*(volatile uint8_t *) 0x25
I suppose you could say that the ‘&’ “cancels” the first ‘*’ leaving you with a pointer to the uint8_t stored in address 0x25.
It obviously works, but wondering if someone could explain exactly how it’s processed.