MezData-Logo

Blinken wie ein Audi

Blinken wie ein Audi mit Zylonenauge

BlinkmusterAngelehnt an Abiaufgabe 18-1 [Korrekturhinweis]

Mit LED soll ein inovativer KFZ-Blinker entwickelt werden. Ein zunehmendes Leuchtband (Blinkfolge) zeigt die Richtung (siehe Bild rechts).

Das Zylonenauge wird mit intern 1MHz betrieben.

Solange Taster T0 gedrückt ist (PD4=0) wird wiederholt die Blinkfolge t0..t4 mit einem Abstand zwischen den Ausgaben von 150 ms ausgegeben.

Mit delay_ms()

Solange Taster T0 gedrückt ist wird das Unterprogramm blinken() immer wieder ausgeführt. Das UP blinken() gibt die Musterfolge t0..t4 mit einem Abstand von 150ms mit (_delay_ms(150)) aus. Hinweis: Das UP endet nach Ausgabe des Musters t4.

Ist ein Entprellen von T0 notwendig?

Entwickeln Sie das Hauptprogramm mit Initialisierung und das UP blinken().

Lösung anzeigen..

Mit Timer-ISR

Statt _delay_ms(150) soll nun 8-Bit Timer0 mit CTC-Interrupt verwendet werden. T0 aktiviert die Ausführung einer Blinkfolge t0..t4 (nach Ausgabe von Muster t4 deaktiviert sich die Ausgabe). Somit wird nur solange geblinkt, wie T0 gedrückt bleibt.

Das Aktivieren und Deaktivieren der Ausgabenfolge kann mit diesen Alternativen erreicht werden:

  1. Durch Setzen und Rücksetzen des ISR-Enable-Flags OCIE0A
  2. Durch Starten und Stoppen des Zählers im Vorteiler (Prescaler)
  3. Durch eine globale Variable, die in der ISR die Ausführung beeinflusst.

Optimal sollte möglichst schnell nach Drücken der Taste T0 die Blinkfolge durchlaufen werden.

Begründen Sie, welche Alternative am besten geeignet ist.

Entwickeln Sie eine Lösung.

Lösung anzeigen..

Welche Probleme können mit dem Vorteiler (engl. Prescaler) auftreten?

Bei Starten und Stoppen des Timers wird der Vorteiler nicht zurück gesetzt, somit kann gleich oder erst nach einem Durchlauf der Vorteilzeit der Timer-Impuls kommen.

Aus der Doku zum 2313 S117 aus dem Englischen:

"Timer/Counter1 und Timer/Counter0 teilen sich das gleiche Prescaler-Modul, aber die Timer/Counter können unterschiedliche Prescaler-Einstellungen haben. Die folgende Beschreibung gilt sowohl für Timer/Counter1 als auch für Timer/Counter0."

Prescaler Reset

"Der Vorteiler ist freilaufend, d.h. er arbeitet unabhängig von der Clock Select-Logik des Timers/Zählers und wird von Timer/Zähler1 und Timer/Zähler0 gemeinsam genutzt. Da der Vorteiler nicht von der Taktwahl des Timers/Zählers beeinflusst wird, hat der Zustand des Vorteilers Auswirkungen auf Situationen, in denen eine vorskalierte Taktung verwendet wird. Ein Beispiel für Vorskalierungsartefakte tritt auf, wenn der Timer aktiviert und vom Vorteiler getaktet wird (6 > CSn2:0 > 1). Die Anzahl der Systemtaktzyklen von der Aktivierung des Timers bis zum ersten Auftreten der Zählung kann von 1 bis N+1 Systemtaktzyklen betragen, wobei N gleich dem Vorteilerteiler (8, 64, 256 oder 1024) ist.
Es ist möglich, den Prescaler-Reset zur Synchronisation des Timers/Zählers zur Programmausführung zu verwenden. Es ist jedoch Vorsicht geboten, wenn der andere Timer/Zähler, der den gleichen Vorteiler teilt, auch die Vorskalierung verwendet. Ein Prescaler-Reset wirkt sich auf die Prescaler-Periode für alle Timer/Zähler aus, an die es angeschlossen ist.

Übersetzt mit www.DeepL.com/Translator"

Led-Matrix: Beliebige LED scheinbar gleichzeitig leuchten lassen (Zeit-Multiplex-Verfahren)

LED MatrixDurch die Matrix-Anordnung ist es nicht möglich, beliebige LED zeitgleich leuchten zu lassen. Durch die Trägheit des Auges ergibt sich jedoch die Möglichkeit, nacheinander die LED-Gruppen an PB7..4 ihre Muster ausgeben zu lassen:

  1. Nur PB4 auf 0 und Muster für LED3..0 anlegen.
  2. Nur PB5 auf 0 und Muster für LED7..4 anlegen.
  3. Nur PB6 auf 0 und Muster für LED11..8 anlegen.
  4. Nur PB7 auf 0 und Muster für LED15..12 anlegen.
  5. Wieder zu 1.

