avr-chat
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-chat] Array access to ports


From: David Brown
Subject: Re: [avr-chat] Array access to ports
Date: Tue, 30 Oct 2007 12:54:05 +0100
User-agent: Thunderbird 2.0.0.6 (Windows/20070728)

Ron Kreymborg wrote:

-----Original Message-----
From: address@hidden [mailto:address@hidden On Behalf Of David Brown
Sent: Monday, 29 October 2007 7:25 PM
To: address@hidden
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






reply via email to

[Prev in Thread] Current Thread [Next in Thread]