68HC11 Mikrokontroller

1. Software

1.1. Interrupts

1.1.1 Timer Overflow Interrupt

Im Expanded Multiplex Modus liegt der Interrupt ab der Adresse $00D0 in Form eines JMP Befehls.

IrqInit ldaa #$7E       OP-Code für JMP Befehl
        staa $D0
        ldx  #IrqWork   Adresse der Interrupt Routine
        stx  $D1
        clr  IrqCnt
        ...
        ldaa #$80       TOI Flag setzen, PR1 und PR0 = 0
        staa TMSK2,Y    Timer IRQ freigeben
        cli             Interrupts freigeben
        rts

IrqWork inc  IrqCnt
        ldaa IrqCnt
        cmpa #30        30=1 Sekunde
        bne  Irq02
        clr  IrqCnt
        ...

Irq02   ldaa #$80       IRQ Service durch setzen von TOF
        staa TFLG2,Y
        rti

Der Vorteiler wird durch PR1 und PR0 auf 1 gesetzt, so daß alle 32,768 ms ein Interrupt ausgelöst wird. Der Interrupt muß am Anfang oder am Ende der Routine durch das Setzen des TOF Flags quittiert werden (sonst hängt der ganze Controller). Zum Setzen des Flags sollte nicht der BSET Befehl benutzt werden, da das TFLG2 Register vorher gelesen wird.

1.1.2 IRQ Interrupt

Im Expanded Multiplex Modus liegt der Interrupt ab der Adresse $00EE in Form eines JMP Befehls.

      bset OPTION,Y,#$20   IRQ = Flankensensitiv

Das IRQE Bit im Option-Register definiert die Sensitivität des IRQ Eingangs:

Bit = 0 = Pegelsensitiv

Bit = 1 = Flankensensitiv (negativ)

Das Setzen des Bits muß innerhalb der ersten 64 E-Zyklen nach einen RESET geschehen.

IrqInit ldaa #$7E      OP-Code für JMP Befehl
        staa $EE
        ldx  #IrqWork  Adresse der Interrupt Routine
        stx  $EF
        clr  IrqCnt
        ...
        cli            Interrupts freigeben
        rts

IrqWork inc  IrqCnt
        ldaa IrqCnt
        cmpa #30
        bne  Irq02
        clr  IrqCnt
        ...

Irq02   rti

Ein Interrupt Service ist nicht notwendig. Es sei denn, daß der Hardwarebaustein, der den Interrupt generiert, einen Service benötigt. Der Interrupt kann jederzeit durch SEI gesperrt und durch CLI wieder freigegeben werden.

In diesem Beispiel wird der Interrupt aus dem I2C-Uhrenbaustein PCF8583 gewonnen. Die RTC hat einen Ausgang, der zyklisch einen Sekundenimpuls mit einem Tastverhältnis von 50% liefert. Deshalb sollte die Interrupt Erkennung auf der fallenden Flanke erfolgen.

1.1.3 XIRQ Interrupt

Im Expanded Multiplex Modus liegt der Interrupt ab der Adresse $00F1 in Form eines JMP Befehls.

        ldaa #$90       /XIRQ freigeben
        tap

Freigeben des Interrupts durch setzen des X-Bits im Condition Code Register. Achtung: Das X-Bit kann ab jetzt nicht mehr gelöscht werden.

IrqInit ldaa #$7E       OP-Code für JMP Befehl
        staa $F1
        ldx  #IrqWork   Adresse der Interrupt Routine
        stx  $F2
        clr  IrqCnt
        ...
        cli             Interrupts freigeben
        rts

IrqWork inc  IrqCnt
        ldaa IrqCnt
        cmpa #30
        bne  Irq02
        clr  IrqCnt
        ...

Irq02   clr  RTC+$0D    Interrupt Service
        rti

Ein Interrupt Service ist nicht notwendig. Es sei denn, daß der Hardwarebaustein, der den Interrupt generiert einen Service benötigt.

