MezData-Logo Creative Commons License 363 Lösungen Button :AVR: Gemultiplexte Punktmatrixanzeige

Punktmatrixanzeige zur Ausgabe von Zeichen

Anschluss an µController

Zeilen R1..R7 an PA0..PA6 pos. Logik

Spalten C1..C5 an PC0..PC4 über Treiberbaustein. -> pos. Logik

LED leuchtet wenn Zeile = 1 und Spalte = 1.

Balken wandert von Spalte 1 bis Spalte 5

Assembler [Quellcode] C-Code [Quellcode]
.include "m16def.inc"

.def tmp = R16      ;tmp-Register zum Arbeiten
.def tmp2 = R17
.def spalte = R18   ;Spalte fuer Darstellung

    jmp reset       ;Einsprung nach Reset
    .org $2a        ;folgender Code ab Adresse $2a
reset:
    ldi tmp,high(RAMEND);Oberste RAM-Adresse holen
    out SPH, tmp        ;Stack-Pointer initialisieren
    ldi tmp,low(RAMEND) 
    out SPL, tmp
    ldi tmp,$ff
    out DDRA,tmp    ;PA als Ausgang
    out DDRC,tmp    ;PC als Ausgang
    ldi spalte,1    ;Spalte initialisieren  
    out PORTA,tmp   ;alle ZeilenLED an
loop:
    out PORTC,spalte;Spalte einschalten
    rol spalte      ;naechste Spalte
    sbrc spalte,5   ;wenn Spalte 6
    ldi spalte,1    ;dann wieder Spalte 1
    rcall wait      ;warte zum Anzeigen
    rjmp loop

wait:
    ldi tmp,100     ;aeusseren Zaehler laden 100 ms
wl1:
    ldi tmp2,250    ;inneren Zaehler 1ms bei 1Mhz
wl2:
    nop
    dec tmp2        ;tmp2--
    brne wl2        ;Sprung wenn nicht null
    dec tmp         ;tmp--
    brne wl1        ;Sprung wenn nicht null
    ret
#include <avr/io.h>     // Definitionen laden
#include <util/delay.h> // Delay-Bibliothek laden

int main(){
  unsigned char spalte=1; // erste Spalte
  DDRA=0xff;    // PA als Ausgang
  DDRC=0xff;    // PC als Ausgang
  PORTA=0xff;   // alle LED an
  while(1){     // Endlosschleife
    PORTC = spalte; // Spalte anschalten
    spalte *= 2;    // naechste Spalte
    if (spalte > 0b00010000)
      spalte = 1;
    _delay_ms(100); // warte 100ms
  }
  return 0;
}

Ausgeben eines Zeichens mit indirekter Adressierung des Programmspeichers

Assembler [Quellcode] C-Code [Quellcode]
.include "m16def.inc"

.def tmp = R16      ;tmp-Register zum Arbeiten
.def tmp2 = R17
.def spalte = R18   ;Spalte fuer Darstellung

    jmp reset       ;Einsprung nach Reset
    .org $2a        ;folgender Code ab Adresse $2a
reset:
    ldi tmp,high(RAMEND);Oberste RAM-Adresse holen
    out SPH, tmp        ;Stack-Pointer initialisieren
    ldi tmp,low(RAMEND) 
    out SPL, tmp
    ldi tmp,$ff
    out DDRA,tmp    ;PA als Ausgang
    out DDRC,tmp    ;PC als Ausgang
spalte1:
    ldi spalte,1    ;Spalte1 initialisieren
    ldi ZH, high(daten*2)   ;Datenzeiger initialisieren
    ldi ZL, low(daten*2)
nspalte:
    lpm tmp, z+     ;lade Daten aus Flash
    out PORTA,tmp   ;ausgeben Spalte
    out PORTC,spalte;Spalte einschalten
    rcall wait      ;warte zum Anzeigen
    rol spalte      ;naechste Spalte
    sbrc spalte,5   ;wenn Spalte 6
    rjmp spalte1    ;dann wieder Spalte 1
    rjmp nspalte    ;sonst naechste Spalte

wait:
    ldi tmp,10      ;aeusseren Zaehler laden 10 ms
wl1:
    ldi tmp2,250    ;inneren Zaehler 1ms bei 1Mhz
wl2:
    nop
    dec tmp2        ;tmp2--
    brne wl2        ;Sprung wenn nicht null
    dec tmp         ;tmp--
    brne wl1        ;Sprung wenn nicht null
    ret

daten:
    .db $08,$04,$7E,$04,$08
#include <avr/io.h>     // Definitionen laden
#include <util/delay.h> // Delay-Bibliothek laden

const unsigned char daten[]={0x08,0x04,0x7e,0x04,0x08};
 // Tabelle mit Daten

int main(){
  unsigned char spalte=1,dzeiger=0; // erste Spalte
  DDRA=0xff;    // PA als Ausgang
  DDRC=0xff;    // PC als Ausgang
  while(1){     // Endlosschleife
    PORTA = daten[dzeiger++]; // Zeile laden
    PORTC = spalte; // Spalte anschalten
    spalte *= 2;    // naechste Spalte
    if (spalte > 0b00010000)
      spalte = 1;
      dzeiger = 0;
    _delay_ms(10); // warte 10ms
  }
  return 0;
}

