Lied abspielen ohne Programm-Blockade

OP #5032958
Lesenswert?

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
Lesenswert?

@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
Lesenswert?

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
Lesenswert?

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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren