Guten Abend Markus - ersteinmal danke für die Rückmeldung.
Zu den paar Dingern:
1. Das war mir nicht völlig bewusst, deshalb mal nach dem Motto " vorsichthalber, man weiß ja nie" vorgegangen 
2. Eigentlich war mein Ziel den Ansatz zu vereinfachen - meine erste Version benötigt zwei Timer zur Zeitmessung und einen für Multiplexing. Damit hätte ich keine Timer mehr zur Verügung 
Diese Version funktioniert auch wirklich gut - benötigt wird der Ganzzahlenbereich von 1-9999 Hz. Wurde alles perfekt angezeigt. Verbessern wollte ich das wegen des Offsets von einer Sekunde, die mit einem Timer gemessen wurde, während mit dem anderen Timer Flanken registriert wurden.
3. Du hast Recht, diese Optimierungen kommen nur nicht sofort in den Sinn, da braucht man die Erfahrung 
4. Da ich keine Nachkommastellen brauche, gehe ich von aus, dass es mit einem Zyklus geht. Wenn nicht, habe ich da diese Option des Noise Canceler gefunden...
5. Falls eine lineare Abweichung aufgrund des Quarzes eintritt brauche ich da nur einen korrekturfaktor einzusetzen und nicht mit datentypen spielen - so der Gedanke 
Danke für die Tipps - die Sache mit überflüssigen Variablen werde ich so weit es geht zu klären versuchen.
Anbei mein "Fortschritt" (mit noch nicht optimierten Variablen) 
MfG Nik
Code:
#define F_CPU 16000000 // uC läuft mit 16MHz
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
volatile unsigned short z=0;
volatile unsigned short UpdateDisplay; // Verzögerung
volatile unsigned int Startzeit = 0; // ICR-Wert bei 1. steigender Flanke sichern
volatile unsigned int Endzeit = 0; // ICR-Wert bei 2. steigenden Flanke sichern
volatile unsigned int LowByte = 0;
volatile unsigned int HighByte = 0;
int zaehler1_ovf = 0; // Anzahl der Überläufe des Timer1
uint16_t freq = 0;
unsigned long zaehlschritte = 0;
ISR(TIMER1_OVF_vect)
{
z++;
//TIFR = (1<<TOV1); //Beim Überlauf von Timer1 und dem anschließenden Interrupt erfolgt eine Zurücksetzung auf Null
}
ISR(TIMER1_CAPT_vect)
{
static unsigned short ErsteFlanke = TRUE;
if(UpdateDisplay) // Das Display wurde mit den Ergebnissen der vorhergehenden
{ // Messung noch nicht aktualisiert. Die nächste Messung
return; // verzögern, bis die Start- und EndTime-Variablen wieder
} // gefahrlos beschrieben werden können
LowByte = ICR1L; // low Byte zuerst, high Byte wird gepuffert
HighByte = ICR1H;
// overflow verpasst, wenn ICR1H klein und wartender Overflow Interrupt
if ((HighByte < 128) && (TIFR & (1<<TOV1)))
{ // wartenden timer overflow Interrupt vorziehen
++z;
TIFR = (1<<TOV1); // timer overflow int. löschen, da schon hier ausgeführt
}
// Bei der ersten Flanke beginnt die Messung, es wird der momentane
// Timer beim Input Capture als Startwert gesichert
if(ErsteFlanke)
{
Startzeit = ICR1;
z = 0;
ErsteFlanke = FALSE; // Nach der nächsten Flanke beginnt die Ausgabe
}
// das ist die zweite Flanke im Messzyklus. Die Messung wird gestoppt
else
{
Endzeit = ICR1;
UpdateDisplay = TRUE; // Eine vollständige Messung. Sie kann ausgewertet werden
ErsteFlanke = TRUE; // Bei der nächsten Flanke beginnt der nächste Messzyklus
}
}
int main(void)
{
// Definition von Ein- und Ausgängen des uC Boards
DDRB = 0xFE; // Mit Ausnahme des ICP1-Pins alles als Ausgang
DDRC = 0xFF; // PORTC als Ausgang - über PORTC werden die jeweiligen Segmente einer 7-Seg. Anzeige gesteuert
DDRD = 0xFF; // PORTD als Ausgang
PORTC = 0b00000000;
TIMSK = (1<<TICIE1) | (1<<TOIE1); // Interrupts akivieren, Capture und Overflow
TCCR1B = (1<<ICES1) | (1<<CS10); // Input Capture Edge, kein Prescaler
sei(); // Interruptbehandlung ein
while(1) // unendliche Schleife
{
if(UpdateDisplay) // Erst nach zweiter Flanke ausführen
{
zaehler1_ovf = z; // Anzahl der Überläufe wird in zaehler1_ovf kopiert
z= 0;
zaehlschritte = (unsigned long)(0.5+(65536.0*zaehler1_ovf) + Endzeit - Startzeit);
if (zaehlschritte==0)
{
freq = 0;
}
else
{
// Die abschließende Summierung aller Anteile samt Kompensation von Abweichungen
freq = (uint16_t) (F_CPU/(zaehlschritte));
}
zahl_ausgeben(freq);
UpdateDisplay = FALSE;
}
}
return 0;
}
EDIT: Wieso ich keinen Prescaler verwende? Der Gedanke war, dass je mehr Signale pro Zeiteinheit gemessen werden können, desto genauer auch die Anzeige sein wird. 
EDIT 2:
Änderungen:
Code:
volatile unsigned long Zeitdifferenz = 0;
ISR(TIMER1_CAPT_vect)
{
static unsigned short ErsteFlanke = TRUE;
static unsigned long Startzeit = 0; // Startzeit als static deklariert
...
{
Zeitdifferenz = ICR1 - Startzeit; // Jetzt wird
UpdateDisplay = TRUE; // Eine vollständige Messung. Sie kann ausgewertet werden
ErsteFlanke = TRUE; // Bei der nächsten Flanke beginnt der nächste Messzyklus
}
}
...
int main(void)
{
...
zaehlschritte = (unsigned long)(0.5+(65536.0*zaehler1_ovf) + Zeitdifferenz);
...
}
Lesezeichen