Zylonenauge I/O-Belegung
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
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: 11T0..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.
- Bei einer Ja-Stimme leuchtet nur L0
- bei zwei Ja-Stimmen leuchten L0 und L1
- bei drei Ja-Stimmen leuchten L0..L2
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