Grundprinzip
An PB eines ATtiny2313 mit 1MHz Systemtakt soll eine Folge von Mustern nacheinander auf der LED-Zeile ausgegeben werden.
Die LED leuchten bei log. 0 (neg. Logik)
Die Zeit zwischen den Mustern (400 ms) soll mit _delay_ms(400) realisiert werden.
Einfache Lösung
Für jedes Muster ein Befehl
#include <avr/io.h> //Definitionen #include <util/delay.h> //Delay-Bibliothek int main(){ // Hauptprogramm PORTB=0xff; // alle LED aus DDRB=0xff; // PB als Ausgang while(1){ // Endlosschleife PORTB=PORTB&~0b111 | 0b011; _delay_ms(400); PORTB=PORTB&~0b111 | 0b101; _delay_ms(400); PORTB=PORTB&~0b111 | 0b110; _delay_ms(400); PORTB=PORTB&~0b111 | 0b101; _delay_ms(400); } return 0; }
Lösung mit Array
Die Muster werden in ein Array geschrieben und ausgeben
#include <avr/io.h> // Definitionen laden #include <util/delay.h> // CPU Frequenz einstellen! unsigned char muster[]={0b100,0b010,0b001,0b010}; unsigned char musterzaehler=0; int main(){ // Hauptprogramm PORTB=0xff; // alle LED aus DDRB=0xff; // PB als Ausgang while(1){ // Endlosschleife PORTB=(PORTB|0b111) & ~muster[musterzaehler]; // Array-Muster _delay_ms(400); musterzaehler++; if(musterzaehler>=sizeof(muster)){//sizeof ergibt Byte-Groesse musterzaehler=0; } } return 0; }
Zwischen mehreren Mustern umschalten
Mittels Taste an PD0 soll zwischen zwei Musterfolgen umgeschaltet werden können.
Als Lösung könnten zwei Felder muster1[] und muster2[] angelegt werden und mittels switch-Anweisung wird die Ausgabe umgeschaltet. Eleganter und besser erweiterbar ist die Verwendung eines 2-Dimensionalen Arrays, siehe Quelltext.
Da die Muster unterschiedlich lang sind wird zum Erkennen des Musterendes ein geeignetes Verfahren benötigt:
- Entweder mit einem Stopp-Symbol, einer Kombination die nie als Ausgabe vorkommt und das Ende anzeigt.
- Oder mit einer Längenangabe des Musters als ersten Wert (hier gewählt).
So wird muster[2][6]={{4,0b100,0b010,0b001,0b010},{5,0b000,0b110,0b011,0b010,0b111}} im Speicher abgelegt:
muster | [0][0] | [0][1] | [0][2] | [0][3] | [0][4] | [0][5] | [1][0] | [1][1] | [1][2] | [1][3] | [1][4] | [1][5] |
---|---|---|---|---|---|---|---|---|---|---|---|---|
relative Adresse | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
Dateneingabe | 4 | 0b100 | 0b010 | 0b001 | 0b010 | ? | 5 | 0b000 | 0b110 | 0b011 | 0b010 | 0b111 |
gespeichert | 4 | 4 | 2 | 1 | 2 | 0 | 5 | 0 | 6 | 3 | 2 | 7 |
Es werden 12 Byte im SRAM belegt weil das Muster im SRAM gespeichert wird
#include <avr/io.h> // Definitionen laden #include <util/delay.h> // CPU Frequenz einstellen! #define KEYREADER ~PIND & 0b01111111 // Einlesen, invertieren, maskieren zurecht schieben #include "keycheck.inc" // http://mezdata.de/avr/083_c-entprellen/keycheck.inc unsigned char muster[2][6]={{4,0b100,0b010,0b001,0b010},{5,0b000,0b110,0b011,0b010,0b111}}; unsigned char musterzaehler=1,musternummer=0; int main(){ // Hauptprogramm PORTB=0xff; // alle LED aus DDRB=0xff; // PB als Ausgang while(1){ // Endlosschleife keyCheck(); if(keyEnter&1){ // Taste gedrueckt? musterzaehler=0; musternummer++; if(musternummer>=sizeof(muster)/sizeof(muster[0])) musternummer=0; } PORTB=(PORTB|0b111) & ~muster[musternummer][musterzaehler]; // Muster aus Array _delay_ms(400); musterzaehler++; if(musterzaehler>muster[musternummer][0]){ // musterzaehler=1; } } return 0; }
Fragen
Welche relativen Byte-Adressen haben die Elemente bla[2][0] und bla[3][3] in einem Feld char bla[4][5] ?
Beim Vergleich mit einem Koordinatensystem, nach welchem Prinzip werden die Daten im zweidimensionalen Feld abgelegt: [x][y] oder [y][x] ?
Welche relativen Byte-Adressen haben die Elemente blub[0][2] und blub[1][0] in einem Feld int blub[4][5] ?
Mit PROGMEM Daten im Flash-Programmspeicher speichern
Mit PROGMEM können konstante Daten im Flash-Speicher untergebracht werden, im SRAM wird nichts belegt. Gelesen werden die Daten mit besonderen Funktionen, denen die Speicheradresse der Daten mittels des &-Operators übergeben wird.
#include <avr/io.h> // Definitionen laden
#include <util/delay.h> // CPU Frequenz einstellen!
#include <avr/pgmspace.h> // Flashzugriffe laden
#define KEYREADER ~PIND & 0b01111111 // Einlesen, invertieren, maskieren zurecht schieben
#include "keycheck.inc" // http://mezdata.de/avr/083_c-entprellen/keycheck.inc
unsigned char PROGMEM muster[2][6]={{4,0b100,0b010,0b001,0b010},{5,0b000,0b110,0b011,0b010,0b111}};
unsigned char musterzaehler=1,musternummer=0;
int main(){ // Hauptprogramm
PORTB=0xff; // alle LED aus
DDRB=0xff; // PB als Ausgang
while(1){ // Endlosschleife
keyCheck();
if(keyEnter&1){ // Taste gedrueckt?
musterzaehler=0;
musternummer++;
if(musternummer>=sizeof(muster)/sizeof(muster[0])) musternummer=0;
}
PORTB=(PORTB|0b111) & ~pgm_read_byte(&muster[musternummer][musterzaehler]); // Muster aus Array
_delay_ms(400);
musterzaehler++;
if(musterzaehler>pgm_read_byte(&muster[musternummer][0])){ //
musterzaehler=1;
}
}
return 0;
}
Denken Sie sich zwei Musterfolgen aus und erstellen Sie die Werte für muster[][].