Не надо ничего выворачивать. Вот обработка индикации в часах на ATMega8 (тех, что с эффектами):
Спойлер
Код: Выделить всё
flash unsigned char razr[6]={0b100000,0b10000,0b1000,0b100,0b10,0b1};
flash unsigned char code[11]={0b000000,0b001000,0b001100,0b100100,0b110000,0b110100,0b010000,0b010100,0b100000,0b000100,0b111100};
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
if(counter<5) counter++;
else counter=0;
PORTD=PIND&0b11000000;
if((ind[counter]!=_ind[counter])&&mode){
if(change==0){
if(mode==1) {lum=-1; OCR2=16; TIMSK|=0x80;}
if(mode==2) rotate=0;
div=-1;
}
change|=(1<<counter);
}
if(change==0) _ind[counter]=ind[counter];
if((mode==2)&&(change&(1<<counter))) buffer=code[rotate];
else buffer=code[ind[counter]];
if(ind[6]&(1<<(5-counter))) buffer=buffer|0b10;
PORTC=(PINC&1)|buffer;
PORTD=PIND|razr[counter];
if(div<24) div++;
else{
div=0;
if(change&&(mode==1)){
if(lum<14) lum++;
else{
lum=0;
change=0;
TIMSK&=(~0x80);
_ind[0]=ind[0];
_ind[1]=ind[1];
_ind[2]=ind[2];
_ind[3]=ind[3];
_ind[4]=ind[4];
_ind[5]=ind[5];
}
OCR2=16+14*lum;
}
if(change&&(mode==2)){
if(rotate<9) rotate++;
else{
change=0;
_ind[0]=ind[0];
_ind[1]=ind[1];
_ind[2]=ind[2];
_ind[3]=ind[3];
_ind[4]=ind[4];
_ind[5]=ind[5];
}
}
}
}
Тут так много кода, т.к. эффекты. Основной смысл тут:
Код: Выделить всё
flash unsigned char razr[6]={0b100000,0b10000,0b1000,0b100,0b10,0b1}; flash unsigned char code[11]={0b000000,0b001000,0b001100,0b100100,0b110000,0b110100,0b010000,0b010100,0b100000,0b000100,0b111100};
Код: Выделить всё
buffer=code[ind[counter]]; if(ind[6]&(1<<(5-counter))) buffer=buffer|0b10; PORTC=(PINC&1)|buffer; PORTD=PIND|razr[counter];
ШИМ лучше делать вторым прерывание таймера, по совпадению. В нём просто гасить все разряды. Изменяя значение регистра сравнения, можно изменить ширину импульса, т.е. яркость. За одно и паузу при переключении разрядов можно сделать, это избавит от проблем с засветкой.
А вот, кстати, код индикации часов, что на фото выше. Там и регулировка яркости есть, и антизасветка.
Спойлер
Код: Выделить всё
flash unsigned char code[10]={0b0100,0b1100,0b0011,0b0001,0b1011,0b0010,0b1010,0b1000,0b1001,0b0000};
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
static unsigned char counter=0;
static unsigned char div=0;
_dot_l=0;
_dot_r=0;
if(dot_l&(1<<(3-counter))) _dot_l=1; if(dot_r&(1<<(3-counter))) _dot_r=1;
if(ind[counter]!=sp){
PORTB=code[ind[counter]]; PORTB|=(1<<(counter+4)); }
if(counter<3) counter++;
else counter=0;
if(div<77) div++;
else{
div=0;
kn1=(~_kn1);
kn2=(~_kn2);
kn3=(~_kn3);
}
if(mig_dot) sec_dot=sec&1;
}
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
PORTB&=0x0F; }