#include <avr/io.h>
#include <avr/interrupt.h>
#define KEYREADER (~PIND)>>4 // Einlestellen, invertieren, maskieren zurecht schieben
unsigned char keyOld = 0; // alter Tasten-Zustand
unsigned char keyEnter, keyExit; // gedrueckte und losgelassene Tasten
typedef enum {ZME, ZMZ, ZSE, ZSZ} stellenTyp; // MinutenEiner..StundenZehner
typedef enum {ANZEIGEN, SET_STUNDEN, SET_MIN_Z, SET_MIN_E} modeTyp;
volatile unsigned char stelle[] = {9, 5, 3, 2}; // 23:59 (Minuten, Stunden)
unsigned char mode = ANZEIGEN; // Betriebsmodus
volatile unsigned char sek = 0; // Sekunden Zaehler
volatile unsigned int cs = 0; // Centisekunden
void my_delay_cs(unsigned int n) { // delay in Centisekunden
unsigned int future = cs + n;
while (cs < future);
}
void keyCheck() { // Tastaturabfrage mit Flankendedektion
unsigned char keyTest, tmp;
keyEnter = 0, keyExit = 0;
keyTest = KEYREADER; // Einlestelle[ZSE]n
if (keyOld != keyTest) { // hat sich was getan
my_delay_cs(2); // Prellen abwarten
tmp = KEYREADER; // noch mal Einlestelle[ZSE]n
if (tmp == keyTest) { // ist es stabil?
keyEnter = (~keyOld) & keyTest; // steigende Flanke !alt und neu
keyExit = keyOld & (~keyTest); // fallende Flanke alt und !neu
keyOld = keyTest;
}
}
}
#define T_SET keyEnter & 4
#define T_DOWN keyEnter & 2
#define T_UP keyEnter & 1
int main() {
DDRB = 0xFF; // PORTB als Ausgang
PORTD = 0x70; // PullUps an
/*
* Aufgabe 1 Timer einstellen
*/
sei();
while (1) {
keyCheck();
/*
* Aufgabe 4 Zustandsdiagramm umsetzen
*/
if (mode!=ANZEIGEN) sek = 0; // Sekunden anhalten
}
return 0;
}
void decStelle(unsigned char s) { // Stelle erniedrigen
if (stelle[s] > 0) stelle[s]--;
}
void incStelle(unsigned char s, unsigned char m) {
if (stelle[s] < m) stelle[s]++;
}
void decStunde() { // Stunde erniedrigen
/*
* Aufgabe 3
*/
}
void incStunde() { // Stunde erhoehen
/*
* Aufgabe 2
*/
}
void incMinute() { // Minuten erhoehen
if (stelle[ZME] < 9) {
stelle[ZME]++;
}
else { // MinutenZehner
stelle[ZME] = 0;
if (stelle[ZMZ] < 5) {
stelle[ZMZ]++;
}
else { // StundenEiner
stelle[ZMZ] = 0;
incStunde();
}
}
}
ISR(TIMER1_COMPA_vect) { // jede 0,5ms
static unsigned char i = 0, ms = 0;
static const unsigned char stelleEin[] = {0b11100000, 0b11010000, 0b10110000, 0b01110000};
PORTB = stelleEin[i] | stelle[i];
if(i==3 && (sek&1)) PINB=0x08; // LED15 als Sekundenblinker
switch (mode) { // beim Einstellen andere Stellen ausblenden
case SET_STUNDEN: // Stunden einstellen
if (i == ZME || i == ZMZ) PORTB = 0;
break;
case SET_MIN_Z: // Minuten Zehner einstellen
if (i != ZMZ) PORTB = 0;
break;
case SET_MIN_E: // Minuten Einer einstellen
if (i != ZME) PORTB = 0;
break;
}
if (ms < 19) { // interner Zaehler
ms++;
}
else {
ms = 0;
cs++; // Centiskunden hochzaehlen
if (cs % 100 == 0) { // eine Sekunde ist rum
if (sek < 59) {
sek++;
}
else { // Minute ist rum
sek = 0;
incMinute();
}
}
}
if (i < 3) i++; // Stellen durchgehen
else i = 0;
}