... Wenn der Microcontroller 2 Zyklen mehr braucht stört mich das nicht, da er dann noch fix genug ist ...
Stimmt, im Prinzip. Und ich habe (fast) immer viel Reserve im Zielcontroller, weil Codes die Neigung haben, mit dem Alter des Projektes umfangreicher zu werden.

... Aber, ich finde eine Kapselung generell besser lesbar und wartbarer ...
Erstmal - ich fühle mich immer noch als C-Anfänger, zumindest nicht als Könner. Deine Lösung finde ich pfiffig, ein bisschen sophisticated aber für mich nicht wirklich besser lesbar - und damit auch nicht besser pflegbar. Meine Lösung ist recht konventionell (denke ich) und gut lesbar - weil die #define´s schon recht praktisch sind.

Aber es ist ja DEIN Projekt - und jeder löst ne Aufgabe nach seinem Geschmack (und Können natürlich). Und strukts sind für mich eben nicht die erste Wahl.

Mein Beispiel, weder als Vorbild noch unbedingt zum Lesen gedacht.
Code:
// Auszug aus ~com~.h
// ==================
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                //
  #define SetBit(ADDR,BIT)       ((ADDR)  |=  (1<<(BIT)))       // Setzt Bit
  #define ClrBit(ADDR,BIT)       ((ADDR)  &= ~(1<<(BIT)))       // Löscht Bit
  #define ToggleBit(ADDR,BIT)    ((ADDR)  ^=  (1<<(BIT)))       // Toogelt Bit
// - - - - - - - - - - - - - - - -
  #define       PrtLED  PORTD   // Port für gn+rt-LED Tim_rh (Timerrhythmus)
  #define       L1g         4   // Auf PD4 grüne LED
  #define       L1r         5   // Auf PD5 rote  LED
                        // ##>>> (Heartbeat)LEDs schalten Aode -<|- Portpin <<<##
  #define       FlgLED      2   // LED - Schaltflag, aktuell nur Heartbeat = on
                        //      1=> Heartbeat, 
                        //      2=> Togglebeat rtLED in ISR (TIMER1_COMPA_vect)
// Ende Auszug aus ~com~.h
// =======================
// - - - - - - - - - - - - - - - -
// Auszug aus ~main~.c
// ===================
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// . . .
//              ===================================================
// ####>>>>     Initialisierung der Anschlüsse für R5M auf mega1284: <<<<####
//           (           PB0   1 A   A  40  PA0         (CN 11 -Audi)
// CN_12     (           PB1   2 A   A  39  PA1         (CN 11 -Audi)
// PORTB     (           PB2   3 A   A  38  PA2         (CN 11 -Audi)
// (CIR od.  /           PB3   4 A   A  37  PA3         (CN 11 -Audi)
//  LCD ...  \           PB4   5 A   A  36  PA4, Servo10
//  siehe    (     MOSI, PB5   6 A   A  35  PA5, Servo9
//  unten    (     MISO, PB6   7 A   A  34  PA6, Servo8
//           (      SCK, PB7   8 A   A  33  PA7, Servo7
//  Taste /RES,       /RESET   9        32  AREF ref Vcc, aktuell
//                       Vcc  10        31  GND                        
//                       GND  11        30  AVcc                       
//                     XTAL2  12     A  29  PC7, Servo6
//                     XTAL1  13     A  28  PC6, Servo5
//           RXD0,       PD0  14 EU  A  27  PC5, Servo4
//           TXD0,       PD1  15 EU  A  26  PC4, Servo3
//           RXD1,       PD2  16 EU  A  25  PC3, Servo2
//           TXD1,       PD3  17 A   A  24  PC2, Servo1
//           L1g         PD4  18 A   E  23  PC1, SDA   
//           L1r         PD5  19 A   E  22  PC0, SCL   
//             TasteA_1, PD6  20 EU  EU 21  PD7, TasteB_2, PCINT31, (Sound)
// - - - - - - - - - - - - - - -
// Ports+Pins als Ein- (0) oder Ausgänge (1) konfigurieren, Pull Ups (1) aktivieren
//      A = Ausgang, E = Eingang ohne , EU = Eingang MIT PullUp
  DDRA  = 0b11111111;   // siehe aktuell oben
  PORTA = 0b00000000;   //    und Port/Pull Ups (1)  aktivieren
                        //
  DDRB  = 0b01111111;   // siehe aktuell oben
  PORTB = 0b10000000;   //    und Port/Pull Ups (1)  aktivieren
                        //
  DDRC  = 0b11111100;   // PC0..7 (mega1284), I2C = PC0 + PC1
  PORTC = 0b00000000;   // bis auf I2C : Alle OHNE Pullup !!
                        // 
  DDRD  = 0b00111100;   // -> siehe Schaltplan m-32-plus
  PORTD = 0b11000011;   //    Pull Ups aktivieren, NICHT bei extINT0/~1
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// . . . und unmittelbar nach diesen ersten, wirksamen Codezeilen eine
//        Kontrollsequenz um . . . steht dabei:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  for(i=0; i<10; i++)   // grüneLED1 blinken lassen bevor Interrupts erlaubt sind,
  {                     //   um ungewollte Resets u.ä. besser erkennen zu können
    SetBit(PORTD, L1g); // gnLED/PD4 schalten EIN, HELL
    wms(3);             // Millisekundenwait
    ClrBit(PORTD, L1g); // gnLED/PD4 aus
    wms(97);            //
// Nur zur Erläuterung in diesem Posting:
// Der besseren Auffälligkeit halber wurde die alternierend flackernde rote LED zugefügt.
    SetBit(PORTD, L1r); // rtLED/PD5 schalten EIN, HELL
    wms(3);             // 
    ClrBit(PORTD, L1r); // rtLED/PD5 aus WENN T1 nicht gedrückt
    wms(97);            //
  }             // Ende von for(i=0; i<10; i++)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
// Ende Auszug aus ~main~.h
// ========================