Also um das LED-Multiplexing hab ich mir nicht großartig Gedanken gemacht, Bedingung war eigentlich nur, dass die Anzeige möglichst hell sein sollte, damit die Kamera auch gut belichtet wird

Ich habe zusätzlich einen 74HC4543 (Treiber/Decoder/Latch) vor jede Sieben-Segment-Ziffer gebaut. Dadurch muss man nur den 4 Bit breiten Dezimalwert ausgeben und der Decoder bereitet die Daten dann so auf, dass die Sieben-Segment-Anzeige alles richtig anzeigt.
Bei mir sieht das dann so aus, wenn 100us rum sind werden alle Ziffern ausgeschaltet, alle Latches nacheinander mit neuen Werten beschrieben und danach werden alle Ziffern wieder eingeschaltet und die neue Zeit steht dann da. Der ganze Vorgang dauert so um die 3,6us.
Wenn du solche Bauteile auch anwenden darfst würde ich das machen.
Ich hab mir eben mal das Datenblatt angeschaut zu dem 18F876, der besitzt auch ein CCP-Modul. Schau mal unter 8.2 Compare Mode im Datenblatt. In dem anderen Beitrag von mir mit 15.3.. unter diesem Kapitel steht es in den 18F Datenblätter.
Das ist eigentlich ganz easy. Zuerst mal brauchst Du den TMR1 um mit dem CCP-Modul arbeiten zu können. Dann stellst Du das CCP-Modul so ein, dass es im Compare-Modus arbeitet und schreibst vorher noch den Zählerstand, wie weit der TMR1 zählen soll, in das CCPR1 Registerpaar. Nun wird ständig der TMR1 mit dem CCPR1 verglichen und wenn der TMR1 bis zu dem Wert im CCPR1 hochgezählt hat, wird das CCPIF-Interruptflag gesetzt und der TMR1 wird automatisch auf 0 gesetzt und läuft ganz normal weiter. Damit sparst Du Dir schonmal das vorladen des Timers. Einfach den Prescaler und das CCPR1 Register einmal richtig einstellen und Du bekommst ständig einen Interrupt in einem festen Interval.
Und das Programm könnte dann so irgendwie aussehen:
void main(void) {
unsigned char zehn_ms=0;
unsigned char led_mux=0;
init(); // Hier stellst Du alles ein was Du brauchst, CCP-Modul, CCPR1-Register, Pins usw...
while(1) {
if(CCPIF) { // Das CCPIF wird alle z.B. alle 1ms gesetzt)
CCPIF=0;
zehn_ms++;
led_mux++;
if(zehn_ms==10) {
zehn_mus=0;
// jetzt sind wieder 10ms vergangen und dann wird hier eine
// Funktion aufgerufen in der die Variablen der Zeit geändert werden
}
if(led_mux==XX) {
led_mux=0;
// hier gehts dann irgendwie weiter :)
}
}
}
Nur mit dem LED-Mux musst Du Dir mal etwas genauere Gedanken machen. Ich habs wie gesagt mit Latches gemacht und da ist die Anzeige ständig da, da muss nur beim beschreiben der Latches einmal gemuxt werden. Ansonsten hast Du bei 50Hz 20ms Periodendauer und in dieser Zeit müssten alle Anzeigen neu beschrieben werden. Also bei 6 Ziffer hättest du dann 3,33ms Leuchtdauer pro Ziffer. Das könnte vielleicht nen bissel dunkel werden

aber ich würde es einfach mal versuchen.
Vielleicht so, ich nehme hier mal an, dass die Daten über PortA laufen und die Steuerleitungen über den PortB:
void main(void) {
unsigned char anzeige[5]={0,0,0,0,0,0}; // hier sollen die fertigen Daten zur Ausgabe stehen, für jede Ziffer ein Element
unsigned char i=0;
if(led_mux==3) { // wenn man das genauer brauch, muss man eine kleinere Zeitbasis wählen
led_mux=0;
ausgabe(anzeige[i], i);
i++;
if(i==6) { // wenn die letzte Ziffer beschrieben wurde, fängt es wieder von vorne an
i=0;
}
}
}
void ausgabe(unsigned char wert, unsigned char ziffer) {
LATB = 0; // die vorherige Stelle wieder ausschalten
LATA = wert; // Datenport mit neuem Wert beschreiben
LATB = 1<<ziffer; // an PortB hängen die Steuerleitungen common_anode oder common_kathode musst du dann selbst schaun
// die nächste Stelle einschalten
// und die bleibt für die nächsten 3 ms auch an
}
Also ob das so funktioniert weis ich nicht, sieht aber schonmal gut aus

Probier einfach mal nen bissel rum...
Um noch mal auf Deine Frage wegen der Interrupts zurück zu kommen, bei den 16F war es glaub ich so, dass es keine priorisierten Interrupts gibt. Sobald ein Interrupt auftritt wird dieser abgearbeitet und falls währenddessen ein weiterer auftritt wird dieser danach abgearbeitet. Aber für diese Aufgabe brauchst die Interrupts nicht zu aktivieren, wenn Du das eine Flag einfach so in der Software abfragst ist das genau genug für eine Stopuhr. Die jeweiligen Interruptflags werden immer gesetzt, auch wenn die Interrupts nicht aktiviert sind (GIE bleibt 0). Es erfolgt dann einfach keine Programmunterbrechung.
Gruß
Flo