Anmeldungsdatum: 27.07.2007 Beiträge: 925 Wohnort: Oberhofen im Inntal (Tirol)
Verfasst am: Di 24.Jun 2008 22:00:59 Titel: Timer0 als Timer (Codebeispiel: Sirene)
Hallo!
Im letzten Beitrag hatte ich dich schon auf Timer eingestimmt. Jetzt geht es an's Eingemachte. Lass' uns doch mal den einfachsten Timer des ATmega8 ansehen -- Timer0. Dieser Timer kann von 0 bis 255 zählen. Und bei jedem Überlauf (255 -> 0) kann ein Interrupt (OVF0) ausgelöst werden.
Als "Timer" zählt der Timer0 den Systemtakt. Wenn man keinen Prescaler einstellt, dann wird bei jedem Tick des Systemtakts auch der Wert des Timers um 1 erhöht. Würde man 8 als Prescaler einstellen, dann erhöht sich der Wert des Timers nur alle 8 Ticks.
Da der Timer beim 256. Tick wieder nach 0 überläuft, würde der OVF0-Interrupt bei einem Systemtakt von 8 MHz genau 31.250 mal ausgelöst werden. Würde man im OVF0-Handler einen Pin toggeln, dann hätte man am Ausgangspin eine Frequenz von 15.625 Hz anliegen. Das wäre eine Frequenz, die man nicht hören würde, wenn man sie an einem Lautsprecher anlegt.
Würde man das gleiche Spiel mit einem Prescaler von 8 spielen, dann würde der OVF0-Interrupt bei einem Systemtakt von 8 MHz genau 3.906,25 mal ausgelöst werden. Wie man sieht, ist das keine Ganzzahl mehr. Das liegt an dieser Rechnung:
Toggelt man auch in diesem Fall im OVF0-Handler einen Pin, dann würde am Ausgangspin eine Frequenz von 1.953,125 Hz. anliegen. Steuert man mit diesem Ausgangspin einen Summer (Buzzer) an, dann erhält man einen ziemlich lauten (fast 2 kHz) Ton.
Mach dich bereit, nach dem Übertragen dieses Programmes den Strom vom Board zu nehmen.
Dieser Ton kann ziemlich unangenehm sein (Ohren zuhalten und Kampfhunde anketten).
'Timer0 Overflow Interrupt
'Dieser Interrupt wird beim Überlauf (255 nach 0) ausgelöst
'1000000 (Counts) / 256 (8-Bit Timer) = 3906,25 (Interrupts die Sekunde)
On OVF0 On_ovf0
Enable OVF0
Enable Interrupts
Do
!NOP
Loop
End
'Timer0 Overflow Interrupt
'Zwei mal toggeln entspricht einem Impuls. 3906,25 mal toggeln gibt auf dem
'Buzzer einen Ton mit 1953,125 Hertz.
On_ovf0:
Toggle Buzzer
Return
'Timer0 Overflow Interrupt
'Dieser Interrupt wird beim Überlauf (255 nach 0) ausgelöst
'125000 (Counts) / 256 (8-Bit Timer) = 488,28125 (Interrupts die Sekunde)
On Timer0 On_timer0_overflow
Enable Timer0
Enable Interrupts
Do
!NOP
Loop
End
'Timer0 Overflow Interrupt
'Wenn der Taster gedrückt wurde, dann wird der Buzzer-Pin getoggelt.
'Zwei mal toggeln entspricht einem Impuls. 488 mal toggeln gibt auf dem Buzzer
'einen Ton mit 244 Hertz ausgegeben.
On_timer0_overflow:
If Taster = 1 Then
Toggle Buzzer
Else
Buzzer = 0
End If
Return
Wie man im Beispiel sieht, kann man statt OVF0 auch das Alias TIMER0 verwenden.
Die oben gezeigten Beispiele demonstrierten schon mal das Grundprinzip aller Timer. Man kann damit zählen und beim Überlauf einen Interrupt auslösen. Man kann den aktuellen Wert des Timers aber auch auslesen und schreiben. Wenn man den Wert des Timers setzt, dann zählt der Timer ab diesem Wert nach oben. Je höher man diesen Timer0-Wert setzt, desto weniger Zeit vergeht bis zum Überlauf des Timers. Das kann man nutzen um die Frequenz genauer einzustellen.
Das folgende Beispiel demonstriert wie man den Wert des Timer0 bei jedem Überlauf (im Overflow-Interrupt) neu setzen kann. Das Beispiel soll eine Sirene darstellen. Dabei wird der Buzzer des Pollin-Evaluationsboards oder des Testboards von Roland Walter angesteuert. Bitte keinen Lautsprecher direkt anschließen. Das kann den ATmega8 zerstören.
Der Vorwahlwert für den Timer0 wird in der Mainloop in zwei For-Schleifen rauf und runter gezählt. Im Interrupt-Handler wird dieser Wert verwendet um den Timer0-Wert neu zu setzen. Bis der Interrupt-Handler ausgeführt wird, kann unterschiedlich viel Zeit vergehen, je nachdem was der µC gerade machen muss.
Weiters sichert der µC vor jedem Interrupt-Handler die AVR-Register. Das benötigt bei jedem Anspringen des Interrupt-Handlers zusätzliche 66 Ticks. Man kann sich also ausrechnen, dass der Timer0 in der Zwischenzeit -- wenn kein Prescaler eingestellt wäre -- bereits mehr als 66 Ticks hochgezählt hat. Würde man dem neuen Wert des Timer0 die bereits vergangenen Ticks nicht anrechnen, dann würde die Frequenz des Überlauf-Interrupts schwanken und zu langsam sein.
Das Setzen des neuen Timer0-Wertes braucht leider auch ein paar Ticks. Diese Ticks muss man dazuzählen wenn die Frequenz genau sein soll. Das Wort "genau" ist vielleicht ein wenig übertrieben. Mit dem Timer0 kann man nur dann eine "sehr genau einstellbare" Frequenz erzeugen, wenn man den fertigen Maschinencode analysieren kann um herauszufinden, wie viel Ticks dafür benötigt werden. Da ich es selten so genau brauche, gehe ich einfach von 9 Ticks aus (so habe ich es in einem Fachbuch gelesen). Diese Ticks zähle ich gleich beim Auslesen des aktuellen Timer0-Wertes mit dazu.
Es gilt also: Mit dem Timer0 kann man nur dann eine "sehr genau einstellbare" Frequenz erzeugen, wenn man den fertigen Maschinencode analysieren kann. Wem das zu umständlich ist, der sollte für "sehr genaue" Frequenzen den Timer1 oder Timer2 verwenden.
'Timer0 Overflow Interrupt
'Dieser Interrupt wird beim Überlauf (255 nach 0) ausgelöst
On Timer0 On_timer0_overflow
Enable Timer0
Enable Interrupts
Dim Timer0_vorwahl As Byte
Dim Current_timervalue As Byte
Do
'schnell hochzählen
For Timer0_vorwahl = 80 To 150 Step 1
Waitms 5
Next Timer0_vorwahl
'den hohen Ton etwas herausziehen
Waitms 1500
'etwas langsamer runterzählen
For Timer0_vorwahl = 150 To 80 Step -1
Waitms 30
Next Timer0_vorwahl
Loop
End
'Timer0 Overflow Interrupt - den Buzzer-Pin toggeln
'
'Zwei mal toggeln entspricht einem Impuls.
'Vorher wird der Timer auf einen Wert eingestellt, ab dem der Timer0
'nach oben zählen soll. Je höher dieser Wert, desto weniger Zeit braucht der
'Timer0 um von 255 auf 0 überzulaufen.
'Damit die in der Zwischenzeit gezählten Ticks in der Rechnung berücksichtigt werden,
'wird zuerst der aktuelle Timerwert ausgelesen und zum Vorwahlwert dazugezählt.
'Das Setzen des neuen Timer0-Wertes braucht leider auch ein paar Ticks. Es sind
'wahrscheinlich so um die 9 Ticks. Um trotzdem eine ziemlich genaue Frequenz
'zu erzeugen, werden die dafür benötigten 9 Ticks gleich mit dazugezählt.
On_timer0_overflow:
'aktuellen Stand auslesen und 9 Ticks dazuzählen
Current_timervalue = Timer0 + 9
'Timerwert neu setzen
Timer0 = Timer0_vorwahl + Current_timervalue
'Pin toggeln
Toggle Buzzer
Return
wow... ich bin in den letzten tagen auf das thema aufmerksam geworden und hab mit deiner hilfe versucht sofort losulegen, erstmal dankeund respekt! Tja und nun zu meinen Wehwehchen^^ ich war so frei und übermütig mir gleich alles zusammenzuschustern (ISP Kabel selbst gemacht, nicht den Platinenvorbau von Robotik) und den Atmega8. Ich betreibe also den "Programmer" über die Druckerschnittstelle (LPT) und mit deinem Programm (BASCOM). Wenn ich jetzt kompiliere ist soweit alles OK. Wenn ich versuche zu übertragen kommt folgende Fehlermeldung: "Could not identify Chip with ID:000000" drücke ich OK, kommt: "Selected Chip and target Chip do not match AT90S1200<->AtMega8". Natürlich ist es nciht auszuschließen, das ich irgendwo fehler gemacht habe (soviel erfahrung habe ich nciht!). Ich denke aber, dass es nciht an BASCOM oder dem LPT Anschluss liegt, denn die Spannung am Reset gegen GND liegt normal bei ca. 2,16 V , wenn ich auf übertragen klicke, sinkt kurz die Spannung auf etwa 1,6V (der wert schwankt, manchmal geht es auch nur auf 1,9V runter). Oder kann es trotzdem daran liegen??
Programmer habe ich einfach STK200/STK300 Programmer genommen, weils dort Lpt gab... und Lpt anschluss war vorausgefüllt mit 387 (habe ich so gelassen)[Port delay: 0]
Kannst du mir irgendwie helfen, "Baustellen" auszuschließen? Ich weiß ja ncihtmal, ob es am Programmer oder der Software oder dem LPT oder dem Atmega liegt
AChja: fast vergessen: gebaut ist der ISP dongle nach dem Plan bei Robotikhardware (also schon mit IC und nciht diese billigvariante mit 2 Widerständen...wäre aber zu testzwecken auch ganz gut? Wie macht man das?) und: Stromversorgung wird über das Netzteil gewärleistet, habe den 5V und GND Anschluss missbraucht
in Hoffnung,
lg
eXO
Anmeldungsdatum: 27.07.2007 Beiträge: 925 Wohnort: Oberhofen im Inntal (Tirol)
Verfasst am: Do 03.Jul 2008 10:35:40 Titel:
Hallo eXO!
eXo|Kickerxy hat folgendes geschrieben:
Wenn ich versuche zu übertragen kommt folgende Fehlermeldung: "Could not identify Chip with ID:000000"
Damit ist klar, dass Bascom den µC nicht ansprechen kann.
eXo|Kickerxy hat folgendes geschrieben:
BASCOM oder dem LPT Anschluss liegt, denn die Spannung am Reset gegen GND liegt normal bei ca. 2,16 V , wenn ich auf übertragen klicke, sinkt kurz die Spannung auf etwa 1,6V (der wert schwankt, manchmal geht es auch nur auf 1,9V runter).
Wenn du einen STK200 Programmer einsetzt, dann braucht deine Schaltung eine externe Stromversorgung. Am Reset sollten in diesem Fall 5 Volt anliegen, wenn der Programmer nicht überträgt und annähernd 0 Volt, wenn der Programmer arbeitet.
Wie man in diesem Bild sieht, muss ein 10 k Widerstand zwischen VCC und dem Reset-Pin geschaltet werden. Wenn man diesen Widerstand vergisst, dann schafft es der Progermmer nicht, den Reset-Pin nach GND zu ziehen.
eXo|Kickerxy hat folgendes geschrieben:
Programmer habe ich einfach STK200/STK300 Programmer genommen
Welchen Programmer hast du dir zusammengebaut? Ein Link wäre nicht schlecht.
mfg
Gerold
PS: Vielleicht hast du einen Anfängerfehler gemacht und VCC und GND nicht an den 74244 angeschlossen.
und: externe Stromversorgung ist ja vorhanden: ich hab an meinem Netzteil den halben Molex Stecker genommen ( den mit 5Vund gnd) und an den Atmel nach deinem Schema angeschlossen. 10k Widerstand ist auch vorhanden.
Edit: hm.. hab grad mal nachgemessen, 5V kkommen nicht wirklich aus dem NT, eher 6,67V (oder mein Messgerät ist mist, war so billig ^^)Ich habe auch mehrere Kontroll LEDs.
Die LED an MISO gegen GND z.B. leuchtet schwach, wenn Netzteil angeschlossen wird und relativ normal hell, wenn zusätzlich der lpt Stecker drinne ist, ziehe ich externe Stromversorgung heraus, leuchtet diese immernoch (fast)genauso hell.
An Reset liegen nur 3,3V an...
ach nochwas: ich habe nur einen 100nf kondensator gehabt, den an den Digitalbereich angeschlossen, der analog kommt bisher ohne aus...........
#edit ich kontrolliere alle Leitungen nochmal wie sie in dem Schaltplan (s. Link) sind und messe nach. ich melde mich heut abend nochmal mit allen ergebnissen (spätestens morgen), danke schoneinmal
lg
eXO
ps: bei manchen browsern geht der link nicht(einfach rechtsklick->ziel speichern unter..)
Was sehe ich da gerade.... soll das etwa der Anschluss an den IC sein? Wenn ja, dann passt das ja auch mit deiner Skizze,^^ und das ergibt ja auch einen Sinn.^^ Na ich messe trotzdem mal alles nach und gucke, ob etwas verlötet ist oder lose, etc,. (So eine ***Skizze )
hm ich glaub mein Messgerät hat ein Wackelkontakt... mal zeigt es bei SCK z.B. 6,75, mal 0,44V an. Dann beim Klick gings kurz azf 4,85V hoch und dann auf 0V.
Hier noch ein Paar Bilder;) Ist zwar noch kein Meisterwerk, aber das erste, wasich gelötet habe überhaupt
Atmega von oben:
von unten:
Stromversorgung:
Programmer von oben:
von unten:
lg eXO
ps: das eine Stück Hartpapier hab ich am Programmer abgebrochen, weils sonst nicht in den Lpt Kontakt gepasst hätte
pps: okay, dann wird der Atmega vllt hinüber sein, ich folge deinem Rat.
Wird dann aber bis ca. Übermorgendauern (bestellen)
#edit: Bestellung ist raus, übermorgen baue ich nochmal komplett neu auf, morgen bin ich nicht da, ich melde mich in jedem Fall,
Reset muss unter 0,2 Volt runter gehen. Ansonsten wird der µC den Reset nicht erkennen. Mögliche Fehler: Entweder du hast einen zu kleinen Widerstand am Reset-Pin, oder du hast die Reset-Leitung nicht **zwischen** Widerstand und Reset-Pin angeschlossen.
An MISO sollte, wenn dann nur ganz kurz mehr als 0 Volt anliegen. Über diese Leitung schickt der µC Daten an den Computer zurück. Aber nur dann, wenn er den Befehl dazu bekommt. Ansonsten sollte hier immer 0 Volt anliegen.
Und vielleicht legst du dir zum Testen von solchen Schaltungen ein kleines Steckbrett und eine Rolle Schaltdraht (0,22 mm²; isoliert) zu.
hm allmählich glaube ich einfach, dass mein Messgerät sehr ungenau ist... ich hab das Spannungsdings gebaut, sieht auch gut aus laut messgerät kommen da aber 6,6V raus^^ ich denke, dann passt das so. Ich baue gleich mal mit einem neuen Atmega und gucke obs diesmal geht
mfg
eXo
#edit kann es schaden zu große Kondensatoren zu nehmen=?
Die Elkos können größer sein, aber die Keramikkondensatoren am 7805 sollten schon in etwa passen. Und auch für dich gilt, für solche Arbeiten brauchst du **unbedingt** ein funktionierendes Multimeter. So ein digitales Multimeter bekommt man schon für unter 20 Euro.
ES geht! es geht wirklich!^^ ich kann es noch gar nicht glauben! Es lag am Atmega! (oder an der Konstruktion), der Programmer war in Ordnung (außer, dass nicht pin10 und 20angeschlossen waren, das hattest du ja schon bemerkt). Ja... ich hol mir ein neues Messgerät Danke vielmals für deine Hilfe so jetzt kann ich endlich bei deinen Tuts weiterlesen ich melde mich irgendwann nochmal (bzw wennich Probleme habe^^)..
Dieser Beitrag ist diesmal nicht hier im Loetstelle-Forum entstanden. Trotzdem möchte ich ihn euch nicht vorenthalten, da er für professionelle Entwicklungen ein sehr wichtiges Thema darstellt.
Es geht um den Speicher, den SRAM und die teilweise Aufteilung des SRAM in HWSTACK, SWSTACK und FRAME.
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen. Du kannst Dateien in diesem Forum nicht posten Du kannst Dateien in diesem Forum nicht herunterladen