Lied abspielen ohne Programm-Blockade

OP #5032958
Hallo zusammen

Ich möchte an meinem Signalgeber eine Melodie ausgeben. Das Ganze sieht 
etwa so aus:
1
void buzzer_play_tone(double frequenzy, uint8_t intervall)
2
{
3
  // Start the Timer1 with prescaler of 1024
4
  TCCR1B |= (1<<CS12) | (1<<CS10);
5
  uint16_t tone = 0;
6
  // Get the tone duration in micro seconds
7
  tone = 1000000/frequenzy;
8
  while(global_tone_duration<intervall)
9
  {
10
    OUTPUT_BUZZER |= 0x80;
11
    delay_us(tone);
12
    OUTPUT_BUZZER &= ~0x80;
13
    delay_us(tone);
14
  }
15
  // Stop the Timer1 
16
  TCCR1B &= ~((1<<CS12) | (1<<CS10));
17
  // Set back the tone duration, so that next tone is possible
18
  global_tone_duration = 0;
19
}
20

21
void buzzer_play_song(void)
22
{
23
  buzzer_play_tone(A7,VIERTEL_NOTE);
24
  buzzer_play_tone(E7,ACHTEL_NOTE);
25
  buzzer_play_tone(F7,ACHTEL_NOTE);
26
  buzzer_play_tone(G7,ACHTEL_NOTE);
27
}

Die ganze Tonausgabe funktioniert problemlos.

Jedoch blockiert mir die Funktion den restlichen Programmcode, so dass 
ich nichts mehr machen kann, vor allem wenn das Lied länger wird.

Meine Frage: Wie muss ich es implementieren, so dass bei jedem 
Funktionsaufruf nur ein Ton gespielt wird. Ich möchte jedoch nicht 20 
if-Abfragen mit einem Zähler. Gibt es mit Arrays eine Möglichkeit oder 
sonst irgendwas, so dass das Programm überschaubar bleibt?

MfG
#5033001
@TM FW (p_richner)

>Ich möchte an meinem Signalgeber eine Melodie ausgeben. Das Ganze sieht
>etwa so aus:

Dann gehört dein Beitrag aber nicht ins Unterforum Projekte & Code, dort 
gehören nur halbwegs getestete Projekte rein und keine Fragen.

>Jedoch blockiert mir die Funktion den restlichen Programmcode, so dass
>ich nichts mehr machen kann, vor allem wenn das Lied länger wird.

Logisch.

>Meine Frage: Wie muss ich es implementieren, so dass bei jedem
>Funktionsaufruf nur ein Ton gespielt wird. Ich möchte jedoch nicht 20
>if-Abfragen mit einem Zähler. Gibt es mit Arrays eine Möglichkeit oder
>sonst irgendwas, so dass das Programm überschaubar bleibt?

Sicher. Und wie schon gesagt gibt es Timer-Interrupts, damit 
wird deine CPU nicht blockiert. Siehe auch Multitasking.
#5033727
Speziell zur Tonausgabe bieten sich die PWM-Ausgänge Deines unbekannten 
AVRs geradezu an. Schau doch einfach mal ins Datenblatt.

TM F. schrieb:
> Ich möchte jedoch nicht 20
> if-Abfragen mit einem Zähler.

if/else Ketten sind extrem unleserlich, für sowas nimmt man switch/case.

TM F. schrieb:
> Gibt es mit Arrays eine Möglichkeit

Natürlich. Schreibe in ein Array die Tonhöhe und Dauer als Liste und 
setze einen Pointer darauf.
#5035112
Wenn Du nicht selber einen Scheduler programmieren willst und Dich mit 
Timerrinterrupts quälen, kannst Du sowas auch rel. simpel mit einem 
Realtime Betriebssystem lösen. z.B. FreeRTOS.
Die Einarbeitungszeit ist natürlich auch nicht ganz unerheblich, aber 
das ganze ist dann sehr flexibel in der Anwendung.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.