Die Addition stört nicht weiter, das Ergebnis ist ja zur Compilezeit bekannt. Oder willst du eine Bibliothek mit zulinkbaren Modulen machen, die nur dazugebunden werden sollen? Dann geht es natürlich nicht über Makros.

Bei deinem Beispiel müssen PINM1A und PINM1E auf dem gleichen Port liegen, voll flexibel bist du da immer noch nicht.

Ausserdem musst du nicht nur den Port kennen (PORTX-Register) sondern auch Direction-Register (DDRX) und evtl Port Input Register (PINX). Die liegen nicht bei allen AVRs nebeneinander im Adressraum.

Werte werden auch nicht in einem Makro "abgelegt". Ein Makro macht nichts weiter als reinen Textersatz zur Compilezeit.

Falls du Makros willst wie SET(PORTB_1), CLR(PORTB_1) oder MAKE_OUTPUT(PORTB_1) geht das zwar, aber die Makros werden recht unübersichtlich, weil im MAKE_OUTPUT() das DDR angefasst werden muss und im SET() das PORT-Register und mit CLR() noch eine Maskenoperation hinzukommt. Der Compiler macht zwar den optimalen Code, weil er nur Konstanten zu falten hat, aber einen Fehler aus so verschlungenen Makros rausfischen ist keine Freude.