In diesem Beispiel wird der Interrupt aus dem Uhrenbaustein RTC-72421 gewonnen. Der Service wird hier durch löschen des IRQ-Flag in Register 13 erreicht.

1.2 I2C-Bus

1.2.1 Init

Der I2C-Bus wird bedient über den Controller Baustein PCF 8584.

i2cInit ldaa #$80       Software Reset
        staa i2cCntr
        ldaa #$55       Aktiver Monitor Modus
        staa i2cData
        ldaa #$A0       Select S2
        staa i2cCntr
        ldaa #$19       8MHz in, SCL = 45kHz
        staa i2cData
        ldaa #$C1       I2C geht in den Idle Modus
        staa i2cCntr
        rts

1.2.2 START/STOP

START und STOP Signal auf dem I2C-Bus erzeugen.

i2cStart ldaa #$C5
         staa i2cCntr
         rts

i2cStop  ldaa #$C3
         staa i2cCntr
         rts

Adresse des Slave auf den Bus senden. Bevor die Adresse gesendet wird, sollte der Bus auf Aktivität getestet werden. Dies wird durch das BB Flag angezeigt. Aus irgendeinem Grund wird dies aber nach der ersten erfolgreichen Übertragung auf dem Bus nicht mehr angezeigt. Das Busy Flag steht immer auf 0 obwohl die letzte Übertragung beendet ist. Es sollte aber auf 1 stehen. Deswegen kann nach einer sinnvollen Wartezeit der Einsprung in i2cSlv erfolgen.

i2cSlave ldab i2cCntr
         andb #$01        Test BB: Bus Busy ?
         beq  i2cSlave    ja
i2cSlv   staa i2cData     Send Slave Adresse
         rts

Das X Register zeigt auf einen Buffer. An erster Position steht die Anzahl der Bytes, die gelesen werden sollen. In der Regel verfügen die I2C Bausteine, wenn sie über mehr als ein Register haben, über eine Autoincrement Funktion. Soll nur ein Teil der Register Inhalte übertragen werden, dann wird die Übertragung durch senden eines Negativ Acknowledge abgebrochen.

Achtung: Als erstes wird die Adresse des Slave zurückgeliefert und erst dann die Inhalte der Register des I2C Bausteins.

1.2.3 Read

i2cRead ldaa 0,X
        deca
        staa i2cCnt
i2cR02  ldaa i2cCntr
        tab
        anda #$80          Test PIN: Byte empfangen ?
        bne  i2cR02        nein
        andb #$08          Test LRB: ACK ?
        bne  i2cR03        nein
        ldaa i2cData
        inx
        staa 0,X
        dec  i2cCnt
        bne  i2cR02
        ldaa #$40
        staa i2cCntr      Set ACK for negativ achnowledgement
        ldaa i2cData      Read Last Byte and send NAK
        inx
        staa 0,X
i2cR04  ldaa i2cCntr
        anda #$80         Test PIN
        bne  i2cR04
i2cR03  rts

1.2.4 Write

Das X Register zeigt auf einen Buffer, aus dem die Bytes zur Übertragung gelesen werden.

i2cWrt  ldaa 0,X
        inca
        staa i2cCnt
i2cW02  ldaa i2cCntr
        tab
        anda #$80          Test PIN: Byte gesendet ?
        bne  i2cW02        nein
        andb #$08          Test LRB: ACK ?
        bne  i2cW03        nein
        dec  i2cCnt
        beq  i2cW03        noch'n Byte senden
        inx
        ldaa 0,X
        staa i2cData       Send Byte
        bra  i2cW02
i2cW03  rts

1.2.5 Beispiele für RTC

Beispiel für das Setzen der Uhrzeit in einem PCF 8583 Baustein.