Es bietet sich an, die Ausgabe über einen Timer gesteuerten Interrupt periodisch ausführern zu lassen, das Muster wird dabei im SRAM gespeichert.

Ausgabezyklus

Um eine flackerfreie Anzeige zu erhalten und eine gute Zeitbasis für ein eigenes delay_ms() zu erhalten soll die Timer-ISR mit 500Hz aufgerufen werden. Zeitbasis ist Keramikschwinger mit 4MHz.

Mit einem Feld mit 4 Byte vram[] werden die Ausgaben im SRAM gespeichert:
Byte3 für LED15..12, Byte2 für LED11..8, Byte1 für LED7..4 und Byte0 für LED3..0

Vorgegebener Quelltext [zylonMatrixBlinker/zylonMatrixBlinkerAufg.h]
#include <avr/io.h>
#include <avr/interrupt.h>
 
volatile unsigned char vram[] = {0,0,0,0}; // LED 4er Gruppen
volatile unsigned int ticks = 0; // Zaehler für 2ms Ticks
 
int main() {
  DDRB = 0xFF;          // PORTB als Ausgang
  PORTD = 0x70;         // PullUps an
  /*
   * Aufgabe 1 Timer initalisieren Systemtakt 4MHz Aufruf mit 500Hz
   */
  sei();
  while (1) {
    if ((PIND&(1<<PD4))==0){
      blinken();
    }
  }
  return 0;
}
void incLeds(){ // eine weitere Led links einschalten
  unsigned char i;
  for (i=0;i<4;i++){
    if(vram[i]>=15){
      continue; // zur Bedingung in der For-Schleife springen
    }
    else{
      vram[i]=vram[i]*2+1;
      break; // die For-Schleife verlassen
    }
  }
}
void my_delay_ms(unsigned int n){ // delay ms mit Ticks
  /*
   * Aufgabe 2 delay mit ticks 
   */
}
void clearLeds(){ // alle Led aus
  /*
   * Aufgabe 3 vram loeschen
   */
}
void blinken(){ // ein Blinkzyklus
 /*
  * Aufgabe 4 blinken lassen
  */
}
ISR(TIMER0_COMPA_vect) { // jede 2ms
  static unsigned char i = 0;
  static const unsigned char vramEin[] = {0b11100000, 0b11010000, 0b10110000, 0b01110000};
  ticks++; // ein Tick weiter
  PORTB = vramEin[i] | vram[i];
  if (i < 3) i++; // vram durchgehen
  else i = 0;
}
 

Ermitteln Sie die Einstellungen um 8Bit Timer0 im CTC-Mode bei 4MHz Systemtakt mit 500Hz die ISR aufrufen zu lassen.

Entwicklen Sie den Quellcode für my_delay_ms(..) unter Verwendung des ticks-Zählers. Tipp Sie dürfen ticks dabei auch auf 0 setzen.

Entwickeln Sie den Quellcode für clearLeds() der alle Elemente des Feldes vram[] auf 0 setzt.

Entwickeln Sie den Quellcode für blinken():

Lösung anzeigen..

Aufgabe: Leuchtbalken mit Tasten einstellen

Byte 1 0
LED 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Phase 3 2 1 0
Nibble High Low High Low
PB7..4 0b0111 0b1011 0b1101 0b1110

Die Datenstruktur für das vram kann speichersparsamer gestaltet werden:

Zwei Byte: Byte1 für LED15..8 und Byte0 für LED7..0

unsigned char vram[] = {0,0}; // Videospeicher

Die Ausgabe in der ISR erfolgt wieder in 4 Phasen, eine pro ISR-Aufruf:

Erstellen Sie eine ISR ISR(TIMER0_COMPA_vect) mit diesem Verhalten CTC-Interrupt 400Hz bei 1Mhz Systemtakt.

Der Leuchtbalken und ausgebenBalken()

Zwei globale Variablen sind vorgegeben:

unsigned char position=7; // Balkenposition
unsigned char balken[2][8]={{0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80},{0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff}};

Erstellen Sie eine Funktion ausgebenBalken() die das Muster für position ins vram schreibt von balken.

Erstellen Sie eine Funktion main() mit Aufruf der Initalisierung, der Abfage der Tasten und des Aufrufs von ausgebeBalken() zur Entprellung der Tasten können Sie die Funktion keycheck() verwenden.

Lösung anzeigen..

Für Checker: Unterschiedliche Helligkeit (ich hab noch keine Lösung)

Vier verschiedene Helligkeiten sollen die LED annehmen können: {Aus,1/3,2/3, An} .Beim Leuchtblaken beginnen die LED beginnen nun erst mit 1/3 zu leuchten, erst wenn sie An sind, wird bei Tastendruck die nächste LED angegangen.

Tipps: Vram-Datenstruktur muss geändert werden. Pulsweitenmodulation. Ein ganzer Zyklus ist nun drei mal länger.