MezData-Logo

Binäruhr mit Zylonenauge

Zylonenauge-Binäruhr

Binäruhr

Eine Binäruhr wird mit den Zylonenauge erstellt. Die Uhrzeit wird dabei BCD-Codiert.
Mittels der Tasten soll die Uhr gestellt werden können.

Zur genaueren Zeitmessung kommt der 4Mhz Keramikschwinger zum Einsatz.

Aufgaben

Vorgabe [zylon-binaeruhr-vorgabe/zylon-binaeruhr-vorgabe.ino]
  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3.  
  4. #define KEYREADER (~PIND)>>4 // Einlestellen, invertieren, maskieren zurecht schieben
  5. unsigned char keyOld = 0; // alter Tasten-Zustand
  6. unsigned char keyEnter, keyExit; // gedrueckte und losgelassene Tasten
  7. typedef enum {ZME, ZMZ, ZSE, ZSZ} stellenTyp; // MinutenEiner..StundenZehner
  8. typedef enum {ANZEIGEN, SET_STUNDEN, SET_MIN_Z, SET_MIN_E} modeTyp;
  9. volatile unsigned char stelle[] = {9, 5, 3, 2}; // 23:59 (Minuten, Stunden)
  10. unsigned char mode = ANZEIGEN; // Betriebsmodus
  11. volatile unsigned char sek = 0; // Sekunden Zaehler
  12. volatile unsigned int cs = 0; // Centisekunden
  13.  
  14. void my_delay_cs(unsigned int n) { // delay in Centisekunden
  15. unsigned int future = cs + n;
  16. while (cs < future);
  17. }
  18.  
  19. void keyCheck() { // Tastaturabfrage mit Flankendedektion
  20. unsigned char keyTest, tmp;
  21. keyEnter = 0, keyExit = 0;
  22. keyTest = KEYREADER; // Einlestelle[ZSE]n
  23. if (keyOld != keyTest) { // hat sich was getan
  24. my_delay_cs(2); // Prellen abwarten
  25. tmp = KEYREADER; // noch mal Einlestelle[ZSE]n
  26. if (tmp == keyTest) { // ist es stabil?
  27. keyEnter = (~keyOld) & keyTest; // steigende Flanke !alt und neu
  28. keyExit = keyOld & (~keyTest); // fallende Flanke alt und !neu
  29. keyOld = keyTest;
  30. }
  31. }
  32. }
  33.  
  34. #define T_SET keyEnter & 4
  35. #define T_DOWN keyEnter & 2
  36. #define T_UP keyEnter & 1
  37. int main() {
  38. DDRB = 0xFF; // PORTB als Ausgang
  39. PORTD = 0x70; // PullUps an
  40. /*
  41.   * Aufgabe 1 Timer einstellen
  42.   */
  43. sei();
  44. while (1) {
  45. keyCheck();
  46. /*
  47.   * Aufgabe 4 Zustandsdiagramm umsetzen
  48.   */
  49. if (mode!=ANZEIGEN) sek = 0; // Sekunden anhalten
  50. }
  51. return 0;
  52. }
  53.  
  54. void decStelle(unsigned char s) { // Stelle erniedrigen
  55. if (stelle[s] > 0) stelle[s]--;
  56. }
  57. void incStelle(unsigned char s, unsigned char m) {
  58. if (stelle[s] < m) stelle[s]++;
  59. }
  60. void decStunde() { // Stunde erniedrigen
  61. /*
  62.   * Aufgabe 3
  63.   */
  64. }
  65. void incStunde() { // Stunde erhoehen
  66. /*
  67.   * Aufgabe 2
  68.   */
  69. }
  70. void incMinute() { // Minuten erhoehen
  71. if (stelle[ZME] < 9) {
  72. stelle[ZME]++;
  73. }
  74. else { // MinutenZehner
  75. stelle[ZME] = 0;
  76. if (stelle[ZMZ] < 5) {
  77. stelle[ZMZ]++;
  78. }
  79. else { // StundenEiner
  80. stelle[ZMZ] = 0;
  81. incStunde();
  82. }
  83. }
  84. }
  85.  
  86. ISR(TIMER1_COMPA_vect) { // jede 0,5ms
  87. static unsigned char i = 0, ms = 0;
  88. static const unsigned char stelleEin[] = {0b11100000, 0b11010000, 0b10110000, 0b01110000};
  89. PORTB = stelleEin[i] | stelle[i];
  90. if(i==3 && (sek&1)) PINB=0x08; // LED15 als Sekundenblinker
  91. switch (mode) { // beim Einstellen andere Stellen ausblenden
  92. case SET_STUNDEN: // Stunden einstellen
  93. if (i == ZME || i == ZMZ) PORTB = 0;
  94. break;
  95. case SET_MIN_Z: // Minuten Zehner einstellen
  96. if (i != ZMZ) PORTB = 0;
  97. break;
  98. case SET_MIN_E: // Minuten Einer einstellen
  99. if (i != ZME) PORTB = 0;
  100. break;
  101. }
  102. if (ms < 19) { // interner Zaehler
  103. ms++;
  104. }
  105. else {
  106. ms = 0;
  107. cs++; // Centiskunden hochzaehlen
  108. if (cs % 100 == 0) { // eine Sekunde ist rum
  109. if (sek < 59) {
  110. sek++;
  111. }
  112. else { // Minute ist rum
  113. sek = 0;
  114. incMinute();
  115. }
  116. }
  117. }
  118. if (i < 3) i++; // Stellen durchgehen
  119. else i = 0;
  120. }
  121.  

Timer einstellen

Der Systemtakt betägt 4MHz, der 16Bit Timer1 soll im CTC-Mode alle 0,5ms
ISR(TIMER1_COMPA_vect) aufrufen. Ermitteln Sie die Einstellungen.

EntscheidungsbaumHochzählen der Stunden

Das UP incStunde() soll die Stundenanzeige erhöhen. Nebenstehend ein Analysegraph. Erstellen Sie den Quellcode.

Runterzählen der Stunden

Das UP decStunde() soll die Stundenanzeige erniedrigen. Zeichen Sie einen Analysegraph und erstellen Sie den Quellcode.

Zustandsdiagramm

Einstellen der Zeit

Erstellen Sie den Quellcode für den Zustandsgraph.

Lösung anzeigen..

 

Lösungen für die bessere Ablesbarkeit

Die BCD-Ausgabe ist schlecht lesbar, weil die LED nicht einfach den BCD-Stellen zugeordnet werden können. Lösungen:

  1. Frontplatte mit Markierungen.
  2. Die Low-Bits könnten eine andere Farbe bekommen
  3. Stellen nacheinander heller leuchten lassen
    [zylon-binaeruhr-versuch.ino]
  4. Die Low-Bits werden anders dargestellt, z.B. bei Zustand 1 leuchten sie heller und bei Zustand 0 blitzen sie periodisch auf.
    Lösung anzeigen..

Ausblick, Erweiterungen