Hallo, ich hab den AT90S2313 und brauche verschiedene Blinktakte an den Ausgängen. Also Beispiel: PD6 blinkt mit 20Hz / PD5 blinkt mit 10Hz und PD4 mit 50Hz oder so in etwa. Ich programmier noch nicht lange und hab noch keine Idee wie man soetwas macht. mit dem Wait-Befehl geht das wohl schlcht oder. Vorschläge bitte in Basic. Danke schon mal, Tobias
Ach so, ich hab noch etwas vergessen: die Lampen sollen natürlich alle "gleichzeitig" blinken. Tobias
Dein Freund ist der Timer-Interrupt. Lass diesen mit dem kleinsten gemeinsamen Vielfachen deiner Wunsch-Frequenzen "klappern" und behandle in dieser ISR für jeden "Taktausgang" eine separate Zählvariable, mit der du den Ausgang steuerst. In ASM ist das kein Problem, es müsste also auch mit einer Hochsprache zu realisieren sein...
ja danke- aber so richtig werd ich daraus nicht schlau. könnte ich da mal ein Beispiel in Basic bekommen? Tobias
Hi... BASIC kann ich leider nur auf dem Commodore plus/4 und dem PC, bei AVR leider (oder Gottseidank) nicht. Aber nochmal zum Problem. Du möchtest verschiedene Blinkfrequenzen gleichzeitig ausgeben. Dazu rechnest du dir erstmal eine "Taktfrequenz" aus, die durch alle deine gewünschten Frequenzen teilbar ist. Willst du 10Hz, 50Hz und 30Hz, so ist 150Hz schonmal nicht schlecht. Denn dann hast du als Teiler 15, 3 und 5. 1,5kHz wäre besser, dann teilt man durch 150, 30 und 50... Du stellst also Timer0-Vorteiler und Timer0-Startwert so ein, dass Timer0 alle 6,67ms (1/150Hz) einen Überlauf-Interrupt erzeugt. In der ISR (Beispiel 150 Hz) musst du dann Folgendes tun: - SREG sichern (zumindest in Assembler) - Timer0 auf Startwert setzen (n Takte vor Überlauf) - die Variable für erste Frequenz runterzählen * bei 0 wieder auf Startwert (im obigen Beispiel 15) setzen und * den Portpin für Freq.1 toggeln - die Variable für zweite Frequenz runterzählen * bei 0 wieder auf Startwert (im obigen Beispiel 3) setzen und * den Portpin für Freq.2 toggeln - die Variable für dritte Frequenz runterzählen * bei 0 wieder auf Startwert (im obigen Beispiel 5) setzen und * den Portpin für Freq.3 toggeln - SREG wiederherstellen (in ASM) Das Hauptprogramm schickt dann den AVR schlafen oder macht noch anderes sinnloses Zeugs... Willst du die Frequenzen flexibel machen, dann setze die ISR-Frequenz (also die Frequenz der Timer-Interrupts) so hoch, dass du mit größeren Teilern arbeiten kannst. In ASM würde ich darauf achten, dass der maximal erforderliche Teiler 255 beträgt, also ein Register als Variable genügt. Das macht das Programm schnell und überschaubar, denn eine ISR soll möglichst kurz sein. Wenn es nötig ist, gehen auch 16-Bit-Teiler (also jeweils 2 Register), aber eben nur, wenn unbedingt nötig. Brauchst du noch eine Tastaturabfrage, so lass eine weitere Zählvariable mitlaufen, mit der du alle 100...200ms deinen Eingangsport abfragst und die Werte mit den zuvor eingelesenen Werten vergleichst, so hast du gleich eine Flankenerkennung, die die Tasten einigermaßen entprellt (für Profi-Lösungen siehe Codesammlung). ...HanneS...
Sorry, mein Rechenbeispiel stimmt nicht, die Zeiten gelten nicht für die Periode sondern nur für die halbe Periode. Es kommt also nur die halbe Frequenz heraus. Du musst die ISR-Frequenz also verdoppeln...
SUPER TOLL - das hab ich schon fast verstanden glaub ich ;-) 1. was ist toggeln? --- 2. nur zu Verständniss: -Timer0 läuft runter(erste frequenz) -timer0 wird mit 2. zeit neu gestartet und läuft wieder runter -timer0 wird mit 3. frequenz neu gestartet und läuft wieder runter und dann ist ein µC-Zyklus durch und wie/wann wird der Ausgang gesetzt/rückgesetzt? oder so: -Ausgang 1 setzen -Timer0 läuft runter(erste frequenz) -Ausgang 1 rücksetzen -Ausgang 2 setzen -timer0 wird mit 2. zeit neu gestartet und läuft wieder runter -Ausgang 2 rücksetzen -Ausgang 3 setzen -timer0 wird mit 3. frequenz neu gestartet und läuft wieder runter -Ausgang 3 rücksetzen danke schon mal, Tobias
Hi... 1. Toggeln ist Umschalten, aus H mach L, aus L mach H, also den Pegel am Pin wechseln... 2. Nein, falsch... Der Timer läuft mit einer festen Frequenz. Damit er das tut, muss man den (für diese Frequenz notwendigen) Vorteiler einstellen und den Timer in jeder ISR (Interrupt-Service-Routine) wieder mit dem richtigen Startwert laden. Für jeden zu erzeugenden Blinktakt wird eine weitere Variable gebraucht, zweckmäßigerweise ein Register. Jedes dieser Register wird in der ISR um 1 vermindert. Wird dabei der Registerwert 0, dann setzt man das Register wieder auf den für diesen Blinktakt erforderlichen Startwert und schaltet das Ausgangsbit um. Dies wird für jeden Blinkausgang getrennt gemacht. Man kann dabei den ISR-Takt als Zeitnormal sehen, jeder Blinktakt dauert eben soundsoviele ISR-Takte, wenn die abgelaufen sind, wird von vorn gezählt. In ASM sieht die ISR etwa so aus: timer0ovf: ;Einsprungpunkt, der als Intvektor eingetragen wird in r2,sreg ;Statusregister sichern out tcnt0,r3 ;Register r3 enthält den Timer-Startwert (256-n) ;Blinker 1... dec r16 ;R16 um 1 vermindern brne label2 ;bei nicht 0 weg hier... ldi r16,15 ;Startwert (15) in Register 16 laden sbis portb,0 ;Portbit (PB0) gesetzt? rjmp label1 ;nein, dann nicht setzen cbi portb,0 ;Portpin auf Low setzen rjmp label2 ;und weiter... label1: ;PB0 war also nicht gesetzt, deshalb sbi portb,0 ;Portpin auf High setzen label2: ;Blinker 2... dec r17 ;R17 um 1 vermindern brne label4 ;bei nicht 0 weg hier... ldi r17,5 ;Startwert (5) in Register 17 laden sbis portb,1 ;Portbit (PB1) gesetzt? rjmp label3 ;nein, dann nicht setzen cbi portb,1 ;Portpin auf Low setzen rjmp label4 ;und weiter... label3: ;PB1 war also nicht gesetzt, deshalb sbi portb,1 ;Portpin auf High setzen label4: ;Blinker 1... dec r18 ;R18 um 1 vermindern brne label6 ;bei nicht 0 weg hier... ldi r16,3 ;Startwert (3) in Register 18 laden sbis portb,2 ;Portbit (PB2) gesetzt? rjmp label5 ;nein, dann nicht setzen cbi portb,2 ;Portpin auf Low setzen rjmp label6 ;und weiter... label5: ;PB2 war also nicht gesetzt, deshalb sbi portb,2 ;Portpin auf High setzen label6: ... out sreg,r2 ;Statusregister wiederherstellen reti ;fertig... (RETurn from Interrupt) Das sieht gegenüber BASIC zwar viel aus, ist es aber nicht, denn jeder Befehl kostet nur 2 Bytes Flash (1 Word) und dauert meist nur ein oder zwei Takte... Das Toggeln geht auch noch etwas eleganter, ich habe aber bewusst diese Form gewählt. Übrigens kann man den Registern "sprechende Namen" zuweisen, das macht den Code lesbarer. Mit den Konstanten geht das auch. Ich habe hier darauf verzichtet, da ich nicht das ganze Programm schreiben will... ...HanneS...
Lach... Typischer Fehler beim Kopieren... Das zweite "Blinker 1..." muss natürlich "Blinker 3..." heißen... Aber das erkennt man ja, oder?
DANKE! Dann werd ich das mal in Basic versuchen - vielen Dank! Tobias
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.