имхо, тема
viewtopic.php?f=57&t=113571 закрыта преждевременно, хотя в целом тема не новая. речь идет (вангую!) о ситуации, когда, например, выводы сегментов индикатора подключаются не к одному порту, а к разным, да еще и биты не по порядку, а вперемешку. думаю, каждый, кто сталкивался с трассировкой плат с семисегментниками сталкивался с этой проблемой: либо простая программа, выводящая сегменты в один порт, либо удобная разводка платы, оптимально подводящая пины индикатора к пинам МК.
когда я делал свои проекты из ряда "меньше не бывает", эта проблема была очень актуальной, и до сих пор приводит в ступор всех, кто пробует перебросить выводы иначе, чем сделал я.
к сожалению, однозначной методики решения подобной проблемы нет, если не считать промелькнувшей пару лет назад темы одного весьма уважаемого среди микроконтроллерщиков разработчика (вот убей меня бог, проклятый склероз не дает мне вспомнить, кто это был). только тема та была связана с шаблонами С++ и требовала просто колоссальных знаний языка С++, лично я не врубился, хотя круть ощутил...
обычно же перестановка битов сводится к следующему.
1. исходные данные
допустим, на входе имеем индикатор, у которого сегменты на выводы подаются в таком порядке ABCHGEFD
при этом удобнее всего развести сегменты ABCD на порт D микроконтроллера, причем в таком порядке побитово ...AB.DC, а остальные на порт С, причем в таком порядке E.F...HG
2. задача: написать код, поддерживающий "прозрачный" с точки зрения программиста вывод чисел на сегменты.
3. решение (в частном случае)
нарисуем табличку "соответствия" битов
Код: Выделить всё
символ ABCHGEFD
PORTD ...AB.DC
PORTC E.F...HG
хорошо видно, что для вывода в порт D надо биты AB сдвинуть вправо на 3 позиции, D на 1 влево, а C - на 5.
аналогично для вывода в порт С нужно E сдвинуть на 5 влево, F на 4 влево, а пару HG вправо на 3.
естественно, все прочие биты игнорировать, т.е. не менять.
лично я уже на этом этапе думаю: а на самом ли деле именно такое распределение сегментов по битам портов наиболее оптимально? и, если готов чем-то пожертвовать, я корректирую схему, а следовательно и распределение битов, т.е. перестраиваю таблицу соответствий. цель при этом - добиться наименьшего количества сдвигов. т.е. я стремлюсь разбросать сегменты так, чтобы как можно больше сегментов находились рядом друг с другом, чтобы двигать их все одновременно, как в случае с битами AB и HG - если бы тут было не по 2 сегмента в группе, а по 3 или даже 4 - все было бы просто идеально!
но продолжим рассмотрение нашего неудачного случая.
итак, мы определили, какие биты в какую сторону надо двигать, при этом знаем, что перед началом сдвигов надо отфильтровать их от остальных. т.е. наши действия сводятся к выделению нужных битов, сдвигов их и накоплении результата, который затем выводится в порт.
получается нечто такое:
Код: Выделить всё
// для удобства определим константы, определяющие биты сегментов
#define A 0x80
#define B 0x40
... и так далее
// в этой переменной у нас будет число, которое надо вывести на сегменты
char symbol;
// далее я разобью оператор на строки, чтобы было понятнее, в каком месте что делается
PORTD = // в порт D будет выводиться
(PORTD & ~(A | B | D | C)) // содержимое тех битов порта, которые не назначены сегментам, отсюда инверсия перед скобками
| (((symbol & (A | B)) >> 3) // сдвинутые на 3 позиции вправо биты AB
| ((symbol & D) << 1) // сдвинутый на 1 влево бит D
| ((symbol & C) << 5) // и сдвинутый на 5 влево бит С
; // все, наконец-то
// аналогично надо сформировать и новое значение порта С - не буду делать этого в целях экономии своих сил
надеюсь, понятно, что операция & служит для выделения значения определенного бита или группы битов, операция | для формирования самой группы битов, а инверсия вкупе с & выполняет функцию сбрасывания указанной группы битов, т.е. их обнуление. если это непонятно - курите битовые операции
вот как-то так...

понятно ли начинающим?
