Tonerzeugung mit der Licht-Klangkugel
(EN google-translate)
(PL google-translate)
Zum besseren Verständnis der Tonerzeugung werden nun ausgehend von einem sehr einfachen Programm immer aufwändigere Programme zur Toerzeugung entwickelt.
Die Quelltexte der folgenden Programm sind nicht bei SNIPPETS_KLANGKUGEL mit dabei, sondern können hier nachfalgend heruntergeladen werden:
ton001 - Ansteuerung über den digitalen Ausgang PD6
#include<avr/io.h> #include<avr/interrupt.h> void init() { DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; //Für Ton PD6 als digitalen Ausgang setzen, PD7 als digitalen Eingang: DDRD |= 0b01000000; } int main(void) { unsigned char ton_ein = 0; unsigned long pause=0; init(); while(1) { for(pause=0;pause<400;pause++) DDRC=0; PORTD|=0b01000000; for(pause=0;pause<400;pause++) DDRC=0; PORTD&=0b10111111; }//Ende while(1) }
Code 0-1: Quelltext von ton001.
Es entsteht ein tiefer Ton mit konstanter Lautstärke, da ein Rechtecksignal auf PD6 ausgegeben wird. Um eine definierte Tonhöhe festlegen zu können, wird nun der Timer 0 eingesetzt. Beim folgenden Programm ton002 wird ein Ton von exakt 1000Hz erzeugt.
#include<avr/io.h> #include<avr/interrupt.h> void init() { DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; //Für Ton PD6 als digitalen Ausgang setzen, PD7 als digitalen Eingang: DDRD |= 0b01000000; //Zeitbasis mit Timer0: //Vorteilung 8, Obere Zählgrenze 125 => 1000000Hz/(8*125)= 1000Hz für einen Zählzyklus TCCR0 = (0<<FOC0) | (0<<WGM00) | (0<<COM01) | (0<<COM00) | (1<<WGM01) | (0<<CS02) | (1<<CS01) | (0<<CS00); OCR0=125; } int main(void) { init(); while(1) { if(TCNT0<62) PORTD|=0b01000000; else PORTD&=0b10111111; }//Ende while(1) }
Code 0-2: Quelltext von ton002.
Über ein PWM-Signal auf PD7 / OC2 kann dem Ton eine Hüllkurve verliehen werden und so ein lebendigerer Klang erzeugt werden. Dies wird durch die besondere Verschaltung zwischen PD6, PD7 und dem Lautsprecher ermöglicht. In der nachfolgenden Schaltung ist der beteiligte Ausschnitt der Elektronik dargestellt.
Bild 0-1: Anschluß des Lautsprechers bei der Licht- Klangkugel.
In folgendem Programm wird für jeden Ton über den Wert von OCR2 eine Hüllkurve erzeugt. Der entsprechende Ton klingt so, als würde er angeschlagen und dann verklingen. Über die Variable obergrenze wird zudem die Tonhöhe nach jedem "Anschlagen" verändert.
#include<avr/io.h> #include<avr/interrupt.h> void init() { DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; //Für Ton PD6 und PD7 als digitalen Ausgang setzen: DDRD |= 0b11000000; //Zeitbasis mit Timer0: //Vorteilung 64, Obere Zählgrenze 125 => 1000000Hz/(64*125)= 125Hz für einen Zählzyklus TCCR0 = (0<<FOC0) | (0<<WGM00) | (0<<COM01) | (0<<COM00) | (1<<WGM01) | (0<<CS02) | (1<<CS01) | (1<<CS00); OCR0=125; //Das PWM-Signal von Timer2 geht über Pin 21 (PD7, OC2) auf blau2 //und wird hier auch für das Dimmen konfiguriert: TCCR2 = (0<<FOC2) | (1<<WGM20) | (1<<COM21) | (0<<COM20) | (0<<WGM21) | (0<<CS22) | (0<<CS21) | (1<<CS20); OCR2 = 0; //Pulsbreite 0..255, 255==maximale Helligkeit, 0==dunkel. //hier ist es o.k., wenn PC1 auf 0 gesetzt ist. } int main(void) { unsigned int zaehler = 0; unsigned char obergrenze = 125; init(); while(1) { if(TCNT0<(obergrenze>>1)) PORTD|=0b01000000; else PORTD&=0b10111111; if(zaehler<100) OCR2=zaehler; else OCR2=100-zaehler/30; zaehler++; if(zaehler>3000) { zaehler = 0; obergrenze+=20; if(obergrenze>200) obergrenze=125; OCR0 = obergrenze; } }//Ende while(1) }
Code 0-3: Quelltext von ton003.
Übung
|