Очень и очень часто приходится манипулировать кучей никак не связанных между собой пинов, вот и возникают куча дифайнов и прочей лабуды.
Есть довольно простое решение, немного тормознее, чем хардкод, и память кушает, но много удобнее.
В принципе, ничего нового для программистов я не скажу, а вот для тех у кого в голове ARDUINO, будет полезно
Оформляем структуру в которой будем хранить пины:
1 2 3 4 | typedef struct { volatile uint8_t *port; uint8_t pin; } out_t; |
а дальше создаем массив этих структур:
1 2 3 4 | out_t outs = { { &PORTA, PA1}, { &PORTB, PB4}, }; |
ну и так далее. Получается удобно проходить в цикле.
1 2 3 4 | uint8_t i; for(i=0;i<sizeof(outs)/sizeof(out_t);i++){ *outs[i].port |= _BV(outs[i].pin); } |
ну и как бонус — инициализация. в AVR регистр направления DDRx всегда на 1 байт младше, чем соответствующий PORTx, получается небольшой трюк:
1 2 3 4 | uint8_t i; for(i=0;i<sizeof(outs)/sizeof(out_t);i++){ *(outs[i].port-1) |= _BV(outs[i].pin); } |
- инициализация на выход всего массива. Это много медленнее, чем одной операцией проставить все нужные пины, но если время не критично — поддерживать такой код порядком проще: добавили запись в массив — и готово.
Да, чтобы не тратить память, можно все это хранить в PROGMEM и доставать по необходимости.
ну и еще напоследок, удобный макрос от разработчиков ядра Linux для ловли багов:
1 2 3 | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) // и его применение BUILD_BUG_ON(sizeof(phs_entry_t) != sizeof(uint32_t)); |
если структура phs_entry_t размером не равна uint32_t (32 бита) — код не соберется