Hallo Leute, ich bin neu hier und Student. Hab ein Projekt bekommen, einen Meldodiegenerator zu machen. Habe ein Minimexle baord (www.minimexle.de) mit einem ATmega88 und 4 Tastern, Lcd Display 16 zeichen 2 zeilen monochrom, einen ntc, lichtdiode, led und nen buzzer. Nun wollte ich erst mal zum einsteigen anfangen ein Programm zu schreiben mit Hilfe eines Interrupts(oder Timer) womit ich mit 2 Tasten die Led schneller Blinken lassen kann und langsamer. Das möchte ich dann auf den Buzzer erweitern. Danach möchte ich mich mit Arras und Struckturen anfreunden, dh. die 8 Lieder(Noten alle) in ein struct legen und dann für jedes Lied mit Pointern drauf zugreifen. Je nach Lied brauch ich dann auch nen andern Timer für die Geschwindigkeit. Dann möchte ich ein einfaches Menü zu machen also Titel in der oberen Zeile im Display, unten ei Lied rauf/runter und Play/Stop eventuell mit play/stop(beide gedrückt, oder einfach play nochmals lang drücken) Pause Modus. Nun alles schön und gut, bestimmt einfach realisierbar, aber ich bin anfänger, ne absolute Null, Displayausgabe, Taster einlesen, Led-ausgabe krieg ich noch hin, interrupt (blinken einer led) haben wir mal gemacht. Also nur mal ein ansatz wie ich den Tei mim LED (schneller/langsamer) blinken Buzzer höher tiefer stellen. Ein Programmteil oder Ansatz würde mir sehr helfen, bin seit Tagen dran des mit dem Interrupt zu verstehen, wie ich den schneller langsamer mach, für die anwendungen und wie ich die verschiedenen sachen ausgeb an den Buzzer, mit 256 werten? (Char?) Keine Ahnung. Danke für eure Hilfe lg Paul
Hi, dazu kann ich dir das AVR-Tutorial und das AVR-GCC-Tutorial an's Herz legen. Da ist die Interrupt-Geschichte und das ganze Timer-Zeug recht gut erklärt. Aber im Grunde brauchst du etwa Folgendes: Einen Timer-Interrupt, sinnvollerweise von der Compare-Unit (ISR(TIMER_COMPA_vect) oder so) um das eigentliche Blinken zu erzeugen, sowie eine Schleife, in der du deine Taster abfragst. In der Schleife brauchst du dann eine Entprellung, um die Flanken ohne viel Müll zu erkennen. Bei jeder Flanke der entsprechenden Taste verstellst du dann dein OCR (OCR0A z.B. für die Output-Compare-Unit A an Timer0).
Für die Erzeugung eines Tons oder ein Blinken braucht's keinen Interrupt, ein Timer reicht, der einen OCx Pin toggelt. Um ein Signal auf den Pin OC1A (PB1) zu bekommen, musst Du folgende Register konfigurieren: TCCR1A, TCCR1B, TIMSK1 Wähle den CTC Modus und lass' den Port OC1A togglen, dann kannst Du mit dem Register OCR1A die Blink- oder Tonfrequenz einstellen. Nur wenn sich etwas ändert soll, z.B. um die Tonlänge in einer Melodie zu steuern, würde sich ein Timerinterrupt anbieten.
Um diesen Besagten Pin zu toggeln, geht das auch mit dem Timer 0? Oder geht das nur mit dem Timer 1? Muss ich dann den Pin(PB1) zu meinem Ausgabepin(Buzzer PD5) rüberschleifen? Oder kann ich direkt OC0B toggeln? Also mit Timer 0. Und wie genau kann ich den Ton dann mit dem Register OCR1A einstellen? Danke für Hinweise, (soll übrigens Töne und Tonlänge ohne interrupts machen). Tonlänge = <util/delay.h> Ton selber = Timer Compare?ohne Interrupt?
Hallo Paul, hier mal eine Anregung für solch einen Melodien-Generator. Ist zwar für einen 8051er geschrieben, dafür aber in C und die Tonhöhe und Tondauer werden ohne Interrupts erzeugt: die Tonhöhe durch Ausgabe einer entsprechenden Frequenz, mit einem Timer im Überlauf erzeugt und die Tondauer durch eine delay- bzw. wait-Funktion. Als Kern hast Du einfach eine kleine Funktion, an die der gewünschte Ton und die Dauer übergeben wird und dann brummts. Viel Spaß dabei Sound_Maker
@Paul, Timer 0 sollte auch gehen um einen Pin zu toggeln, nur ist Timer 0 ein 8 Bit Timer und damit lassen sich die Frequenzen für die entsprechenden Noten nicht genau genug erzeugen. Musst Dir mal die erzeugbaren Frequenzen ausrechnen, um zu sehen ob das trotzdem reicht. Der Portpin für Timer 1 ist in Hardware festgelegt und muss mit dem Buzzer verbunden werden, falls Timer 1 verwendet werden soll. Wenn der Buzzer bereits mit PD5 verbunden ist, dann kannst Du PD5 als Eingang definieren, den PB1/PB2 draufschalten, oder den Buzzer auftrennen und auf PB1/PB2 legen. Ich würde Letzteres machen, da sicherer. Aber vielleicht geht auch Timer 0 für Dich, dann kannst Du Dir das Rumgelöte sparen. Das Beispiel von Sound_Maker ist m.E. nur bedingt brauchbar für Dich, denn der Mega88 hat keinen Preload per Hardware, aber einen CTC Mode. Das ist aber etwas im Prinzip Ähnliches. Der CTC funktioniert so, daß der Zähler bis zum Wert des entsprechenden OCRx Registers zählt und dann wieder von 0 anfängt. Wenn man ihn bei 0 noch den entsprechenden Portpin toggeln lässt, dann bekommt man so eine einstellbare Ausgangsfrequenz. Weil getoggelt wird, ist die Ausgangsfrequenz 1/2 der CTC Frequenz. Konsultier das Mega88 Datenblatt damit Du siehst, wie Prescaler, CTC, Toggle Modi und ORCx eingestellt werden, bzw. Einfluss auf die Frequenz haben. Falls Du nicht klar kommst, melde Dich wieder.
Danke für die Tipps, hab jetzt so gemacht, dss der Timer0 im CTC Mode(Prescaler 256) mit OCR0A variabel zählt(je nach frequenz) und OCR0B fest auf 2 steht, somit den PD5 (Buzzer) immer toggelt(eingestellt durch COMB0 Modus). Töne hab ich mim Kollegen(Musiker) am Keyboard nach gehör genau eingstellt. 1,5 Oktaven und schon 4 lieder geschrieben. Jetzt hab ich heut den Timer1 (16bit) eingestellt auch CTC aber Interrupt, und mit 1024 Prescaler und gleich auf die kleinste ms anzahl gestellt, also dass interruptservice routine alle 35ms kommt. Jetzt muss ich nur noch die Lieder in arrays schreiben in der ISR(Timer1) auslesen lassen mit ner variablen, die dann immer eins erhöht wird nach (35ms, je nach ton -variabel). und dann teil1(displaymenü) 14% bei jetztigen strings (Lied 1 bis Lied 8) und Teil 2 (lieder 4) mit 25% mit tastern und teil 3 (fast fertig, noch ISR und co.) zu vereinen. Und dann theoretisch.... solltes gehn;) Dh. noch die 4 restlichen Lieder programmiern, und erst mal in arrays einlesen;) Danke für eure Hilfe ich meld mich wenns probz gibt oder wenns mal funktioniert;) lg Paul
PS: Ich habs jetzt fast soweit, wer interesse hat kann sich melden, und ich poste dann hier meinen code;) Ein Problem hatte ich noch bei auslesen eines 2 dim. arrays mit tonhöhe(timer0) und tonlänge(timer1, der gleichzeitig ISR macht, worin ausgelesen wird). Und zwar: Ich mache play/ stop mit sei(); und cli(); set und clear interrupt, mit paar geeigneten einstallungen dazu hats auch funktioniert, aber wenn ich mal auf play drücke, dauert es zb 3sec. bis er das lied abspielt, manchmal und manchmal gehts. Ebenso wenn ich mal mittem im lied stop mache oder bei mehrmaligen wiederholten abspielen spielt er den ersten ton zu lang ab, länger als im array steht(keine delay funkt. dazwischen, habe schon geschaut.) Danke für hilfe lg Paul
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.