* Setzen der Uhrzeit im PCF 8583 am I2C-Bus
* $09,$00,$00,$00,$00,$02,$09,$23,$12,$98
*  |   |   |   |   |   |   |   |   |   `-- Jahr
*  |   |   |   |   |   |   |   |   `------ Monat
*  |   |   |   |   |   |   |   `---------- Tag
*  |   |   |   |   |   |   `-------------- Stunde
*  |   |   |   |   |   `------------------ Minute
*  |   |   |   |   `---------------------- Sekunde
*  |   |   |   `-------------------------- 1/100 Sekunde
*  |   |   `------------------------------ Status
*  |   `---------------------------------- Startadresse = 0
*  `-------------------------------------- 9 Bytes
*
SetTime ldaa #$A2       Adresse als Write
        jsr  i2cSlave   Adresse setzen
        jsr  i2cStart   START ausgeben
        ldx  #Buffer
        jsr  i2cWrt     Bytes schreiben
        jsr  i2cStop    STOP ausgeben
        rts

GetBuf  fcb  $01,$01

GetTime ldaa #$A2       Adresse als Write
        jsr  i2cSlv     Adresse setzen
        jsr  i2cStart   START ausgeben
        ldx  #GetBuf    Buffer für Register-Startadresse
        jsr  i2cWrt     Adresse ausgeben
        jsr  i2cStop    STOP ausgeben

        ldaa #$A3       Adresse als Read
        jsr  i2cSlv     Adresse setzen
        jsr  i2cStart   START ausgeben
        ldx  #i2cRBuf   Pointer auf Lese-Buffer setzen
        ldaa #9         Neun Bytes lesen
        staa 0,X
        jsr  i2cRead    Bytes einlesen
        jsr  i2cStop    STOP ausgeben
        rts

1.2.6 Beispiel für A/D und D/A

Dies Beispiel gilt für den I2C-Bus Baustein PCF 8591. Der Ausgang des D/A wird auf den Eingang eines A/D Kanals gelegt. Somit ergibt sich eine einfache Testmöglichkeit in dem das Ausgegebene Signal sofort wieder gemessen wird. Dazu dient das folgende Programm. Laut Datenblatt erfolgt die Übernahme der aktuellen Messung erst beim nächsten Meßzyklus. Um also an den momentanen A/D Wert zu kommen, muß die Messung zweimal ausgeführt werden.

Datas   fcb  #$02,$44,$FF

        ldaa #$96         Adresse als Write
        jsr  i2cSlv
        jsr  i2cStart
        ldx  #Datas
        jsr  i2cWrt
        jsr  i2cStop

        ldaa #$97         Adresse als Read
        jsr  i2cSlv
        jsr  i2cStart
        ldx  #i2cRBuf
        ldaa #6
        staa 0,X
        jsr  i2cRead
        jsr  i2cStop

        ldaa #$97         Adresse als Read
        jsr  i2cSlv
        jsr  i2cStart
        ldx  #i2cRBuf
        ldaa #6
        staa 0,X
        jsr  i2cRead
        jsr  i2cStop
D/A Value Output Voltage A/D Value

00

0,006

00

10

0,283

0F

20

0,587

1F

30

0,891

2F

40

1,196

3F

50

1,498

4F

60

1,802

5F

70

2,106

6F

80

2,411

7F

90

2,714

8F

A0

3,017

9F

B0

3,321

AF

C0

3,623

BF

D0

3,928

CF

E0

4,232

DF

F0

4,543

EF

FF

4,821

FE

Tabelle1: Uref = 4,86V =>19mV/Bit

1.2.7 Beispiel für D/A Wandler

Die Register des D/A Wandler TDA 8444 können nur beschrieben werden. Der Wert $3F wird auf Kanal 7 ausgegeben.

Datas   fcb  #$02,$F7,$3F

        ldaa #$48
        jsr  i2cSlv
        jsr  i2cStart
        ldx  #Datas
        jsr  i2cWrt
        jsr  i2cStop

D/A Value Ouput Voltage

00

0,028

04

0,402

08

0,551

0C

0,699

10

0,849

14

0,997

18

1,146

1C

1,295

20

1,439

24

1,587

28

1,737

2C

1,885

30

2,034

34

2,182

38

2,331

3C

2,480

