Also ich würd das mit dem Rechtecksignal mit einem Comparematch Interrupt mit dem Timer1 machen.
Wenn Du die Taktfrequenz geschickt auswählst Ich würd vermutlich 8 MHz nehmen kommst Du auf deine gewünschte Periodendauer.
In das Comparematch Vergleichsregister trägst du je nach gewünschter Periodendauer den Vergleichswert ein (Tabelle oder den Controller rechnen lassen). Der Vergleichswert sollte der halben Periodendauer entsprechen, weoil Du ja eine positive und eine negative Halbwelle brauchst.
Wenn dann der Timer diesen Wert erreicht hat löst er einen Comparematch Interrupt aus. Der interne Timer wird wieder auf 0 gesetzt, was man auch durch setzen eines Bits machen kann.
In der gleichen Routine wird dann dein Port C0 von 0 nach eins bzw. von 1 nach 0 gesetzt.
Die Abfrage von deinem Eingangsport PortA sowie die Neubeschreibung der Comparematchwerte würd ich auch in dieser Interrupt Routine machen um Überholeffekte zu vermeiden.
Ob Du die Abfrage von PortA, sowie die Berechnung des Comparematchwertes in den Interrupt reinkriegst ist vor allem ein Timingproblem. Vor allem wenn eine Periodendauer von 1mS = 0,5mS für eine halbe Periode gefordert wird.
Während des Schreibens der Comparematchwerte in ein Hilfsregister, das dann später in der Comparematch Routine abgefragt wird würd ich mit "CLI" eine Interruptausführung kurz unterbinden um zu Vermeiden, das zwischen dem Schreiben der beiden Bytes ein Interrupt auftreten kann.
Wie genau diese Routine arbeitet ist hauptsächlich davon abhängig wieviele andere Interrupts auch noch aktiv sind, weil ein aktiver Interrupt die Ausführung eines weiteren verhindert.
Ausserdem solltest Du die Abschaltung von Interrupts mit "CLI" im Hauptprogramm möglichst vermeiden und die Befehle bis zum "SEI" auf ein minimum beschränken, da es sonst zu einem kleinen Phasenjitter kommen kann.
Ein weiterer Punkt ist im Tastverhältnis versteckt.
Wenn ein Tastverhältnis von genau 50% gefordert ist musst Du dafür sorgen, das in diesem Comparmatchinterrupt genau gleich viele Taktzyklen fur das Ausschalten, sowie für das Einschalten des Ports C0 gebraucht werden.
Eine möglichkeit wäre den PORTC0 in ein Register einzulesen, mit EOR 0b00000001 das letzte Bit umzukehren und den Registerwert wieder in den PORTC zurückzuschreiben.
Da dabei immer die gleiche Befahlsanzahl durchlaufen wird, sollte auch das Tastverhältnis genau 50% betragen.
Versuchs mal es ist eigentlich einfacher als man denkt.
Die 1ms Zeitschleife würd ich einfach mal ins Blaue (so ungefähr)programmieren und mit dem Simulator (AVR STudio 4) die genauen Zeiten austesten.
Normalerweise zählt man dazu einfach irgendwelche vorbelegten Registerwerte runter bis die 0 erreichen und springt dann aus der Routine wieder raus. Wenn während der Zählschleife natürlich Interrups auftreten braucht die Zeitroutine natürlich für die Abarbeitung mehr als 1ms.
Wenn Du natürlich einen mathematischen Weg für sowas brauchst musst Du halt ein wenig rechnen.
Lesezeichen