Ausgeben mehrerer Zeichen mit indirekter Adressierung des Programmspeichers

Assembler [Quellcode] C-Code [Quellcode]
.include "m16def.inc"

.def tmp = R16      ;tmp-Register zum Arbeiten
.def tmp2 = R17
.def spalte = R18   ;Spalte fuer Darstellung
.def zeichen = R19  ;Index des Zeichens
.def durchlauf = R20

    jmp reset       ;Einsprung nach Reset
    .org $2a        ;folgender Code ab Adresse $2a
reset:
    ldi tmp,high(RAMEND);Oberste RAM-Adresse holen
    out SPH, tmp        ;Stack-Pointer initialisieren
    ldi tmp,low(RAMEND) 
    out SPL, tmp
    ldi tmp,$ff
    out DDRA,tmp    ;PA als Ausgang
    out DDRC,tmp    ;PC als Ausgang
spalte1:
    inc durchlauf   ;weiterer Durchlauf
    cpi durchlauf,50;nach 50 Durchlauf
    brlo nix
    clr durchlauf
    inc zeichen     ;neues Zeichen
    andi zeichen,1
nix:
    ldi spalte,1    ;Spalte1 initialisieren
    ldi ZH, high(daten*2)   ;Datenzeiger initialisieren
    ldi ZL, low(daten*2)
    ldi tmp,5       ;5 Byte pro Zeichen
    mul tmp,zeichen ;Position in der Tabelle
    add ZL,R0       ;Addiere Position
    adc ZH,R1
nspalte:
    lpm tmp, z+     ;lade Daten aus Flash
    out PORTA,tmp   ;ausgeben Spalte
    out PORTC,spalte;Spalte einschalten
    rcall wait      ;warte zum Anzeigen
    rol spalte      ;naechste Spalte
    sbrc spalte,5   ;wenn Spalte 6
    rjmp spalte1    ;dann wieder Spalte 1
    rjmp nspalte    ;sonst naechste Spalte

wait:
    ldi tmp,10      ;aeusseren Zaehler laden 10 ms
wl1:
    ldi tmp2,250    ;inneren Zaehler 1ms bei 1Mhz
wl2:
    nop
    dec tmp2        ;tmp2--
    brne wl2        ;Sprung wenn nicht null
    dec tmp         ;tmp--
    brne wl1        ;Sprung wenn nicht null
    ret

daten:
    .db $08,$04,$7E,$04,$08,$10,$20,$7E,$20,$10
#include <avr/io.h>     // Definitionen laden
#include <util/delay.h> // Delay-Bibliothek laden

const unsigned char daten[2][5]={{0x08,0x04,0x7e,0x04,0x08},
                                 {0x10,0x20,0x7e,0x20,0x10}};
 // Tabelle mit Daten

int main(){
  unsigned char spalte=1,dzeiger=0,zeichen=0,durchlauf=0;
  DDRA=0xff;    // PA als Ausgang
  DDRC=0xff;    // PC als Ausgang
  while(1){     // Endlosschleife
    PORTA = daten[dzeiger++]; // Zeile laden
    PORTC = spalte; // Spalte anschalten
    spalte *= 2;    // naechste Spalte
    if (spalte > 0b00010000)
      spalte = 1;
      dzeiger = 0;
      durchlauf++;
      if (durchlauf > 50){
        durchlauf = 0;
        zeichen = 1 - zeichen;
      }
    }
    _delay_ms(10); // warte 10ms
  }
  return 0;
}

Punktmatrixanzeige zur Ausgabe von Zeichen mit Interruptsteuerung

[AVR-GCC-Tutorial: Interrupts] [ATmega16 Headerdatei: iom16.h]

Assembler [Quellcode] C-Code [Quellcode]
.include "m16def.inc"

.def tmp = R16      ;tmp-Register zum Arbeiten
.def tmp2 = R17
.def spalte = R18   ;Spalte fuer Darstellung
.def zeichen = R19  ;Index des Zeichens
.def durchlauf = R20;Zaehler fuer Zeichenwechsel
.def itmp = R21     ;tmp-Register bei Interrupt
.def led = R22      ;RGB-LED animieren

    jmp reset       ;Einsprung nach Reset
    .org OVF0addr   ;Einsprung nach Timer0 Ueberlauf
    jmp isr_timer   ;nach ISR
    .org $2a        ;folgender Code ab Adresse $2a

isr_timer:
    in itmp,SREG    ;SREG retten
    push itmp
    sbrs spalte,5   ;wenn nicht Spalte 6
    rjmp nspalte    ;dann naechste Spalte
    inc durchlauf   ;weiterer Durchlauf
    cpi durchlauf,50;nach 50 Durchlauf
    brlo nix
    clr durchlauf
    inc zeichen     ;neues Zeichen
    andi zeichen,1