3F

2,592

Tabelle2: Uref = 2.501V => 37,1mV/Bit

1.3 LCD Anzeige

Bei der Anzeige handelt es sich um ein 2*32 Zeichen Modul LM032L von Hitachi.

LcdReg  EQU   $C000
LcdDat  EQU   LcdReg+1

* String auf LCD ausgeben
LcdStr  ldaa  1,X Zeile
        ldab  #$40
        mul
        addb  0,X Spalte
        addb  #$80
        stab  LcdReg
        bsr   Wait1ms
        inx
        inx
        bsr   Wait1ms
loop    ldaa  0,X
        beq   End1
        staa  LcdDat
        bsr   Wait100
        inx
        bra   loop
End1    rts

* Zeichen auf LCD ausgeben
* D = A + B
* A = Adresse
* 80 + 0..19 = 1. Zeile
* C0 + 0..19 = 2. Zeile
* B = Zeichen = Ascii
LcdXY   staa  LcdReg
        bsr   Wait1ms
LcdChr  stab  LcdDat
        bsr   Wait100
        rts

* Warte 1 ms = 330, 2 ms = 660
Wait1ms pshx
        ldx #660
Wait1   dex
        bne Wait1
        pulx
        rts

* Warte 100 us
Wait100 psha
        ldab
Wait2   decb
        bne Wait2
        pula
        rts

2. Hardware

Meine Standardbeschaltung des 68HC11A1 besteht aus einem komfortablen Resetgenerator mit dem MAX691 und einer umschaltbaren RS232/RS485 Schnittstelle.

Supervisory Circuit:

Vom MAX691 werden in der Regel vier Funktionen benutzt:

Der Resetgenerator:

Der Reset Ausgang wird ganz normal mit dem Reset Eingang des 68HC11 verbunden. Hier passiert nichts aufregendes.

Der Power-Fail Komparator:

Dieser Teil wird als ganz normaler Komparator mißbraucht. Wird dem 68HC11 nach dem Anlegen der Versorgungsspannung über die serielle Schnittstelle ein $FF gesendet, dann beginnt er mit der Programmausführung seines EEPROM ab Adresse $B600. Nach einem Reset sendet der Controller von sich aus dieses Byte, d.h. wenn Jumper J1 offen ist und und Pin 10 des 691  (/PFO) auf 0 liegt, dann ist der serielle Ausgang PD1 über den 74HCT153 mit dem seriellen Eingang PD0 verbunden. Der 68HC11 hat im normalen Arbeitsmodus also die Möglichkeit sich selbst zu starten. R4 und C2 sind so dimensioniert, daß der Controller ca. 30ms dafür Zeit hat, dann wird die Verbindung getrennt und der serielle Eingang auf den externen Eingang gelegt, so daß eine normale Kommunikation mit der Außenwelt stattfinden kann.

Die Batterieumschaltung

Wenn ein externes CMOS RAM oder eine RTC vorhanden ist, dann wird der interne Batterieumschalter benutzt. Über Pin 1 wird ein 3,6V Akku angeschlossen, der im Betrieb über D1 und R5 mit ca. 640 uA geladen wird. Über R6 geht die Akkuspannung zur Überwachung auf einen der Analogen Eingänge.

Die Chip-Enable Output Kontrolle:

Wird ein SRAM über die Batterie mit Strom versorgt, dann ist es wichtig, daß er disabled werden kann, um eventuelle Störungen über die Daten- und Adressleitungen zu verhindern. Ist die Versorgungsspannung vorhanden, dann wird Pin 13 (/CEin) auf Pin 12 (/CEout) durchgeschaltet. Dazu wird der Eingang auf Masse gelegt und der Ausgang mit der Chip Enable Leitung des RAM verbunden. Im normalen Betrieb ist das RAM also immer enabled. Ist die Versorgungsspannung nicht vorhanden, dann wird Pin 12 auf die Batteriespannung gelegt und der Speicher ist disabled. Für den Speicher solte immer der Chip Enable Eingang (/CE) benutzt werden, denn wenn er High Pegel führt geht der Chip in seinen Power Down Modus. Der Energiebedarf zur Erhaltung der Speicherinhalte liegt dann bei einigen Nano Ampere. Die Lebensdauer der Daten ist dann fast nur Abhängig von der Selbstentladung des Akkus. Wird der Akku nur für den Speicher benötigt, kann er auch durch eine Lithium-Batterie ersetzt werden.

