/*
Aufgabenbeschreibung:
Es soll eine einfache Zählerschaltung auf einem Mikrocontroller
(AT-Mega 328, Arduino Uno) realisiert werden.
Der Mikrocontroller soll in der Lage sein, fortwährend in
Einer-Zählschritten hoch- und runterzählen zu können, bis ein
einstellbarer Maximalwert (MW) erreicht ist.
Zwischen zwei Zählschritten soll der Mikrocontroller kurz
pausieren und es dem Nutzer damit ermöglichen, den aktuellen
Zählwert auf einer angeschlossenen Siebensegmentanzeige ablesen
zu können. Eine angeschlossene LED soll dem Nutzer dabei zeigen,
ob der MW erreicht ist.
MW und Zählrichtung können dabei dem Mikrocontroller über
Eingänge vorgegeben werden und können sich zu jeder Zeit ändern.
Die Ausgänge des Mikrocontrollers steuern die Siebensegmentanzeige
und die Anzeige-LED (gelb).
R1) Der Aufbau verfügt über zwei Eingänge x0 und x1 zur Festlegung
des maximalen Zählwerts. Über die Schaltung dieser beiden Eingänge
können der Zählerschaltung somit die dezimaläquivalenten Werte 0
(x1=0 und x0 = 0), 1 (x1 = 0 und x0 = 1), 2 (x1 = 1 und x0 = 0)
oder 3 (x1 = 1 und x0 = 1) als MW vorgegeben werden.
R2) Der Mikrocontroller soll, solange das Einlesen und das Ausgeben
fehlerfrei funktioniert haben, fortwährend in Einerschritten zählen,
bis er das Dezimaläquivalent der x1 x0 Vorgabe (=MW) erreicht hat.
Danach beginnt er von vorne.
Im Falle eines Fehlers ist der Zählvorgang abzubrechen und die Ausgabe
auszuschalten (=alle LEDs auf 0 setzen).
R3) Der Eingang xup gibt dabei als dritter Eingang wie folgt die
Zählrichtung vor:
xup = 1 Mikrocontroller inkrementiert bei jedem Zählschritt: 0 -> … -> MW -> 0 -> ….
xup = 0 Mikrocontroller dekrementiert bei jedem Zählschritt: MW -> … -> 0 -> MW ….
R4) Der aktuelle Zählwert soll auf einer Siebensegmentanzeige als
Dezimalzahl ausgegeben, bzw. dargestellt werden. Diese verfügt über
sieben einzeln ansteuerbare LEDs (A, B, …, G).
R5) Ist der (von x1 x0) vorgegebene MW erreicht, soll für diesen
Zählschritt eine LED aufleuchten. Andernfalls soll die LED
ausgeschaltet sein.
R6) Die Portbelegung entnehmen Sie bitte dem Diagram (rechts) und dem Uno PinOut,
siehe z.B. https://docs.arduino.cc/retired/boards/arduino-uno-rev3-with-long-pins
Reservierte Bits dürfen nicht in Wert oder Datenrichtung geändert werden.
Ausgänge sind rücklesbar.
ACHTUNG:
Bitte nutzen Sie anstatt des bekannten int main(void) Aufbaus
eine void setup() + void loop() Struktur.
Die Funktion setup() wird dabei bei der Abarbeitung einmal durchlaufen
und die Funktion loop() anschließend permanent.
*/
// typ bool ist bereits deklariert
typedef unsigned char uint8_t;
typedef unsigned char BYTE;
typedef enum {PB, PC, PD} PORT;
typedef enum {K0=0, K1, K2, K3, K4, K5, K6, K7} CHANNEL;
void preSetup(void){
// Pseudo-Funktion soll testen, ob reservierte Bits geändert wurden
BYTE PDval = 0b00000000;
BYTE PBval = 0b00100000;
DDRD = 0b00000010; // Output := 1, Input := 0 //Ansteuerung rote LED
DDRB = 0b00100010; // Output := 1, Input := 0 //Ansteuerung gelbe und grüne LED
OutputByte(PD, PDval);
OutputByte(PB, PBval);
}
BYTE InputByte (PORT PortName, BYTE* ReadValue){
// Hardwareabstraktionsschicht, Einlesen und Abspeichern an Adresse ReadValue
if (PortName == PB){
*ReadValue = PINB;
}
else if (PortName == PC){
*ReadValue = PINC;
}
else if (PortName == PD){
*ReadValue = PIND;
}
return 0;
}
BYTE OutputByte (PORT PortName, BYTE WriteValue){
// Hardwareabstraktionsschicht, Ausgabe des Bytes WriteValue am Port PortName
if (PortName == PB){
PORTB = WriteValue;
}
else if (PortName == PC){
PORTC = WriteValue;
}
else if (PortName == PD){
PORTD = WriteValue;
}
return 0;
}
void wait(void){
// Funktion, die eine Zeit wartet
delay(1000);
}
void setup(){
//Nothing to do here // initialisieren der seriellen Schnittstelle
//Initialisierung
}
int maxWert = 0, aktWert = 0, x0 = 0, x1 = 0, xup = 0;
BYTE tempB;
BYTE tempD;
void loop(){
// Pseudofunktion zum Testen, ob reservierte Bits geaendert wurden
// Rote LED darf nicht leuchten, Gruene muss leuchten
preSetup();
// Ab hier Ihr Code
// Do nothing more, wegen Umstrickung main() --> loop(), nach Fehler
// "Abbruch"
while(1){
InputByte(PD, &tempD);
InputByte(PB, &tempB);
// Einlesen der Eingänge x0, x1 und xup
x0 = tempB &(1<<2);
x1 = tempB &(1<<3);
xup = tempB &(1<<4);
// Bestimmen des Maximalwertes basierend auf den Schalterstellungen
if (x1 && x0)
maxWert = 3;
else if (x1)
maxWert = 2;
else if (x0)
maxWert = 1;
else
maxWert = 0;
if(aktWert > maxWert || aktWert < 0){
tempD &= ~0b00000010; //alle Lampenausschalten
tempB &= ~0b11111110;
}
switch(aktWert){
case 0:
//Bitmodifizierung Zahl 0
tempD |= 0b11111100;
tempD &= ~0b00000000;
tempB &= 0b11111110;
break;
case 1:
//Bitmodifizierung Zahl 1
tempD |= 0b00011000;
tempD &= ~0b11100100;
tempB &= ~0b00000001;
break;
case 2:
//Bitmodifizierung Zahl 2
tempD |= 0b01101100;
tempD &= ~0b10010000;
tempB |= 0b00000001;
break;
case 3:
//Bitmodifizierung Zahl 3
tempB |= 0b00000001;
tempD |= 0b00111100;
tempD &= ~0b11000000;
break;
}
wait();
if(xup){ //hochzählen
if (maxWert == 0){
aktWert = 0;
tempB |= 0b00000010; //Gelbe Lampe einschalten
}
else if(aktWert < maxWert){
aktWert++;
tempB &= ~0b00000010; //Gelbe Lampe ausschalten
}
else if(aktWert == maxWert){
aktWert = 0;
tempB |= 0b00000010; //Gelbe Lampe einschalten
}
}
else{ //runterzählen
if(maxWert == 0){
aktWert = 0;
tempB |= 0b00000010; //Gelbe Lampe einschalten
}
else if(aktWert > 0 && aktWert != maxWert){
aktWert--;
tempB &= ~0b00000010; //Gelbe Lampe ausschalten
}
else if(aktWert == maxWert){
aktWert--;
tempB |= 0b00000010; //Gelbe Lampe einschalten
}
else if(aktWert == 0){
aktWert = maxWert;
tempB &= ~0b00000010; //Gelbe Lampe ausschalten
}
}
OutputByte(PD, tempD);
OutputByte(PB, tempB);
wait();
}
}