nix:
    ldi spalte,1    ;Spalte1 initialisieren
    ldi ZH, high(daten*2)   ;Datenzeiger initialisieren
    ldi ZL, low(daten*2)
    ldi itmp,5      ;5 Byte pro Zeichen
    mul itmp,zeichen    ;Position in der Tabelle
    add ZL,R0       ;Addiere Position
    adc ZH,R1
nspalte:
    lpm itmp, z+    ;lade Daten aus Flash
    out PORTA,itmp  ;ausgeben Spalte
    in itmp, PORTC
    andi itmp,0b11100000
    or itmp,spalte
    out PORTC,itmp  ;Spalte einschalten
    rol spalte      ;naechste Spalte
    pop itmp
    out SREG,itmp
    reti            ;return from Interrupt

reset:              ;Hauptprogramm
    ldi tmp,high(RAMEND);Oberste RAM-Adresse holen
    out SPH, tmp        ;Stack-Pointer initialisieren
    ldi tmp,low(RAMEND) 
    out SPL, tmp
    ldi tmp,$ff
    out DDRA,tmp    ;PA als Ausgang
    out DDRC,tmp    ;PC als Ausgang
    ldi tmp,3       ;Systemtakt / 64
    out TCCR0,tmp
    in tmp,TIMSK    ;Timerinterrupt einschalten
    ori tmp, 1 << TOIE0
    out TIMSK,tmp
    sei             ;globale Interruptfreigabe
loop:
    inc led         ;naechste Farbe
    andi led,7      ;nur von 0 bis 7
    mov tmp,led
    swap tmp        ;vertausche Nibble
    lsl tmp         ;und noch einmal schieben
    in tmp2,PORTC   ;schreibe auf PORTC
    andi tmp2,0b00011111
    or tmp2,tmp
    out PORTC,tmp2
    rcall wait
    rjmp loop

wait:
    ldi tmp,150     ;aeusseren Zaehler laden 150 ms
wl1:
    ldi tmp2,250    ;inneren Zaehler 1ms bei 1Mhz
wl2:
    nop
    dec tmp2        ;tmp2--
    brne wl2        ;Sprung wenn nicht null
    dec tmp         ;tmp--
    brne wl1        ;Sprung wenn nicht null
    ret


    

daten:
    .db $08,$04,$7E,$04,$08,$10,$20,$7E,$20,$10
#include <avr/io.h>     // Definitionen laden
#include <util/delay.h> // Delay-Bibliothek laden
#include <avr/interrupt.h> // Interrupt Vektroren laden

const unsigned char daten[2][5]={{0x08,0x04,0x7e,0x04,0x08},
                                 {0x10,0x20,0x7e,0x20,0x10}};

volatile unsigned char zeichen=0;

ISR(TIMER0_OVF_vect){
  static unsigned char spalte=1,dzeiger=0,durchlauf=0;
  PORTA = daten[zeichen][dzeiger++]; // Zeile laden
  PORTC = (PORTC & 0b11100000) | spalte; // Spalte anschalten
  spalte *= 2;    // naechste Spalte
  if (spalte > 0b00010000){
    spalte = 1;
    dzeiger = 0;
    durchlauf++;
    if (durchlauf > 50){
      durchlauf = 0;
      zeichen = 1 - zeichen;
    }
  }
}

int main(){
  unsigned char led =0;
  TCCR0 = 3;    // Systemtakt / 64
  TIMSK |= (1<<TOIE0); // Timerinterrupt frei geben
  DDRA=0xff;    // PA als Ausgang
  DDRC=0xff;    // PC als Ausgang
  sei();        // globale Interruptfreigabe
  while(1){     // Endlosschleife
    led++;
    led &= 7;
    PORTC = (PORTC & 0b00011111) | (led<<5);
    _delay_ms(150); // warte 150ms
  }
  return 0;
}

Liste der Interrupt Vektornamen für C

  1. INT0_vect External Interrupt Request 0
  2. INT1_vect External Interrupt Request 1
  3. TIMER2_COMP_vect Timer/Counter2 Compare Match
  4. TIMER2_OVF_vect Timer/Counter2 Overflow
  5. TIMER1_CAPT_vect Timer/Counter1 Capture Event
  6. TIMER1_COMPA_vect Timer/Counter1 Compare Match A
  7. TIMER1_COMPB_vect Timer/Counter1 Compare Match B
  8. TIMER1_OVF_vect Timer/Counter1 Overflow
  9. TIMER0_OVF_vect Timer/Counter0 Overflow
  10. SPI_STC_vect Serial Transfer Complete
  11. USART_RXC_vect USART, Rx Complete
  12. USART_UDRE_vect USART Data Register Empty
  13. USART_TXC_vect USART, Tx Complete
  14. ADC_vect ADC Conversion Complete
  15. EE_RDY_vect EEPROM Ready
  16. ANA_COMP_vect Analog Comparator
  17. TWI_vect 2-wire Serial Interface
  18. INT2_vect External Interrupt Request 2
  19. TIMER0_COMP_vect Timer/Counter0 Compare Match
  20. SPM_RDY_vect Store Program Memory Ready
Assembler [Quellcode] C-Code [Quellcode]