Automatische Umschaltung:

Wie unterm Power-Fail Komparator beschrieben wird der HCT153 für die Autostartfunktion des HC11 benutzt. Jumper 1 ist im Entwicklungsmodus geschlossen, weil nach einem Reset immer sofort ein neues Programm zum HC11 gesendet wird. Im Betriebsmodus wird der Jumper entfernt, damit sich der HC11 selbst sein Steuerbyte senden kann. Die gewünschte Funktion läßt sich aus dem Wahrheitsdiagramm des HCT153 ableiten:

Select Inputs

Data Inputs

S1 (2)

J1

S0 (14)

GND

I0 (6) I1 (5) I2 (4) I3 (3) /E (1) Y (7) Bemerkung

X

X

X

X

X

X

H

L

not used

L

L

L

X

X

X

L

L

Seriell Input

L

L

H

X

X

X

L

H

Seriell Input

L

H

X

L

X

X

L

L

not used

L

H

X

H

X

X

L

H

not used

H

L

X

X

L

X

L

L

HC11 Output

H

L

X

X

H

X

L

H

HC11 Output

H

H

X

X

X

L

L

L

not used

H

H

X

X

X

H

L

H

not used

Schnittstellentreiber

Über die Jumper J2 und J3 kann der HC11 entweder über eine RS232 mit dem MAX232 oder über eine RS485 mit dem MAX481 betrieben werden. Es kann auch der 75176 Treiber eingesetzt werden. Er hat aber einen ca 30fachen höheren Stromverbrauch. Nach einer vernünftigen Alternative wird noch gesucht. Eine Besonderheit hat der Transmitter (IC6). Sein Ausgang kann vom HC11 über PD2 in den Tri-State-Zustand geschaltet werden. Über diese Möglichkeit kann ein Netzwerk aufgebaut werden. Mehrere HC11 hängen auf der gleichen Leitung. Jeder HC11 besitzt eine eigene Adresse (Software) und darf seinen Transmitter nur dann aktivieren, wenn er vom PC dazu aufgefordert wurde. Das spart Schnittstellen beim PC und reduziert ganz erheblich den Verdrahtungsaufwand in der Wohnung.

2.1 Speichererweiterung

Die Anbindung eines Speicherbausteins ist Standardmäßig in fast jeder Applikation beschrieben. Die direkte Verbindung der R/W Leitung führt jedoch manchmal zu Problemen. Ich habe häufig beobachtet, daß einige Bytes nicht korrekt geschrieben oder gelesen wurden. Erst die Verknüpfung des R/W Signal mit dem E-Takt des HC11 sorgte immer für einen einwandfreien Betrieb.

2.2 Intel Bausteine

Der Zugriff auf Bausteine erfolgt beim HC11 synchron (Motorola Bausteine), d.h. nach dem Anliegen der Signale vom Daten-, Adressbus können die Information in Abhängigkeit von der R/W Leitung geschrieben, bzw. gelesen werden.

Motorola Bausteine arbeiten mit der Synchronen Betriebsart. Die Schreib- und Leseoperationen sind vom Pegel der R/W Leitung anhängig. Die Daten müssen dann innerhalb einer definierten Zeit auf dem Datenbus liegen.

Intel Bausteine arbeiten mit der Asynchronen Betriebsart. Für die Schreib- und Leseoperationen gibt es getrennte Leitungen.

Die Konvertierung vom synchronen in den asynchronen Modus läßt sich sich mit ein paar NAND Gattern hinkriegen:

2.3 RC5 Code Empfänger

