MezData-Logo

Umgang mit Ports -Einlesen und Ausgeben mit Assembler

Zylonenauge I/O-Belegung

I/O Zylon

An PortB sind 16 Leuchtdioden (LED) in Matrixanordnung angeschlossen, für dieses Kapitel werden nur L0..L3 benötigt PB4 wird dabei auf 0 und PB5..7 auf 1 geschaltet. Grundeinstellung alle L aus:

PORTB <- 0xE0

L0 und L3 sollen leuchten


  ldi R16,0xe9  ;L0 und L3 an
  out PORTB,R16 ;ausgeben 
  ldi R16,0xff  ;PortB als Ausgang
  out DDRB,R16  ;einstellen

An PortD sind 3 Taster mit GND (0V) verbunden. Wenn ein Taster gedrückt wird wird der jeweilige Pin PD4..PD6 auf Masse (0V) gezogen. Die internen Pull-Ups müssen dazu eingeschaltet werden.

PD4 = !T0 usw.

Blockschaltbild eines Pins

Blockschaltbild

Befehle, die mit Ports zu tun haben

Befehl Operand Beschreibung Beispiel #Clk
IN Rd,P Einlesen eines Port in Rd in R16,PIND 1
OUT P, Rd Ausgeben von Rd in Port out PORTB,R16 1
SBI P, b Setze Bit b in Port P sbi PORTB,2 2
CBI P, b Lösche Bit b in Port P cbi PORTB,2 2
SBIC P, b Überspringe, wenn Bit b in Port P gelöscht sbic PIND,4 1/2/3
SBIS p, b Überspringe, wenn Bit b in Port P gesetzt sbis PIND,4
rjmp marke
1/2/3

Einlesen Taster T0 und Ausgeben auf L0

Beim Betätigen von Taster T0 soll die Led L0 leuchten. L0 <- !T0 wegen neg. Logik.

Mit Einlesen und Maskieren

Lösung wie von C bekannt, neu ist die Möglichkeit direkt ein PORT-Bit zu setzen (sbi) bzw. zu löschen (cbi).

mask:  
  ldi R16,0xe0
  out PORTB,R16    ;alle LED aus
  ldi R16,0xff
  out DDRB,R16     ;PortB als Ausgang
  out PORTD,R16    ;PortD die Pull-ups anschalten
loop:
  in R16,PIND      ;PIND einlesen
  andi R16,0x10    ;maskieren PD4 fuer T0
  breq setL0       ;falls T0 gedueckt 
  cbi PORTB,0      ;sonst PB0<-0
  rjmp loop
setL0:
  sbi PORTB,0      ;PB0<-1
  rjmp loop        ;immer wieder 

Mit Skip-Befehlen

Bei den Skip-Befehlen wird der darauf folgende Befehl übersprungen wenn das geprüfte Bit gesetzt (sbis) bzw. gelöscht (sbic) ist.

skip:  
  ldi R16,0xe0
  out PORTB,R16    ;alle LED aus
  ldi R16,0xff
  out DDRB,R16     ;PortB als Ausgang
  out PORTD,R16    ;PortD die Pull-ups anschalten
loop:
  sbis PIND,4      ;ueberspringe wenn T0=1
  rjmp setL0       ;wenn T0=0 setze L0
  cbi PORTB,0      ;sonst PB0<-0
  rjmp loop
setL0:
  sbi PORTB,0      ;PB0<-1
  rjmp loop        ;immer wieder 

Welche Lösung ist besser? In beiden Lösungen benötigen alle verwendeten Befehle jeweils 16 Bit Speicher = 1-Wort, also eine Adresse im Programmspeicher. Die Ausführungszeiten der Befehle können in der Formelsammlung in der Spalte # Clocks nachgeschaut werden, dabei gilt bei mehrdeutigen Angaben wie 1/2 dies:

  • Branch-Befehle z.B. breq brauchen:
    • 1 Takt wenn der folgende Befehl ausgeführt wird
    • 2 Takte bei einem Sprung
  • Skip-Befehle z.B. sbic brauchen
    • 1 Takt wenn der folgende Befehl ausgeführt wird
    • 2 Takte bei einem Sprung über einen 1-Wort langen Befehl
    • 3 Takte bei einem 2-Wort-Befehl Übersprung (sind selten)

Aufgaben

