/*
BITTE ERSTELLEN SIE SICH VORAB EINE PRIVATE KOPIE, DAZU
AUF "SAVE AS" GEHEN.
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
DDRB = 0b00100100; // Output := 1, Input := 0
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
}
void initializePins(){
static int initialized = 0;
if (!initialized)
{
DDRB = 0x00; // Alle Pins vom B-Register als Eingänge deklarieren
DDRD = 0x00; // Alle Pins vom D-Register als Eingänge deklarieren
DDRB |= (1 << K0) | (1 << K1) | (1 << K5); // PIN PB0,PB1,PB5 als Ausgänge deklarieren rest Eingänge
DDRD = ~DDRD; // Invertiren aller BIts im DDRD Register damit alles Ausgänge
DDRD ^= ( 1<< K0); // Das BIT-0 vom DDRD Register wird wieder zu einem eingang gemacht
initialized = 1;
}
}
BYTE SiebensegmentD(int state1){
switch (state1)
{
case 0:
return 0b11111100;
break;
case 1:
return 0b00011000;
break;
case 2:
return 0b01101100;
break;
case 3:
return 0b00111100;
break;
}
}
BYTE SiebensegmentB(int state2){
switch (state2)
{
case 0:
return 0b00000000;
break;
case 1:
return 0b00000000;
break;
case 2:
return 0b00000001;
break;
case 3:
return 0b00000001;
break;
}
}
void loop(){
// Pseudofunktion zum Testen, ob reservierte Bits geaendert wurden
// Rote LED darf nicht leuchten, Gruene muss leuchten
preSetup();
// Hier Ihr Code
wait();
initializePins(); // Ausführung der Initalisierung der Pins nach Vorgabe
/*
BYTE PBval = 0b00100000; // setzen des Outputs von PORTB an stelle 5 auf 1
BYTE PDval = 0b00000000; // setzen des Outputs von PORTD
BYTE ZERO = 0b11111100;
BYTE EINS = 0b00011000;
BYTE ZWEI = 0b01101100;
BYTE ZUSATZ23 = 0b00000001;
BYTE DREI = 0b00111100;
OutputByte(PB, PBval); // Schreiben auf den Pin wodurch Grüne LED leuchtet
wait();
BYTE PBin;
InputByte(PB,&PBin);
if ( PBin & (1 << 4)) //Überprüfung ob Inkrementieren oder Dekrementieren
{
PBval = 0b00100000;
OutputByte(PB, PBval);
if ((PINB & (1 << 2)) == 0 && (PINB & (1 << 3)) == 0)
{
PBval &= ~(1<<1);
OutputByte(PB, PBval);
PDval = ZERO;
PBval |= (1<<1);
OutputByte(PD, PDval);
OutputByte(PB, PBval);
}
if ((PINB & (1 << 2)) && (PINB & (1 << 3)) == 0)
{
PBval &= ~(1<<1);
OutputByte(PB, PBval);
PDval = ZERO;
OutputByte(PD, PDval);
wait();
PDval = EINS;
PBval |= (1<<1);
OutputByte(PB, PBval);
OutputByte(PD, PDval);
wait();
}
if ((PINB & (1 << 2)) == 0 && (PINB & (1 << 3)))
{
PBval &= ~(1<<1);
OutputByte(PB, PBval);
PDval = ZERO;
OutputByte(PD, PDval);
wait();
PDval = EINS;
OutputByte(PD, PDval);
wait();
PDval = ZWEI;
PBval = ZUSATZ23;
PBval |= (1<<1);
OutputByte(PD, PDval);
OutputByte(PB, PBval);
wait();
}
if ((PINB & (1 << 2)) && (PINB & (1 << 3)))
{
PBval &= ~(1<<1);
OutputByte(PB, PBval);
PDval = ZERO;
OutputByte(PD, PDval);
wait();
PDval = EINS;
OutputByte(PD, PDval);
wait();
PDval = ZWEI;
PBval = ZUSATZ23;
OutputByte(PD, PDval);
OutputByte(PB, PBval);
wait();
PDval = DREI;
PBval = ZUSATZ23;
PBval |= (1<<1);
OutputByte(PD, PDval);
OutputByte(PB, PBval);
wait();
}
} else {
PDval = 0b00000010;
OutputByte(PD, PDval);
PBval = 0b00000000;
OutputByte(PB, PBval);
}
*/
BYTE PortB = 0, PortD = 0;
int ERROR = 0,i = 0;
BYTE MW = 0,xup = 0;
BYTE Anzeige = 0;
// Do nothing more, wegen Umstrickung main() --> loop(), nach Fehler
// "Abbruch"
while(1) {
//Do nothing
while (ERROR == 0)
{
//wait();
ERROR += InputByte(PB,&PortB); //Überprüfung ob Einlesen der InputBytes Funktioniert hat und kein Fehler
ERROR += InputByte(PD,&PortD);
MW = ((PortB >> 2) & 0b00000011);
xup = ((PortB >> 4) & 0b00000001);
PORTD = SiebensegmentD(i);
PORTB = SiebensegmentB(i);
wait();
ERROR += OutputByte(PB,PortB);
ERROR += OutputByte(PD,PortD);
if(xup)
{
if( i == MW)
{
PORTB |= ( 1<<1 );
wait();
}
i++;
if (i > MW)
{
PORTB &= ~( 1<<1 );
i = 0;
}
}
if(!xup)
{
PORTB &= ~( 1<<1 );
i--;
if (i < 0)
{
i = MW;
PORTB |= ( 1<<1 );
wait();
}
}
}
}
}