Anschluß eines RC5 Code Empfängers an den HC11. Dies ist eine einfache Möglichkeit um Fernsteuerfunktionen zu realisieren. Es kann jede Handelsübliche Fernsteuerung benutzt werden, die den RC5 Code sendet (Philips- oder Universalfernbedienungen).

Adresse   Bedeutung Befehl Bedeutung
0 TV1 Fernsehempfänger 1 0..9 Zahl 0..9
1 TV2 Fernsehempfänger 2 16 Volume +
2 TXT Videotext 17 Volume -
3   Erweiterung für 0 und 1 18 Brightness +
4 LV LaserVision Player 19 Brightness -
5 VCR1 Video Recorder 1 20 Color Saturation +
6 VCR2 Video Recorder 2 21 Color Saturation -
7   Reserviert 22 Bass +
8 SAT1 Satellitenempfänger 1 23 Bass -
9   Erweiterung für 8 und 10 24 Treble +
10 SAT2 Satellitenempfänger 2 25 Treble -
11   Reserviert 26 Balance right
12 CD-VIDEO Compact Disc Video Player 27 Balance left
13   Reserviert 63 System Select
14 CD-PHOTO Photo auf CD Player 71 Dim local Display
15   Reserviert 77 Linear Function +
16 PREAMP1 Audio Vorverstärker 1 78 Linear Function -
17 TUNER Radio Tuner 80 Step up
18 REC1 Analoger Kassettenrecorder 81 Step down
19 PREAMP2 Audio Vorverstärker 2 82 Menu on
20 CD Compact Disc Player 83 Menu off
21 COMBI Audio Rack oder Aufnahmegerät 84 Display A/V System Status
22 SAT Audio Satellitenempfänger 85 Step left
23 REC2 DCC Recorder 86 Step right
24   Reserviert 87 Acknowledge
25   Reserviert    
26 CR-R Beschreibbare CD    
27..31   Reserviert    

Die Bedienungsbefehle sind nur ein Auszug aus allen Befehlen.

2.4 Tastatur

2.5 LCD Anzeige

Ansteuerung des LM032L. Ein 2*20 Zeichen LCD Modul von Hitachi. Obwohl die Pulsbreite für das Enable Signal (Pin 6) mit Min = 450 ns spezifiziert ist, funktioniert die Ansteuerung  durch einen HC11 mit 8 MHz Takt (2 Mhz E-Takt) noch ganz hervorragend.

Pin No Symbol Level

Function

1

Vss

-

0V

 

2

Vdd

-

+5V

Power supply

3

Vo

-

LCD Drive

 

4

RS

H/L

L: Instruction code input
H: Data input

5

R/W

H/L

H: Data read
L: Data write

6

E

H, H > L

   

7

DB0

H/L

   

8

DB1

H/L

   

9

DB2

H/L

   

10

DB3

H/L

   

11

DB4

H/L

   

12

DB5

H/L

   

13

DB6

H/L

   

14

DB7

H/L

   

Früher gab es an dieser Stelle noch Links auf die Datenblätter aller verwendeten IC's. Aber die Seiten der Halbleiterhersteller ändern sich so schnell, das einem schon fast schwindlig dabei wird. Wer interesse daran hat kann sie von mir bekommen. Auf dieser Seite sind sie nicht vorhanden, da sie im PDF Format vorliegen, und das verbraucht einfach zu viel Speicherplatz.

68HC11A0       293.214 Bytes
HM 62256       158.193 Bytes
MAX 232      1.224.812 Bytes
MAX 481        165.936 Bytes
MAX 691        160.785 Bytes
74 HCT 00       96.632 Bytes
74 HCT 139      45.775 Bytes
74 HCT 153      21.737 Bytes
74 HCT 573      62.704 Bytes
PCF 8584       167.211 Bytes
PCF 8583       121.730 Bytes
SAA 3049       157.689 Bytes
SFH 5110        39.789 Bytes
8705           323.680 Bytes
             3.039.887 Bytes