Skip to main content
2 of 3
Improved code.
C. K.
  • 530
  • 1
  • 5
  • 18

How to access GPIO pins on Atmega with memory mapping?

I'm programming the Atmega328P in embedded C. I'm going to use 16 pins for turning on LEDs, and I have to use PORTB, PORTD and PORTC for this. I would like to just iterate a pointer so I can turn them on/off instead having to deal with what port each pin relates to. So an example would be how I need three if statements to iterate through the 16 pins like shown below:

// Enable outputs
DDRB = 0b00111111; // 6 outputs
DDRC = 0b00110000; // 2 outputs
DDRD = 0xFF;       // 8 outputs

// LED pins
uint8_t ledpin[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
uint8_t idx = 0;

// Set LEDs
if (idx < 8)
    for(int i = 0; i < 8; i++)
        PORTD |= (1 << ledpin[i]);

if( idx > 8 && idx < 14)
    for(int i = 8; i < 14 ; i++)
        PORTB |= (1 << ledpin[i]);

if (idx >= 14)
    for(int i = 14; i < 16; i++)
        PORTC |= (1 << ledpin[i]);

I would rather use a memory map where I could just say "pin0 address + offset" like this:

// Base address of ports
uint8_t base 0x00
uint8_t offset = 0x04;

// LED pins
uint8_t ledpin[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

// Set LEDs
for(int i = 0; i < 16; i++){
    (base + offset) |= (1 << ledpin[i]); // Pseudo code
     offset += 0x04;
}

The code above is obviously not optimized, nor totally functioning code but I think it gets my point accross as to what I want to achieve. Ultimately I will use this in a code to control a LED cube which will work quite differently, but it's essential that I don't need to decode what port each pin belong to all the time. Is there a good way to solve this with virtually no overhead?

C. K.
  • 530
  • 1
  • 5
  • 18