Ron Kreymborg wrote:
-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On
Behalf Of David Brown
Sent: Monday, 29 October 2007 7:25 PM
To: avr-chat@nongnu.org
Subject: Re: [avr-chat] Array access to ports
Ron Kreymborg wrote:
I am addressing a dozen or so LEDs on a number of different ports,
turning them on and off. I would like to address them
through an array
structure that stores the relevant port and mask. For example:
typedef enum
{
T_LED_OFF,
T_LED_ON
} LED_STATE_TYPE;
typedef struct
{
MYPORT port;
uint8 mask;
} LED_TYPE;
I could designate the respective LEDs with names. For example:
typedef enum
{
LEDOUT,
etc
} LED;
I had hoped to be able to preload the array something like:
static LED_TYPE LedList[] = {
{PORTB, 0x20}, // LEDOUT
{etc}
};
Where the 0x20 is the mask for pin5 of PORTB for the LEDOUT led. I
could then use a simple function to address all leds. For example,
turning the LEDOUT led on (high) would look like:
ChangeLedState(LEDOUT, T_LED_ON);
And the partial function:
void ChangeLedState(LED index, LED_STATE_TYPE state)
{
if (state == T_LED_ON)
LedList[index].port |= LedList[index].mask;
.
.
The snag of course is that PORTB is not a constant but an SFR. Can
anyone suggest whether assigning a port like this is possible, and
what would be the definition of MYPORT?
Cheers
Ron
You can't store an array of SFR's like this - but you can
store an array
of pointers to them:
typedef volatile uint8_t vuint8_t;
typedef vuint8_t pvuint8_t;
typedef struct { pvuint8_t pPort; uint8_t mask; } ledType;
static ledType ledList[] = { { &PORTB, 0x20 }, { &PORTC, 0x10 } };
Then you can write:
*(ledList[index].pPort) |= ledList[index].mask;
-----------------------------------------------------------------
Thanks for the clue David. In fact it is even simpler than that:
typedef struct {uint8* pPort; uint8 mask;} LedType;
pPort should be a pointer to a volatile uint8. I like to build up types
with several typedefs, as that makes it clearer and less error prone
when using complicated types, but you want:
typedef struct {volatile uint8* pPort; uint8 mask;} LedType;
Your code will probably work in exactly the same way with and without
the "volatile" - but under some circumstances, the compiler might
optimise the code and give you different results (for example, turning
an LED on then off in the same function might be omitted). The general
rule is that all hardware access is done through volatiles - don't break
that rule just to save slightly on the typing.
static LedType LedList[] = {{&PORTB, 0x20},{etc...}};
*LedList[index].pPort |= ledList[index].mask;
This uses 13 instructions (OPT=s) - overhead I can live with.
Thanks again
Ron
_______________________________________________
AVR-chat mailing list
AVR-chat@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-chat