Ermitteln Sie Speichergrösse in Anzahl Programmspeicher- (Wort-) Adressen für beide Lösungen.

Erstellen Sie für beide Lösungen einen Programm Ablauf Plan PAP.

Ermitteln Sie für beide Lösungen die (Schleifen-) Durchlaufzeiten für T0 offen und T0 gedrückt.

Lösungen Adressen mask: 12; skip: 11
PAP

T0..T2 einlesen und auf L0..L2 ausgeben

.def tmp = R16  ;R16 als temporaeres Register
init:
  ldi tmp,0xe0
  out PORTB,tmp ;alle LED aus
  ldi tmp,0xff
  out DDRB,tmp  ;PortB als Ausgang
  out PORTD,tmp ;PortD die Pull-ups anschalten
loop:
  in tmp,PIND   ;PIND einlesen
  lsr tmp       ;>>1
  lsr tmp       ;>>1
  lsr tmp       ;>>1
  lsr tmp       ;>>1
  com tmp       ;˘tmp
  andi tmp,0xe7 ;
  out PORTB,tmp ;an PortB ausgeben
  rjmp loop     ;immer wieder  

Stimmt die Lösung?

Überprüfen Sie auf Papier mit sinnvoll gewählten Testeingaben z.B. Kein Taster gedrückt usw.

Testen Sie die Lösung im Simulator.

Testen Sie die Lösung auf dem Z-Eye.

Einfache Schaltnetze simulieren

Mikro-Controller bzw. Speicher-Programmierbare-Steuerungen (SPS) werden oft auch eingesetzt um Schaltnetze zu realisieren. Eine logische Funktion kann durch geschickte Abfolgen von Assembler-Befehlen simuliert werden. Das Init ist schon geschehen, der loop-Code interessiert hier. Hierbei unberührte Ein- bzw. Ausgänge dürfen nicht tangiert werden!

L0 = PB0 usw.
PD4 = !T0 usw.

Logisches Und simulieren

Entwickeln Sie ein Assemblerprogramm für die Funktion L0 = T0 AND T1.

Lösung
loop:
  in tmp,PIND   ;Einlesen
  andi tmp,0x30 ;nur PD4 und PD5 betrachten
  breq setL0    ;T0&T1 gedrueckt?
  cbi PORTB,0   ;sonst PB0<-0
  rjmp loop;
setL0:
  sbi PORTB,0   ;PB0<-1
  rjmp loop;

Logisches Oder simulieren

Entwickeln Sie eine Lösung für die Funktionen L0 = T0 AND T1 AND T2, L1 = T1 OR T2.

Eine Lösung
loop:
  in tmp,PIND   ;Einlesen
  andi tmp,0x70 ;nur PD4 und PD5 betrachten
  breq setL0    ;T0&T1 gedrueckt?
  cbi PORTB,0   ;sonst PB0<-0
  rjmp weiter;
setL0:
  sbi PORTB,0   ;PB0<-1
weiter:
  in tmp,PIND   ;Einlesen
  com tmp       ;invertieren
  andi tmp,0x60 ;nur PD5 und PD6 betrachten
  brne setL1    ;T1|T2 gedrueckt?
  cbi PORTB,1   ;sonst PB1<-0
  rjmp loop
setL1:
  sbi PORTB,1   ;PB1<-1
  rjmp loop

Aufgabe Abstimmanzeige

Eine Abstimmanzeige soll realisiert werden. Wenn ein Taster T gedrückt wird bedeutet das Ja.

Entwickeln Sie ein Programm!

Eine mögliche Lösung?

.def anzahl = R17
loop:
  clr anzahl   ;warum nicht ldi?
  sbis PIND,4  ;T0 gedrueckt?
  inc anzahl   ;anzahl++
  sbis PIND,5
  inc anzahl
  sbis PIND,6
  inc anzahl
  breq aus0    ;nix gedrueckt?
  cpi anzahl,1
  breq aus1    ;einer gedrueckt?
  cpi anzahl,2
  breq aus2    ;zwei gedrueckt?
  ldi tmp,0xe7 ;sonst drei gedrueckt
  rjmp ausgabe
aus0:
  ldi tmp,0xe0
  rjmp ausgabe
aus1:
  ldi tmp,0xe1
  rjmp ausgabe
aus2:
  ldi tmp,0xe3
ausgabe:
  out PORTB,tmp 
  rjmp loop