Ansteuerung aller LEDs der Licht-Klangkugel (RGB - Rot, Grün, Blau)
(EN google-translate)
(PL google-translate)
In dem vorangegangenen Kapitel wurden versciedene Techniken angesprochen, die erste der in die Licht-Klangkugel einzubauenden LEDs anzusprechen.
Im folgenden wird besprochen, wie alle sechs LEDs benutzt und auch in ihrer Helligkeit über Mikrocontrollerprogramme beeinflußt werden können.
Zur besseren Orientierung werden die LEDs zunächst mit festen Bezeichnungen versehen, die denen des Elaktronik-Layouts entspricht (s. nachfolgendes Schaubild).
Bild 0-1: Bezeichnungen der 6 LEDs der Licht-Klangkugel.
Die folgende Tabelle stellt dar, wie die LEDs mit dem Mikrocontroller und ggf. der Spannungsversorgung verbunden sind:
|
|
LED-Bezeichnung | Anode + | Kathode - |
---|---|---|
rot1 | PC4 | GND |
gruen1 | PA1 | PA0 |
blau1 | PA7 | PA6 |
rot2 | PB4 | PB3/OC0 |
gruen2 | PC6 | PC7 |
blau2 | PD7/OC2 | PC1 |
Tabelle 0-1: Verbindungen der LEDs mit dem Mikrocontroller.
Das nachfolgende Programm 005_rgb12.c erlaubt es, auf komfortable Weise alle LEDs anzusprechen. Der Funktion rgb(..) wird eine unsigned char-Variable übergeben. Jedem der unteren 6 Bits dieser Variablen ist eine LED zugeordnet. Durch setzen der Bits auf 1 wird die korrespondierende LED ein durch Setzen auf 0 ausgeschaltet. Die Zuordnung ist die folgende:
LED-Bezeichnung | Bit-Nummer |
---|---|
rot1 | 0 |
gruen1 | 1 |
blau1 | 2 |
rot2 | 3 |
gruen2 | 4 |
blau2 | 5 |
Tabelle 0-2: Bitzuordnung zum Ansprechen der LEDs.
Indem im Hauptprogramm die Variable ZEIT der Funktion rgb(..) übergeben wird, werden ständig alle Kombinationsmöglichkeiten der LEDs durchgspielt. Die Bits oberhalb des Bits Nr. 5 (6. Bit) werden von der Funktion nicht beachtet.
#include <avr/io.h> #include<avr/interrupt.h> volatile unsigned int ZEIT = 0; SIGNAL(SIG_OUTPUT_COMPARE1A) //Interruptfunktion { ZEIT++; ZEIT%=10000; } void init() { DDRA = 0;DDRB = 0;DDRC = 0;DDRD = 0; PORTA = 0;PORTB = 0;PORTC = 0;PORTD = 0; //rot1: Pin26 DDRC |= 0b00010000; //PC4 als Ausgang konfigurieren. //grün1: Pin39,40 DDRA |= 0b00000011; //PA0 und PA1 als Ausgang konfigurieren. //blau1: Pin33,34 DDRA |= 0b11000000; //PA6 und PA7 als Ausgang konfigurieren. //rot2: Pin4,5 DDRB |= 0b00011000; //grün2: Pin28,29 DDRC |= 0b11000000; //blau2: Pin21,23 DDRC |= 0b00000010; //PC1 DDRD |= 0b10000000; //PD7 //ZEIT-Geber: TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<FOC1A) | (0<<FOC1B) | (0<<WGM11) | (0<<WGM10); TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (1<<CS12) | (0<<CS11) | (1<<CS10); TIMSK |= (1<<OCIE1A); OCR1A = 97; //97=> ungefähr im 0,1 Sekunden-Takt wird Interrupt ausgelöst. //genauer sind es 10,067654639Hz, also 0,099328Sekunden pro Zählschritt. sei(); //Interrupts zulassen } void rgb(unsigned char farbe) { //rot1==bit0 if( (farbe & 0b00000001)>0 ) PORTC |= 0b00010000; else PORTC &= 0b11101111; //grün1==bit1 if( (farbe & 0b00000010)>0 ) PORTA |= 0b00000010; else PORTA &= 0b11111101; //blau1==bit2 if( (farbe & 0b00000100)>0 ) PORTA |= 0b10000000; else PORTA &= 0b01111111; //rot2==bit3 if( (farbe & 0b00001000)>0 ) PORTB |= 0b00010000; else PORTB &= 0b11101111; //grün2==bit4 if( (farbe & 0b00010000)>0 ) PORTC |= 0b01000000; else PORTC &= 0b10111111; //blau2==bit5 if( (farbe & 0b00100000)>0 ) PORTD |= 0b10000000; else PORTD &= 0b01111111; } int main(void) { unsigned int zaehler = 0; init(); while(1) { rgb(ZEIT); } }
Code 0-1: Quelltext von 005_rgb12.c
Verwendung von PWM-Signalen
Im nun folgenden Programm wird ein PWM-Signal eingesetzt, um die rote LED zu dimmen. Da diese am PWM-Ausgang des Timers0 angeschlossen ist, muß dieser entsprechend konfiguriert werden.
Der Timer0 wird als PWM-Geber mit Phasen-korrektem Signal realisiert. Die notwendigen Bitkonfigurationen des Registers TCCR0 (Timer/Counter Control Register) können der Tabelle 38 im Datenblatt auf Seite 78 entnommen werden. Es handelt sich um den Modus 1. Die entsprechende Befehlszeile zur Konfiguration lautet entsprechend:
TCCR0 = (0<<FOC0) | (1<<WGM00) | (1<<COM01) | (0<<COM00) | (0<<WGM01) | (0<<CS02) | (0<<CS01) | (1<<CS00);
Code 0-2: Timer0 als Phasen korrekten PWM-Geber konfigurieren.
//Blinken grüne LED #include <avr/io.h> #include<avr/interrupt.h> volatile unsigned int ZEIT = 0; SIGNAL(SIG_OUTPUT_COMPARE1A) //Interruptfunktion { ZEIT++; ZEIT%=10000; } void init() { DDRA = 0;DDRB = 0;DDRC = 0;DDRD = 0; PORTA = 0;PORTB = 0;PORTC = 0;PORTD = 0; //rot1: Pin26 DDRC |= 0b00010000; //PC4 als Ausgang konfigurieren. //grün1: Pin39,40 DDRA |= 0b00000011; //PA0 und PA1 als Ausgang konfigurieren. //blau1: Pin33,34 DDRA |= 0b11000000; //PA6 und PA7 als Ausgang konfigurieren. //rot2: Pin4,5 DDRB |= 0b00011000; //grün2: Pin28,29 DDRC |= 0b11000000; //blau2: Pin21,23 DDRC |= 0b00000010; //PC1 DDRD |= 0b10000000; //PD7 //Timer0 kann ein PWM-Signal erzeugen und damit LED rot2 //durch Variation der Pulsbreite dimmen. //Dies wird hier konfiguriert: TCCR0 = (0<<FOC0) | (1<<WGM00) | (1<<COM01) | (0<<COM00) | (0<<WGM01) | (0<<CS02) | (0<<CS01) | (1<<CS00); OCR0 = 0; //Pulsbreite 0..255, 0==dunkel, 255==maximale Helligkeit. //Damit Strom fließen kann, muß PB4 auf High-Potential gelegt werden: PORTB |= 0b00010000; //ZEIT-Geber: TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<FOC1A) | (0<<FOC1B) | (0<<WGM11) | (0<<WGM10); TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (1<<CS12) | (0<<CS11) | (1<<CS10); TIMSK |= (1<<OCIE1A); // OCR1A = 97; //97=> ungefähr im 0,1 Sekunden-Takt wird Interrupt ausgelöst. //genauer sind es 10,067654639Hz, also 0,099328Sekunden pro Zählschritt. //Kleiner setzen, sonst ist das Dimmen zu langsam: OCR1A = 10; sei(); //Interrupts zulassen } int main(void) { unsigned int wert = 0; init(); while(1) { wert = ZEIT%511; if(wert>255) wert = 511-wert; OCR0 = wert; } }
Code 0-3: Quelltext von 006_rot2_gedimmt.c
Übung
|