U23 2008/Aufgabe Abend2
Contents
Gruppe1:
Gruppe2:
Gruppe3:
Code von Gordin:
Das Programm erzeugt ein simples Lauflicht, das immer von oben nach unten läuft und durch die Taster steuerbar ist. Das bedienen der Taster unterbricht nicht das Lauflicht oder erzeugt eine andere Verzögerung und die Geschwindigkeit des Lauflichts beeinflusst auch nicht die Reaktionszeit der Taster. Wenn man das Programm mit dem unten stehenden Code compiliert ist es 896 Byte groß. Wie das Programm funktioniert ist ausreichend im Code kommentiert (hoff ich 0o).
Funktionen der Taster: Taster 1: Lauflicht schneller laufen lassen. Taster 2: Lauflicht langsamer laufen lassen. Taster 3: Richtung des Lauflichts umkehren. Taster 4: Lauflicht anhalten bzw. weiterlaufen lassen.
Rechtschreibfehler in den Kommentaren sind beabsichtigt...
Hauptprogramm:
<source lang="c"> /*
* Aufgabe2.c * * Created on: 25.08.2008 * Author: Gordin */
- include "../libs/rumpus_ledlib.c" //selbstgeschriebene kleine lib zum steuern der leds
- include "../libs/rumpus_tastlib.c"//selbstgeschriebene kleine lib zum abfragen der Taster
// Variablen für die Warteroutine. uint8_t cycles_to_wait, current_cycle = 0; uint8_t Xwait = 0, setXwait = 255;
uint8_t cyclewait_done(void);
/*
* Wartefunktion für die leds. Leds sollen nur umgeschaltet werden nachdem * das Programm und die warteroutine selber eine bestimmte Anzahl oft durchgelaufen ist. */
uint8_t cyclewait_done() {
if (Xwait < 255) { Xwait++; return 0; } else { Xwait = 0; if (current_cycle >= cycles_to_wait ) { current_cycle = 0; return 1; } else { current_cycle++; return 0; } }
}
int main(void) {
// Erstellung der LED-Sequenz
// Binäre Schreibweise: 11 = led an 10 = led aus 01 = toggle 00 = nichtstun /*uint8_t kr[6] = { 0b11101010, * 0b10111010, * 0b10101110, * 0b10101011}; */
/* Andere möglichkeit: * (Erzeugt die selbe Sequenz wie oben aber das Programm wird ca. 20 Byte größer) * Reihenfolge der leds ist egal, wenn sich nichts ändern soll kann eine led einfach * weggelassen werden. Hier sind ledXaus vor und hinter der leuchtenden led gesetzt, * damit die leds in beide richtungen laufen können. */ uint8_t ledsequenz[4] = {led1 | led2aus | led4aus , led1aus | led2 | led3aus , led2aus | led3 | led4aus , led1aus | led3aus | led4 }; led_init(); // leds initialisieren taster_init(); // taster initialisieren cycles_to_wait = 1 << 4; // Wartezyklen einstellen 65536 Zyklen = ca. 1 Sekunde uint8_t sequenzcount = 0; // Sequenz soll am anfang anfangen 0o int8_t vorwaerts = 1; // Die Sequenz soll vorwaerts laufen uint8_t sequenzlaenge = sizeof(ledsequenz); // Sequenzlänge wird bestimmt uint8_t lauflicht_an = 1; // Das lauflicht wird eingeschaltet while (1) { /* Alle Taster werden abgefragt. Das Ergebnis der Funktion * liegt in taster_states und wird zusätzlich noch zurückgegeben * In den rechten vier bits steht der aktuelle state und * in den linken bits der vorherige zur überprüfung auf wechsel. */ taster_read_all();
/* Es wird geprüft ob ein Taster gedrückt oder losgelassen wurde. * Es zählt nur wenn der taster vorher nicht gedrückt bzw. gedrückt war. * Das Ergebnis steht in taster_downup und wird zusätzlich noch zurückgegeben. * Die ersten vier bits zeigen gedrückt an und die letzten 4 losgelassen */ tasterdownup();
/* * taster_downup wird mit vordefinierten ereignissen kombiniert um zu prüfen * welcher Taster gedrückt wurde. Bsp.: * taster_downup & taster1down ist wahr wenn der Taster 1 gedrückt wurde. * taster_downup & taster3up ist wahr wenn der Taster 3 losgelassen wurde. */
if (taster_downup & taster1down) { if (cycles_to_wait > 1 ) { cycles_to_wait = cycles_to_wait >> 1;// Wartezeit wird verringert, aber nicht zu viel 0o } }
if (taster_downup & taster2down) { if (cycles_to_wait < (1 << 7)) { cycles_to_wait = cycles_to_wait << 1; //Wartezeit wird erhöht, aber nicht zu viel 0o } }
if (taster_downup & taster3down) // Toggle für vorwaerts { if (vorwaerts == 1) { vorwaerts = -1; } else { vorwaerts = 1; } }
if (taster_downup & taster4down) // Toggle für lauflicht { if (lauflicht_an) { lauflicht_an = 0; } else { lauflicht_an = 1; } }
/* Hier wird zuerst geprüft ob das Programm schon oft genug durchgelaufen * ist und erst dann werden die leds umgeschaltet. so blockiert die Wartezeit * der leds nicht den rest des programms. Wenn das Lauflicht ausgeschaltet ist * wird einfach weitergezählt ohne leds zu schalten. */ if (cyclewait_done() && lauflicht_an) { sequenzcount += vorwaerts; // count wird vorwärts oder rückwärts gezählt
// Wenn durch das vorwärts rückwärts schalten müll in dem counter steht // wirds hier wieder richtig gemacht if (sequenzcount >= sequenzlaenge) { if (vorwaerts == 1) { sequenzcount = 0; } else { sequenzcount = (sequenzlaenge - 1); } }
display(ledsequenz[sequenzcount]); // Der Teil der Sequenz der gerade dran ist wird ausgeführt. } }
} </source>
rumpus_ledlib.c:
<source lang="c"> /*
* rumpus_ledlib.c * * Created on: 19.08.2008 * Author: Gordin */
- include <avr/io.h>
// Prototypen void led_1(uint8_t wastun); void led_2(uint8_t wastun); void led_3(uint8_t wastun); void led_4(uint8_t wastun); void led_init(void); static void display(uint8_t led_config);
const uint8_t led1 = 0b11000000; const uint8_t led2 = 0b00110000; const uint8_t led3 = 0b00001100; const uint8_t led4 = 0b00000011; const uint8_t led1aus = 0b10000000; const uint8_t led2aus = 0b00100000; const uint8_t led3aus = 0b00001000; const uint8_t led4aus = 0b00000010; const uint8_t led1toggle = 0b01000000; const uint8_t led2toggle = 0b00010000; const uint8_t led3toggle = 0b00000100; const uint8_t led4toggle = 0b00000001;
//übergibt nur die für die jeweilige Funktion wichtigen bits an die led_X funktionen static void display(uint8_t led_config) {
led_1(led_config & led1); led_2(led_config & led2); led_3(led_config & led3); led_4(led_config & led4);
}
/* toggled alle leds *//* auskommentieren zum benutzen 0o
void led_toggleall() { PORTC ^= _BV(PC4); PORTD ^= _BV(PD3) | _BV(PD6) | _BV(PD7); }*/
/* ausführen bevor man was mit den leds macht */
void led_init() {
DDRC = _BV(PC4); DDRD = _BV(PD3) | _BV(PD6) | _BV(PD7); PORTC &= ~_BV(PC4); PORTD &= ~_BV(PD3) | ~_BV(PD6) | ~_BV(PD7);
}
/* Steuerung für led 1: Argumente, die übergeben werden können:
* 0b11000000 (led1) = anschalten * 0b10000000 (led1aus) = ausschalten * 0b01000000 (led1toggle) = toggle * 0b00000000 (0) = nichts */
void led_1(uint8_t wastun) {
if (wastun == led1aus) { PORTC &= ~_BV(PC4); //löscht PC4 in PORTC } else if (wastun == led1) { PORTC |= _BV(PC4); // setzt PC4 in PORTC } else if (wastun == led1toggle) { PORTC ^= _BV(PC4); // tauscht PC4 in PORTC }
}
/* Steuerung für led 2: Argumente, die übergeben werden können:
* 0b00110000 (led2) = anschalten * 0b00100000 (led2aus) = ausschalten * 0b00010000 (led2toggle) = toggle * 0b00000000 (0) = nichts */
void led_2(uint8_t wastun) {
if (wastun == led2aus) { PORTD &= ~_BV(PD3); //setzt alle werte, die schon da sind und nicht PD3 sind } else if (wastun == led2) { PORTD |= _BV(PD3); // setzt alle werte, die schon da sind und PD3 } else if (wastun == led2toggle) { PORTD ^= _BV(PD3); // setzt alle werte, die schon da sind und tauscht PD3 }
}
/* Steuerung für led 3: Argumente, die übergeben werden können:
* 0b00001100 (led3) = anschalten * 0b00001000 (led3aus) = ausschalten * 0b00000100 (led3toggle) = toggle * 0b00000000 (0) = nichts */
void led_3(uint8_t wastun) {
if (wastun == led3aus) { PORTD &= ~_BV(PD6); //setzt alle werte, die schon da sind und nicht PD6 sind } else if (wastun == led3) { PORTD |= _BV(PD6); // setzt alle werte, die schon da sind und PD6 } else if (wastun == led3toggle) { PORTD ^= _BV(PD6); // setzt alle werte, die schon da sind und tauscht PD6 }
}
/* Steuerung für led 4: Argumente, die übergeben werden können:
* 0b00000011 (led4) = anschalten * 0b00000010 (led4aus) = ausschalten * 0b00000001 (led4toggle) = toggle * 0b00000000 (0) = nichts */
void led_4(uint8_t wastun) {
if (wastun == led4aus) { PORTD &= ~_BV(PD7); //setzt alle werte, die schon da sind und nicht PD7 sind } else if (wastun == led4) { PORTD |= _BV(PD7); // setzt alle werte, die schon da sind und PD7 } else if (wastun == led4toggle) { PORTD ^= _BV(PD7); // setzt alle werte, die schon da sind und tauscht PD7 }
}
</source>
rumpus_tastlib.c:
<source lang="c"> /*
* rumpus_tastlib.c * * Created on: 25.08.2008 * Author: Gordin */
- include <avr/io.h>
void taster_init(void); uint8_t tasterdownup(void); uint8_t taster_read(uint8_t taster); uint8_t taster_read_all(void);
// Vordefinierte states zur leichteren Benutzung const uint8_t taster1up = 0b00000001; const uint8_t taster2up = 0b00000010; const uint8_t taster3up = 0b00000100; const uint8_t taster4up = 0b00001000; const uint8_t taster1down = 0b00010000; const uint8_t taster2down = 0b00100000; const uint8_t taster3down = 0b01000000; const uint8_t taster4down = 0b10000000;
uint8_t taster_states = 0; // Der aktuelle state der Taster uint8_t taster_laststates = 0; // Der vorherige state der Taster uint8_t taster_downup = 0; // Information ob ein taster gedrückt oder losgelassen wurde uint8_t prellarray[]; // Array zur entprellung der Taster
void taster_init() // Initialisieren der Taster (Pull-Offs) {
PORTC = _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3);
}
/* Prüft gleichzeitig bei allen 4 Tastern ob gedrückt bzw. losgelassen wurde.
* Zur überprüfung muss taster_states richtig gesetzt sein. */
uint8_t tasterdownup() {
taster_laststates = taster_states >> 4;
// gerade gedrückte Taster taster_downup = (taster_laststates ^ taster_states) // nur geänderte Wert weiterbenutzen & taster_states // nur neue gesetzte Werte benutzen & 0b00001111 // schließt vorherige Werte aus ;
//gerade losgelassene Taster taster_downup = (taster_downup << 4) // info über gedrückte Taster nach links + ((taster_laststates ^ taster_states) // nur geänderte Wert weiterbenutzen & taster_laststates // nur alte gesetzte Werte benutzen & 0b00001111 // schließt vorherige Werte aus ); return taster_downup;
}
/* Ließt einen einzelnen Taster ein.
* Dazu wird 8 mal nacheinander der state eingelesen und in eine variable geshiftet. * Wenn die variable ganz mit 1 voll ist wird der taster der eingegeben wurde zurück- * gegeben. Wenn die variable nur aus 0 besteht wird 0 zurückgegeben. * wenn einsen und nullen gemischt auftauchen wird der vorherige state mit dem * eingegebenen taster verglichen und zurückgegeben. (der alte state wird zurückgegeben) * Die funktion muss zur überprüfung dauerhaft aufgerufen werden (mit state_read oder * state_read_all vorher) um sinnvolle Ergebnisse zu liefern, da bei jedem durchlauf * nur ein mal geshiftet wird und somit bei einmaligem aufrufen der vorherige state * geliefert wird */
uint8_t taster_read(uint8_t taster) {
if (PINC & taster) { prellarray[taster] = (prellarray[taster] << 1); } else { prellarray[taster] = (prellarray[taster] << 1) + 1; }
if (prellarray[taster] == 0b11111111) { return taster; } else if (prellarray[taster] == 0) { return 0; } else return taster_laststates & taster;
}
/* Ruft taster_read für jeden Taster auf, speichert das ergebnis in taster_states
* und gibt taster_states zurück. Die vorherigen states werden ebenfalls mit übergeben * in den linken 4 bits der variable zum späteren Vergleich */
uint8_t taster_read_all() {
uint8_t i; uint8_t taster_read_all_var = taster_states << 4; // Hier wird geshiftet statt erhöht um den wert für jeden taster direkt übergeben zu können for (i = 1; i <= 8 ; i = (i << 1)) { taster_read_all_var |= taster_read(i); } taster_states = taster_read_all_var; return taster_read_all_var;
} </source>