Hallo Freunde, ich möchte für den Aufbau eines Variometers verschiedene Töne (300, 400, 600,800,1000,1200,1600Hz) mit dem ATtiny13 über das Register Compare OCR0B im Togglemodus erzeugen. Mit der Konfig in der Anlage habe ich bisher nach dem Einschalten der ersten Tonausgabe keinen Erfolg bei der Umschaltung auf eine andere Frequenz. Die erste Frequenz bleibt erhalten. da ich mit dem AVR Studio nicht über ein STK-Board verfüge, kann ich nicht richtig debuggen. Deshalb läuft parallel bei der Freqenzänderung zur Kontrolle eine LED auf PB2 mit. Diese wird immer bei der Tonänderung über eine zwischengelegte Zeitschleife (ca. 1Sek.) geschaltet. Die LED blinkt korrekt. In diesem ersten Versuchsaufbau läuft alles ohne Interrupts. Später soll über das zweite Register OCR0A alle 5 Millisekunden ein Interrupt für eine andere Routine ausgelöst werden. Zur Programmierung benutze ich einen selbstgebauten Parallelportadapter und PonyProg. Die Einstellungen der Fuse-Bits sind außer SUT0 und CSEL1 alle deaktiviert. Der Takt liegt bei 4,8MHz/Vorteiler-64 .Die Programmierung erfolgt problemlos. An diesem Problem sitze ich nun schon einige Tage. Nun wende ich mich an euch in der Hoffnung, es kann mir einer meinen Fehler aufzeigen. Vielen Dank im Voraus.
Du hast keinen Stack angelegt. Verkraftet der Attiny13 dann Aufrufe des Unterprogramms zeit oder schmiert der dann ab? http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack
Krapao schrieb: > Du hast keinen Stack angelegt. Der Tiny13 initialisiert seinen Stackpointer beim Reset selbst. Das ist es also nicht. Jörg T. schrieb: > in der Hoffnung, es kann mir einer meinen Fehler aufzeigen. Hmmm, der erste Fehler ist, dass Dein Programm nur sehr schlecht lesbar ist. Dabei meine ich einerseits die unmöglich flatternden Einrückungen und Tabs, andererseits das konsequente Nichtverwenden der vereinbarten Namen der I/O-Register und deren Bits. Da ich keine Lust verspüre, mittels Datenblatt anhand der (kryptischen) Registeradressen die (verstehbaren) Registernamen zu ermitteln, kann ich zum Programmaufbau nichts weiter sagen. ...
Ja, danke für den Tip, aber erstens steht der Stack von Haus aus auf dem RAM-Ende, zweitens ist es im Studio nachvollziehbar und drittens blinkt die LED zwischen den Aufrufen des Unterprogramms schön im Sekundentakt. Ich meine, dann sollte es nicht daran liegen. Zur Sicherheit habe ich es mit der Festlegung des Stacks getestet - aber mit dem gleichen Ergebnis. :-(
> ldi r16, 0x7f ; Oszillator 7F > out 0x31, r16 Die 0x31 sind IMHO fragwürdig. Lt. Datenblatt ist das das OSCCAL Register. Ich würde dort das CLKPR Register nehmen. Und statt mit absoluten Werten mit den symbolischen Namen programmieren. Dafür sind die da.
Hallo, danke für den Hinweis zur Formatierung. Ich habe den Code noch einmal überarbeitet.
Hi Wie soll sich die Frequenz ändern? Der Timer läuft im Normalmode. Also immer schön von 0 bis 255 und dann wieder von vorn. Du bestimmst nur die Stelle., an der umgeschaltet wird, nicht die Frequenz. Dafür musst du den CTC-Mode nehmen. Geht aber nur mit OCRA. >danke für den Hinweis zur Formatierung. Dazu gehört auch die Entfernung von Tabs. Die haben in einem Quelltext nichts zu suchen. So etwas: >ldi r16, 0x10 >out TCCR0A, r16 ist praktisch unleserlich. Benutze ldi r16, 1<<COM0B0 MfG Spess
Erstmal danke für die komplette Überarbeitung. Ich muss gestehen, es ist wesentlicher übersichtlicher. Um die 4,8MHz als Systemtakt zu bekommen, habe ich angenommen, dass es reicht, die Fuse-Bits CSEL1 und CSEL0 festzulegen und nicht noch über den Vorteiler im Register CLKPR - ok. Weiterhin hast du den CTC Mode aktiviert und setzt vor der nächsten Tonausgabe im Register TCNT0 alles zurück - ok. Habe alles umgesetzt, aber keinen Erfolg. Die LED blinkt im Sekundenrhythmus. Der Lautsprecher an PB1 tickt nur im gleichen Takt der Ausgabe, aber ohne Ton. An sich ist alles verständlich und logisch, aber wo geht es hier schief ?
Krapao schrieb: > Mit dem Programm in Anhang würde ich dann mal testen. Hallo Krapao, erst einmal danke für die komplette Überarbeitung. Ich muss gestehen, es ist wesentlicher übersichtlicher. Um die 4,8MHz als Systemtakt zu bekommen, habe ich angenommen, dass es reicht, die Fuse-Bits CSEL1 und CSEL0 festzulegen und nicht noch über den Vorteiler im Register CLKPR - ok. Weiterhin hast du den CTC Mode für aktiviert und setzt vor der nächsten Tonausgabe im Register TCNT0 alles zurück - ok. Habe alles umgesetzt, aber ohne Erfolg. Die LED blinkt im Sekundenrhythmus. Der Lautsprecher an PB1 tickt nur im gleichen Takt der Ausgabe, aber ohne Ton. Ist es mit dem OCRB nicht möglich? Gruß Jörg
Beachte was Spess schrieb:
> den CTC-Mode nehmen. Geht aber nur mit OCRA.
CTC ist schon da, aber noch auf OC0B ausgelegt. Der Kommentar in ldi
r16, (1<<WGM01)|(1<<COM0B0) bzgl. PB0 ist falsch. Umschreiben auf OC0A
ist aber einfach.
Jörg T. schrieb: > Um die 4,8MHz als Systemtakt zu bekommen, habe ich angenommen, dass es > reicht, die Fuse-Bits CSEL1 und CSEL0 festzulegen und nicht noch über > den Vorteiler im Register CLKPR - ok. Es gibt keinen Grund, deswegen die Fuses zu verändern. Lass doch den Systemtakt auf 9M6 und ändere nur per Software den Taktvorteiler CLKPR auf 1 zu 2 (erst Schreibschutz aufheben, dann zweimal Wert schreiben). Dann läuft Dein Programm auch auf jedem jungfräulichen Tiny13, ohne dass man die Fuses verändern muss.
1 | ldi wl,1<<clkpce ;Schreibschutz-Bit Systemvorteiler |
2 | ldi wh,1 ;neuer Wert für Systemvorteiler für 4,8 MHz |
3 | out clkpr,wl ;Schreibschutz Systemvorteiler aufheben |
4 | out clkpr,wh ;Controllertakt auf |
5 | out clkpr,wh ;4,8MHz umschalten |
6 | nop ;Zeit zum Einschwingen geben |
Erspart allerhand Stress... ...
Danke euch, nun muss ich erst die Hardwareänderung PB1/PB0 wegen OC0B/OC0A Wechsel durchführen => morgen. Dann melde ich mich mit dem Ergebnis. Gruß Jörg
Jörg T. schrieb: > Aufbau eines Variometers Du doktorst momentan daran herum, mit dem einzigen vorhandenen Timer die Tonerzeugung zu realisieren. Dabei möchtest Du den Pin in Hardware toggeln, wozu Du den Timer im Zählumfang begrenzen musst und ihn (trotz einer zweiten Compare-Spur) nicht mehr für andere Zwecke nutzen kannst. Du willst aber keinen Piepser bauen, sondern ein Variometer. Das heißt, dass Du vermutlich noch andere Ressourcen brauchen wirst und die alleinige Nutzung des einzigen Timers für die Tonerzeugung Ressourcenverschwendung ist. Deshalb solltest Du darüber nachdenken, wie Du den Timer für mehrere Dinge parallel einsetzen kannst. Siehe weiter unten... Du initialisierst den Timer für 75 kHz Eingangstakt. Obere und untere zu erzeugende Ton-Frequenz sind 300 Hz und 1600 Hz. Da die Umschaltung zweimal per Periode (also bei jeder Halbwelle) erfolgen muss, brauchst Du Intervalle für 600 Hz bis 3200 Hz. Das entspricht 125 Tähltakte für 600 (300) Hz und 23 (23,4) Zähltakte für 1600 (3200) Hz. Bessere Auflösung erhältst Du aber, wenn Du den Timer mit 150 kHz klappern lässt (9,6 MHz, Vorteiler 64), dann hast Du den Zählerstand 250 für 300 Hz (600 Pegelwechsel) und 47 (46,8) für 1600 Hz (3200 Pegelwechsel). Zwischen den Pegelwechseln der höchsten Frequenz vergehen 3000 CPU-Takte. Das ist eine Menge Rechenzeit, die erlaubt es Dir, den Tonausgabe-Pin in Software (im Interrupt) zu toggeln. Damit hast Du die zweite Compare-Spur und auch den Überlauf-Interrupt für weitere Dinge frei. Der Timer müsste also frei durchlaufen (ohne CTC). Im Interrupt der Tonausgabe müsste Folgendes passieren: - SREG sichern - Pin toggeln - OCR-Register einlesen - zur Frequenz gehörendes Intervall aufaddieren - Summe als neuen Interrupt-Termin ins OCR-Register schreiben - SREG wiederherstellen Das kostet Dich ein (unteres) Exklusivregister für die SREG-Kopie, ein nur in ISRs verwendetes Tempregister (zum Lesen und Ändern des OCR-Wertes) und das (auch vom Hauptprogramm benutzte) Register mit dem Intervall, also insgesamt 3 Register. Und natürlich 7 Takte (plus etwa 10 Takte für Int-Auslösung, Aufruf und Rücksprung) in der ISR. Also etwa 17 von 3000+ CPU-Takten. Das Hauptprogramm ändert dann bei Bedarf das Intervall zur Tonerzeugung, die ISR addiert dieses Intervall auf den Termin des aktuellen Interrupts auf und setzt den Termin des nächsten Interrupts. Mit dem Überlauf-Interrupt (~586 Hz) und einem Software-Nachteiler kannst Du Deinen angestrebten Takt von etwa 5..10 ms erreichen und hast immer noch die zweite Compare-Spur für weitere Aufgaben frei. In der Überlauf-ISR (alle 16384 CPU-Takte) kümmerst Du Dich nur um die Registersicherung und den Nachteiler. Wenn Du in der Mainloop lange Routinen vermeidest (also innerhalb der 16k CPU-Takte bis zum nächsten Überlauf-Int garantiert alle Jobs fertig hast), kannst Du den Nachteiler in der Mainloop auf Unterlauf prüfen und wieder auf Startwert setzen. Dies hält die Überlauf-ISR kurz (und schnell) und vermindert die Verzögerung anderer Interrupts. Du hast Schreibzugriff auf OSCCAL, willst also den internen Oszillator kalibrieren, und das auch noch mit einer im Quelltext festgelegten Konstante. Das ist beim Tiny13 Unsinn, denn der Tiny13 wird beim Reset in Hardware kalibriert. Beim Tiny12 und Tiny15 war das noch nötig, aber da gab es bessere Mittel als die Angabe des Calibrationsbytes im Quelltext. Um weitere Tipps geben zu können, wäre es hilfreich, wenn Du erstmal Dein Konzept erklären würdest. Also - welche Sensoren sollen eingesetzt werden? - wie sollen diese ausgewertet werden? - wie erfolgt die Zuweisung der Tonfrequenzen? Du solltest also erstmal alle Dinge auflisten, die Dein Programm später mal tun soll. Denn nur so können die knappen Ressourcen richtig verteilt werden. Noch ein Tip (einige Leute sehen das aber anders): Suche doch mal im Menü des AVR-Studios den Punkt, wo Du dem Editor sagen kannst, er möge Tabs durch Spaces ersetzen. Denn dann wird Dein Quelltext auch von Texteditorn und Browsern korrekt formatiert angezeigt. Ich hänge Dir mal ein ASM-Programm für den Tiny13 an, nur mal so zum Vergleich, wie lesbar man ein ASM-Programm schreiben und formatieren kann. Und nein, das ist nicht das Nonplusultra, ich bin kein Profi, ich bin auch nur ein Bastler, der hobbymäßig programmiert und das als Autodidakt gelernt hat. ...
Krapao schrieb: > Beachte was Spess schrieb: >> den CTC-Mode nehmen. Geht aber nur mit OCRA. > > CTC ist schon da, aber noch auf OC0B ausgelegt. Der Kommentar in ldi > r16, (1<<WGM01)|(1<<COM0B0) bzgl. PB0 ist falsch. Umschreiben auf OC0A > ist aber einfach. Hallo zusammen, nachdem ich die "vario.asm" von Hannes (Nochmals danke!) als Basis meiner weiteren Versuche von OCR0B auf OCR0A verändert habe, arbeitet der Timer im Compare Match A Mode laut AVR Stdio korrekt. Danach erfolgt aber lediglich eine Zustandsänderung (Toggle) am PB0 im Register 16 "INPUT Port B " und nicht am PB0 im PORTB-Register. Hardwaremäßig tut sich am Pin 5 auch nichts.
Hannes Lux schrieb: >> Aufbau eines Variometers Hallo Hannes, die Idee basiert auf einem Artikel unter: http://www.elektor.de/jahrgang/2007/juni/funk-variometer.91946.lynkx?tab=4 Da ich begeisteter Modellflieger bin und ich vor ca. 25 Jahren mit Assembler für Zilog80 zu tun hatte, wollte ich das Thema Variometer auf Basis eines µC für mich nutzbar machen, ohne teure fertige Geräte kaufen zu müssen/wollen. Da der Artikel schon vor einigen Jahren entstand und alles auf dem ATtiny15 basiert, wollte ich das Ganze auf den ATtiny13 portieren. Hierbei würde auch das Thema mit der langsamen EEPROM Programmierung wegfallen und dafür die RAM-Nutzung möglich sein. Im ersten Ansatz bin ich auf die Redaktion zugegangen, um an den Quellcode des Autors zugelangen, aber ohne Erfolg. Dann habe ich mir den Hexcode reassembliert und versuche nun "von hinten durch die Schulter" den vorhandenen Code zu nutzen und die erforderlichen Anpassungen (Port/Pins/Wegfall EEPROM/Nutzung RAM/Initialisierungsänderungen) umzusetzen. Da es sich bei der Variante mit dem ATtiny15 um eine fertige Lösung (Kernthema-Vario) handelte, wollte ich im ersten Ansatz nicht zuviel auf den Kopf stellen.
Hi >Da der Artikel schon vor einigen Jahren entstand und >alles auf dem ATtiny15 basiert, wollte ich das Ganze auf den ATtiny13 >portieren. Warum hast du dann den ATTiny13 und nicht einen der 'Nachfolger' des ATTiny15, einen ATTiny25/45/86 genommen? MfG Spess
spess53 schrieb: > Warum hast du dann den ATTiny13 und nicht einen der 'Nachfolger' des > ATTiny15, einen ATTiny25/45/86 genommen? Weil ich das gerade erst erfahren habe ...
Ich habe leider keinen Attiny13 für den Hardwaretest da. Deshalb habe ich das Programm aus Beitrag "Re: ATtiny13 Problem mit Tonerzeugung" auf den Attiny2313 (8 MHz auf dem Pollin Funk AVR Board) angepasst. Die Änderungen waren OC0A liegt dort auf PB2, die LED auf PD5 und statt 4800000 sind 4000000 bei der Berechnung einzutragen. Damit messe ich 312 Hz und 434 Hz mit dem Frequenzzähler(!). Es macht keinen Unterschied, ob ich CLKPR wie in vario.asm verwende oder so wie Hannes vorschlägt. Wobei ich zugeben muss, mein Codestück ist ein Schnellschuß nach Datenblatt. Hannes bringt Erfahrungen aus der Praxis rein, so dass ich im Prototypen eher dessen Variante nehmen würde. Wie sieht deine Schaltung beim Abgriff des Signals aus? Belastest du den Ausgang vielleicht so stark, dass der in die Knie geht?
Krapao schrieb: > Wie sieht deine Schaltung beim Abgriff des Signals aus? Belastest du den > Ausgang vielleicht so stark, dass der in die Knie geht? ... da habe ich doch noch einen Schreck bekommen, wegen der evtl. weichen Knie ... für den kleinen ATtiny13 - bin noch schnell in die Werkstatt und kontrolliert. Am Ausgang PB0 hängt ein hochohmiger Piezo, also alles hochohmig. Zur Kontrolle habe ich alles abgenommen und die Frequenz gemessen = 0 ! Ausgang auf Low. Parallel habe ich den Compare Match A auf den Interrupt gelegt und toggle über eine Routine den Ausgang PB1 mit der gleichen Frequenz. Funktioniert, war aber nicht das Ziel. Anbei die vario.asm mit dem Interrupt.
Jörg T. schrieb: > nachdem ich die "vario.asm" von Hannes (Nochmals danke!) als Basis > meiner weiteren Versuche von OCR0B auf OCR0A verändert habe, Sorry, ist nicht von mir... Jörg T. schrieb: > Da der Artikel schon vor einigen Jahren entstand und > alles auf dem ATtiny15 basiert, wollte ich das Ganze auf den ATtiny13 > portieren. Das ist keine gute Idee, der Tiny15 ist mit 2 Timern ausgestattet, der Tiny13 nur mit einem Timer, der allerdings ein paar Funktionen mehr hat, aber auch eine weniger (PLL). Beide Controller sind also nur bedingt kompatibel. Der Nachfolger des Tiny15 ist (wie Spess schon schrieb) der Tiny25/45/84. Der hat sogar einen Kompatiblitätsmodus. Jörg T. schrieb: > um an den Quellcode > des Autors zugelangen, aber ohne Erfolg. Hast Du bei ELV was Anderes erwartet? Die müssen ihre Quellcodes geheim halten um sich nicht zu blamieren. Jörg T. schrieb: > Dann habe ich mir den Hexcode reassembliert und versuche nun "von hinten > durch die Schulter" den vorhandenen Code zu nutzen Auch das ist keine gute Idee. Analysiere lieber, was das Gerät genau machen soll und schreibe den Code dazu völlig neu. Das ist wesentlich einfacher und weniger fehlerträchtig. Und Du schaffst damit was Eigenes, musst Dir nicht den Vorwurf des Abkupferns gefallen lassen. Jörg T. schrieb: > auf den Interrupt gelegt und toggle über eine Routine den > Ausgang PB1 mit der gleichen Frequenz. Hättest vorher mal ins Datenblatt des Tiny13 sehen sollen, Kapitel I/O-Ports auf Seite 43, da steht z.B.:
1 | However, writing a logic one to a bit in the PINx Register, will |
2 | result in a toggle in the corresponding bit in the Data Register. |
Als ISR hätte demnach Folgendes gereicht:
1 | compa: ; Interrupt Timer/Counter Compare Match A |
2 | sbi pinb,pb1 |
3 | reti |
In Deiner ISR fehlt auch noch die Sicherung und Wiederherstellung des SREG. Somit kann sich das Hauptprogramm verarschen, weil die ISR die Flags verändert. Wenn der Interrupt zwischen Flagbeeinflussung und bedingtem Sprung zuschlägt, dann stimmen ja die Flags, auf deren Zustand hin verzweigt wird, nicht mehr. Achja, den Stackpointer brauchst Du beim Tiny13 nicht initialisieren, das macht der beim Reset in Hardware. Mehr habe ich jetzt nicht analysiert, denn mit dem Warteschleifenkonzept kommst Du nicht weit, da Du die Rechenzeit anderweitig nötiger brauchst als zum Zählen von Takten. Du solltest Dir den Text oben noch mal durchlesen: Beitrag "Re: ATtiny13 Problem mit Tonerzeugung" ...
Hannes Lux schrieb: > Mehr habe ich jetzt nicht analysiert, denn mit dem Warteschleifenkonzept > kommst Du nicht weit, da Du die Rechenzeit anderweitig nötiger brauchst > als zum Zählen von Takten. Du solltest Dir den Text oben noch mal > durchlesen: Beitrag "Re: ATtiny13 Problem mit Tonerzeugung" Das Ganze mit der Warteschleife war als Test gedacht, um zwei unterschiedliche Töne im Wechsel auf einem Oszillographen bzw. Frequenzzähler beurteilen zu können, da ja bis jetzt der Togglemode über OCR0A ohne Interupt noch nicht funktioniert. Dein Vorschlag, die Zeiten zwischen den Umschaltungen zu nutzen, ist schon ok. Mich würde trotzdem die Lösung für das eigentliche Problem im Togglemode interessieren.
Hallo Jörg, Ich habe jetzt nicht so 100%ig verstanden, um was es geht. Scheinbar möchtest Du einen Ton mit dem Timer im 'Pin-Toggle-Mode' erzeugen. Der Timer ist dann allerdings für die Piepszeit belegt. Im Anhang eine Tonleiter, nach Deinem Programm und Frequenzrechnung bei mir piepts ;-) Falls der Interrupt das Problem ist: compa: in r02,sreg; <----- cpi r20, 0xff brne com1 cbi PORTB, PB1 ; Piezo an PB1 aus rjmp com2 com1: sbi PORTB, PB1 ; Piezo an PB1 ein com2: com r20 out sreg,R02 ; <----- reti Auf jeden Fall das Statusregister sichern herrmueller
Geht übrigens auch mit PB1 ldi r16, (1<<WGM01)|(1<<COM0B0) ; Toggle OC0B (PB1) on Compare Match (CTC Mode) herrmueller
Hallo zusammen, jetzt piept´s ... endlich. Mit oder ohne Interupt. Danke an alle, die mit Geduld beim Laufen lernen geholfen haben. :-)
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.