Musikausgabe mittels Timer
/*
* Liederausgabe aufbauend auf dem
* Democode "Tonausgabe mittels Timer"
*
* Code, um eine Tonfolge mit definierter Laenge auszugeben
* https://www.eHaJo.de
* (C) Hannes Jochriem, 2013
*/
#define F_CPU 8000000UL /* 8MHz */
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
// Prototypen
void long_delay(uint16_t);
// Defines:
#define SUMMER (1<<PD7)
// Diese Werte berechnen sich aus "8MHz / Frequenz des Tones / 2"
// Sollte ein anderer CPU-Takt verwendet werden muessen
// die Werte neu berechnet werden.
#define TON_C 15152l
#define TON_CIS 14545l
#define TON_D 13468l
#define TON_ES 12618l
#define TON_E 12121l
#define TON_F 11364l
#define TON_FIS 10899l
#define TON_G 10101l
#define TON_GIS 9479l
#define TON_A 9091l
#define TON_B 8421l
#define TON_H 8081l
#define TON_CC 7576l
#define TON_CCIS 7273l
#define TON_DD 6734l
#define TON_EES 6309l
#define TON_EE 6061l
#define TON_FF 5682l
#define TON_FFIS 5450l
#define TON_GG 5051l
#define TON_GGIS 4740l
#define TON_AA 4546l
#define TON_BB 4211l
#define TON_HH 4041l
// globale Variablen
// In diesem Array stehen die Werte fuer den CTC-Counter
uint16_t tonleiter[24] = {
TON_C, // 0
TON_CIS, // 1
TON_D, // 2
TON_ES, // 3
TON_E, // 4
TON_F, // 5
TON_FIS, // 6
TON_G, // 7
TON_GIS, // 8
TON_A, // 9
TON_B, // 10
TON_H, // 11
TON_CC, // 12
TON_CCIS, // 13
TON_DD, // 14
TON_EES, // 15
TON_EE, // 16
TON_FF, // 17
TON_FFIS, // 18
TON_GG, // 19
TON_GGIS, // 20
TON_AA, // 21
TON_BB, // 22
TON_HH // 23
};
// Melodie definieren, in diesem Fall
uint8_t melodie[38] = {
14, // Sand-
14, // mann
11, // lie-
12, // ber
14, // Sand-
14, // mann
11, // es
11, // ist
12, // noch
9, // nicht
11, // so
7, // weit!
7, // Wir
9, // sen-
11, // den
9, // erst
11, // den
7, // A-
4, // bend-
6, // ...
7, // gruß,
9, // eh
7, // ...
6, // je-
9, // des
7, // Kind
9, // ins
11, // Bett-
12, // chen
14, // muss.
11, // Du
12, // ...
9, // hast
7, // ge-
9, // wiss
4, // noch
6, // ...
7 // Zeit.
};
// Die Dauer der Noten definieren, 1 = 1/8-Note, 2 = 1/4 usw.
uint8_t dauer[38] = {2,2,1,1,2,2,2,3,1,1,1,4,2,3,1,1,1,2,1,1,4,1,1,1,1,1,1,1,1,4,1,1,1,1,2,1,1,6};
ISR(TIMER1_COMPA_vect)
{
// Summer-Pin toggeln
PORTD ^= SUMMER;
}
int main()
{
// Laufvariable
uint8_t i;
// Summer als Ausgang definieren
DDRD |= SUMMER;
// Timer1 ohne Vorteiler starten, CTC-Mode
TCCR1B |= (1<<CS10) | (1<<WGM12);
// Outputcompare-Register setzen, hier fuer ~440Hz
OCR1A = TON_C;
// Interrupt einschalten
TIMSK |= (1<<OCIE1A);
// Globales Interruptflag einschalten:
sei();
for(i = 0; i<38; i++)
{ // Fuer alle Noten im Array
// Compare-Wert entsprechend Array setzen
OCR1A = tonleiter[melodie[i]];
// Warten damit die Note klingen kann...
long_delay(dauer[i]*300); // *300 klingt ganz gut bei dem Lied
// Timer kurz aus- und wieder einschalten damit gleiche Noten
// hintereinander unterschieden werden koennen
TCCR1B = 0;
long_delay(2);
TCCR1B |= (1<<CS10) | (1<<WGM12);
}
// Lied Ende, Timer ausschalten:
TCCR1B = 0;
while(1)
{
// nix...
}
return 0;
}
void long_delay(uint16_t ms)
{
for(; ms>0; ms--)
_delay_ms(1);
}
Keine Kommentare