Я вам уже намекал ранее, что SPI используется лишь ля связи с м/с драйвера LED. Программно вы можете реализовать любой абстрактный образ индикатора, преобразуя его непосредственно перед выводом в м/с драйвера в вид сообразный реальной схеме подключения. Способов преобразования абстрактной модели объекта в реальную схему как минимум два: логическое (с помощью логических функций) или табличное преобразование.
Поясню. Допустим у вас 4 светодиода, подключенных к пинам 1, 2, 3, 4 в таком порядке LED1, LED4, LED3, LED2 (нумерация условна). При выводе байта биты в нем соответствуют 0й бит - пин 1, 1й бит - пин 2, 2й бит - пин 3, 3й бит - пин 4. Соответственно в программе вы работаете с этим байтом как угодно, устанавливая и сбрасывая биты по требуемому алгоритму. Но перед выводом в м/с драйвера запускается преобразование, которое состояние бит вашей абстракции корректирует так, как у вас светодиоды подключены в реальности.
"Тупой" пример преобразования.
Код
#define LEDS_MAXNUM 4 //количество светодиодов
const unsigned LedCnvTbl[LEDS_MAXNUM]=
{ // индекс - номер светодиода; значение - его реальное подключение в схеме
0, // позиция LED1
3, // позиция LED2
2, // позиция LED3
1 // позиция LED4
};
uint8_t led_state; // абстрактное состояние светодиодов
uint8_t led_out; //буфер вывода для драйвера светодиодов
void main (void)
{
uinsigned cntr;
uint8_t mask;
...
mask = 1;
for (cntr=0; cntr<LEDS_MAXNUM; cntr++)
{ if ((led_state&mask)==0)
led_out &= ~(1U<<(LedCnvTbl[cntr]));
else
led_out |= 1U<<(LedCnvTbl[cntr]);
mask <<= 1;
}
...
}
В результате преобразования переменная led_out будет иметь такие же значения состояний светодиодов как и в абстрактной модели led_state, но позиционные битовые значения в ней будет скорректированы с учетом описанного выше
реального подключения светодиодов в схеме.