Код
template<volatile unsigned char* __io Reg>
struct Test
{
void f() { *Reg = 0; }
};
Test<&PORTA> t;
t.f();
Правда учти, что некоторые регистры - __ext_io
Еще можно специализации использовать:
Код
template<int No>
struct USART;
#define defUART(N)
template<> struct USART<N> { \
INLINE static void enableReadyToSendInt(bool v) { PUTBIT(UCSR##N##B, UDRIE##N, v); } \
INLINE static void enableReceivedInt(bool v) { PUTBIT(UCSR##N##B, RXCIE##N, v); } \
INLINE static void enableSendInt(bool v) { PUTBIT(UCSR##N##B, TXCIE##N, v); } \
INLINE static void enableSend(bool v) { PUTBIT(UCSR##N##B, TXEN##N, v); } \
INLINE static void clearSendIntFlag() { UCSR##N##A = BIT(TXC##N); } \
INLINE static byte read() { return UDR##N; } \
INLINE static void write(byte v) { UDR##N = v; } \
INLINE static void clearInputBuffer() { read(); read(); read(); } \
INLINE static bool isFrameError() { return TESTBIT(UCSR##N##A, FE##N); } \
};
#if defined ATMEGA128
enum {Usart0, Usart1};
defUART(0)
defUART(1)
#elif defined ATMEGA1280
enum {Usart0, Usart1, Usart2, Usart3};
defUART(0)
defUART(1)
defUART(2)
defUART(3)
....
А затем USART<x> можно передавать как аргумент шаблона. Имхо это лучше передачи регистров - семантика регистров сильно процессорно-зависима, а USART<x> скрывает детали процессора.