...Offensichtlich würdest Du die Timer nach erfolgter Zählung gar nicht abschalten, deshalb Dein Hinweis (Achtung, Reihenfolge!). Du speicherst also die aktiven Zähler und hast dann immer im SRAM den letzten gemessenen Wert. Das hat was für sich, wenn man den Wert nicht nur ab und zu benötigt UND wenn es problemlos klappt.
den 8bit-Zeit-Timer würde ich durchlaufen lassen - der erzeugt Dir die äquitemporalen Perioden (von eventuellen Verzögerungen durch noch nicht beendete andere Interrupts mal abgesehen, diese sollten also auch möglichst kurz sein). Der 16bit-Frequenz-Zähler sollte eigentlich gar nicht überlaufen können, da er ja immer zurückgesetzt wird (Überlauf eben erst ab ca. 5MHz)
Zur Reihenfolge: Probleme kann es doch eigentlich nur geben, wenn das niederwertige Byte gerade überläuft. Speichert man in der Reihenfolge H/L, dann kann
folgendes passieren:
Zählerstand: 0x00FF -> SRAM: 0x00??
Zählerstand: 0x0100 -> SRAM: 0x0000 ; Fehler 256
Andererseits, wenn man in der Reihenfolge L/H speichert:
Zählerstand: 0x00FF -> SRAM: 0x??FF
Zählerstand: 0x0100 -> SRAM: 0x01FF ; Fehler 255 (auch nicht viel besser!)
Das heißt doch aber, daß man den Zähler zum Speichern ausschalten muß, oder?
Deswegen ja die Reihenfolge, Aus dem Datenblatt des Mega88/...:
16.3Accessing 16-bit registers The TCNT1, OCR1A/B, and ICR1 are 16-bit registers that can be accessed by the AVR CPU via the 8-bit data bus. The 16-bit register must be byte accessed using two read or write operations. Each 16-bit timer has a single 8-bit register for temporary storing of the high byte of the 16-bit access. The same temporary register is shared between all 16-bit registers within each 16-bit timer. Accessing the low byte triggers the 16-bit read or write operation. When the low byte of a 16-bit register is written by the CPU, the high byte stored in the temporary register, and the low byte written are both copied into the 16-bit register in the same clock cycle. When the low byte of a 16-bit register is read by the CPU, the high byte of the 16-bit register is copied into the temporary register in the same clock cycle as the low byte is read . Not all 16-bit accesses uses the temporary register for the high byte. Reading the OCR1A/B 16bit registers does not involve using the temporary register. To do a 16-bit write, the high byte must be written before the low byte. For a 16-bit read, the low byte must be read before the high byte.
Das geschieht automatisch im Hintergrund. Wenn Du auf das High-Byte zugreifst, wird in der Hardware in Wirklichkeit das temporary Register angesprochen; die Aktualisierung des HByte<->temporary Register wird über den Zugriff auf das Lowbyte getriggert. So'ne ähnliche Sache gibt es bei'm UART Data Register (UDR). Das sind in Wirklichkeit 2 - eins zum Senden, eins zum Empfangen. Wenn Du das UDR liest, wird das Empfangsregister adressiert, wenn Du schreibst das Senderegister. Für Dich heissen die aber beide UDR.
Allerdings spukt mir noch'ne ganz elegante Geschichte im Kopf rum:
-Man lasse den Zeit-Zähler seinen Output-Compare-Pin toggeln (bzwim PWM setzen/löschen), und verbinde diesen Pin mit dem IC-Pin von Timer1.
-Timer1 zählt wie gehabt die Frequenz (also die Perioden).
-die entsprechende Flanke am IC-Pin bewirkt automatisch, daß TCNT1 ins ICR kopiert wird. (Da steht dann also die Anzahl der Perioden pro 8bit-Timerüberlauf - bisher alles in Hardware im Hintergrund)
-das IC-Event kann einen IRQ triggern, in dessen ISR muß möglichst schnell TCNT1 zurückgesetzt werden (Reihenfolge!), und dann das ICR ausgelesen werden (was allerdings Zeit bis zum nächsten 8bit-Timerüberlauf hat). (Oder kann man Timer1 mit CTC mit ICR als TOP UND ICR durch den entsprechenden Pin gleichzeitig ... hmm... grübel)
Edit:
Das Kauderwelsch da oben soll heissen: Kann ich einen Flankenwechsel/steigende/fallende Flanke am InputCapturePin GLEICHZEITIG zum :
-Clear Timer (CTC)
-(vorheriges) abspeichern des TCNT im ICR
-Generierung eines IRQ
verwenden, bis auf die ISR alles in Hardware, versteht sich?
Und noch'n Edit: erstelle erstmal einen Programmablaufplan (und schreibe den hier).
Trotzdem ein paar Sachen:
-Den Stackpointer mußt Du nicht reinitialisieren (stört aber auch nicht weiter, nur ein paar Takte und Words)
-bei unbenutzten Interruptvektoren ist Schnurz, was drinnsteht, da dieser Code in einem korrekten Programm nie ausgeführt wird, es sei denn man bringt da sinnigen Code unter - ja, ich weiß - da scheiden sich die Geister... (in einer Offiziellen AppNote von Atmel wird übrigens eine ISR direkt an den Interruptvektor geschrieben - ohne Sprungbefehl und über die anderen Vektoren hinweg. geht natürlich nur, wenn man diese nicht braucht. Hab ich auch schon so gemacht...
-zumindest innerhalb der ISRs/Prozeduren kannst Du statt JMP RJMP nehmen.