Inhalt
1. Einleitung 2
2. Die verwendeten I²C-Bus-Register 2
3. Programmversion ohne Bedienoberfläche 3
4. Programmversion mit Bedienoberfläche 11
4.1. Grundlegende Funktion von mC- und PC-Programm 11
4.2. Inbetriebnahme mit dem Microcontroller-Board 11
4.3. Hilfesystem 11
4.4. Anhang 12
4.4.1. Initialisierung 12
4.4.2. Kommunikationszeichen 12
4.4.3. Gespeicherte Einstellungen 12
4.4.4. Statuszustände in mC und PC 13
4.4.5. Die Formulare und Module des PC-Programms 14
4.4.5.1. FormMain 14
4.4.5.2. FormKonfig 32
4.4.5.3. FormVerbinden 34
4.4.5.4. FormInfo 36
4.4.6. Das mC-Programm 37
Einleitung
Das Programm steuert ein I2C-Bus-System. Dabei bedient es sich vorgegebener Hardwaretreiber, die softwaremäßig angesteuert werden und somit den Bus ansprechen.
Der Benutzer sendet die Daten vom PC aus über die serielle Schnittstelle an den Microcontroller. Dieser steuert über die spezielle Hardware den Bus. Empfangsseitig arbeitet auch ein Microcontroller, der die Daten wiederum über die serielle Schnittstelle zum PC überträgt.
Die Realisierung der Bedienerführung des Programms erfolgte in zwei Versionen. Die erste Version, die lediglich als Vorversion zur letztgültigen zweiten Version gedachte war, besteht nur aus dem in Assembler geschriebenen Programm für den Microcontroller, das über ein Terminalprogramm kommuniziert. Einstellungen müssen direkt im Programmcode vorgenommen und dieser anschließend erneut assembliert werden.
Die zweite Version besteht aus einem Assembler-Programm und einem auf Microsoft Windows basierenden Programm für den PC, das mit dem Assembler-Programm kommuniziert.
Die verwendeten I²C-Bus-Register
Die Hardwaretreiber des Busses werden von der Software angesprochen, indem diese entsprechende Werte in die zuständigen Register schreibt. Es gibt hierfür vier Register, die wie im folgenden erklärt zu verwenden sind.
In den ersten sieben Bits A0-A6 wird die eigene Adresse gespeichert, mit der der Teilnehmer im Bus angesprochen werden kann. GC bestimmt, ob das Gerät auf einen General Call reagiert; wobei 0 diesen erlaubt und 1 diesen ignoriert.
Bei einem Transmitter wird in dieses Register das zu übertragende Byte geschrieben. Ein Receiver zeigt damit das soeben empfangene Byte.
CR2 |
ENS1 |
STA |
STO |
SI |
AA |
CR1 |
CR0 |
Die Bits CR0, CR1, CR2 legen die Übertragungsrate des Busses fest. Das Setzen von ENS1 aktiviert die Bus-Schnittstelle. Setzen von STA oder STO bewirkt eine Start- beziehungsweise Stoppaufforderung an den Bus. STA muß anschließend wieder rückgesetzt werden, STO macht dies selbständig. SI ist das Interrupt-Flag, welches bei jedem Bus-Interrupt gesetzt wird und anschließend rückgesetzt werden muß, um die Busübertragung fortzusetzen. Ein gesetztes AA läßt das Geräte ein Acknologe schicken, wenn es die Kommunikation erfordert, ein rückgesetztes AA hingegen läßt das Gerät nicht reagieren und damit ein Not Acknolege schicken.
Dieses Byte enthält nach einem vom Bus ausgelösten Interrupt den Status, in dem sich der Bus befindet und der den Interrupt ausgelöst hat.
Programmversion ohne Bedienoberfläche
Dieses Programm erfüllt die vier Funktionen Master Transmitter, Master Receiver, Slave Transmitter, Slave Receiver.
Zu Starten ist das Programm bei der Adresse 8000h.
Um die Übertragung als Master zu beginnen, muß „a“ eingegeben werden. Abhängig vom Richtungsbit, das bei dieser Version im Programmcode in den Routinen „08h Start gesendet“ beziehungsweise „10h Repeated-Start gesendet“ eingestellt werden muß, wird das Terminal zum Master Transmitter oder zum Master Receiver.
Da das Programm alle für den Betrieb als Slave nötigen Interruptroutinen enthält, kann es auch als Slave angesprochen werden. Hierbei wird an Hand des empfangenen Richtungsbit zwischen Transmitter und Receiver unterschieden und automatisch die entsprechende Routine angesprochen.
Die Übertragung kann vom Transmitter, gleich ob Master oder Slave, mit „!“ beendet werden.
Zu beachten ist, daß alle gleichzeitig am Bus verwendeten Programme unterschiedliche eigene Adressen besitzen müssen, was im Programmcode im entsprechenden Register S1ADR in der Routine „Initialisierung“ einzustellen ist.
;************************************************************
; I2C-Bus
; Entwickelt für µC-Kit von Kern
; Michael Popp; Februar 1998
;************************************************************
;************************************************************
; Vereinbarungen
charin code 2730h ;Unterprogramm Zeicheneingabe
charout code 273Ch ;Unterprogramm Zeichenausgabe
anfang code 8000h ;Start-Adresse
inter code 802Bh ;Adresse für I2C-Interrupt
haupt code 8200h ;Adresse Hauptprogramm
s1adr data 0dbh ;Eigene Bus-Adresse
s1dat data 0dah ;Bus-Daten
s1con data 0d8h ;Bus-Kontrollen
s1sta data 0d9h ;Bus-Status
P1_6 bit 96h ;SCL-Pin
P1_7 bit 97h ;SDA-Pin
si bit 0dbh ;Interrupt Flag
aa bit 0dah ;Ackknowledge Flag
sta bit 0ddh ;Startbit
sto bit 0dch ;Stoppbit
es1 bit 0adh ;I2C-Bus-Interrupt aktivieren
;************************************************************
;************************************************************
; Hauptprogramm
org anfang
mov dptr,#haupt ;
clr a ;
jmp a+dptr ;
org haupt
call init ;Bus initialisieren
loop: mov a,s1sta
cjne a,#0F8h,loop ;Interrupts
call charin ;
cjne a,#61h,loop ;
call start ;
jmp loop ;
;************************************************************
;************************************************************
; Initialisierung
; -> /
; <- /
; cha ea, es1, P1_6, P1_7, s1adr, s1con
; subr /
init: setb ea ;Interrupts aktivieren
setb es1 ;I2C-Bus-Interrupts aktivieren
setb P1_6 ;
setb P1_7 ;
mov s1adr,#10000000b ;Eigene Busadresse, General Call aktiviert
mov s1con,#11000101b ;Controllregister
;------------------------------------------------------------
;S1CON: 1 1 0 0 0 1 0 1
; - ENS1 STA STO SI AA CR1 CR0
;------------------------------------------------------------
ret
;************************************************************
;************************************************************
; Starten
; -> /
; <- /
; cha aa, sta, si
; subr /
start: setb aa
setb sta ;Startbit setzen
clr si
ret
;************************************************************
;************************************************************
; Interruptroutinen
; -> /
; <- /
; cha s1dat, s1con, a
; subr charin, charout
;------------------------------------------------------------
; 00h alle Bus-Fehler
sta00:
reti
;------------------------------------------------------------
; 08h MT, MR Start gesendet
sta08:
mov S1DAT,#11000000b ;Richtungsbit auf senden
; mov S1DAT,#11000001b ;Richtungsbit auf empfangen
clr sta ;
clr sto ;
setb aa ;
clr SI ;
reti
;------------------------------------------------------------
; 10h MT, MR Repeated-Start gesendet
sta10:
mov S1DAT,#11000000b ;Richtungsbit auf senden
; mov S1DAT,#11000001b ;Richtungsbit auf empfangen
clr sta ;
clr sto ;
setb aa ;
clr SI ;
reti
;------------------------------------------------------------
; 18h MT Adresse+W gesendet, ACK empfangen
sta18: call charin ;Tastatureingabe
cjne a,#21h,lab18a ; ! zum Abbruch
setb sto ;Stopbit setzen
jmp lab18b ;Verarbeitung der Daten ueberspringen
lab18a: call charout ;
mov s1dat,a ;
lab18b: clr si ;Daten senden oder Verbindung beenden
reti
;------------------------------------------------------------
; 20h MT Adresse+W gesendet, NACK empfangen
sta20: setb STO ;Stop senden
clr SI
reti
;------------------------------------------------------------
; 28h MT Daten gesendet, ACK empfangen STANDARD
sta28: call charin ;Tastatureingabe
cjne a,#21h,lab28a ; ! zum Abbruch
setb sto ;Stopbit setzen
jmp lab28b ;Verarbeitung der Daten ueberspringen
lab28a: call charout ;
mov s1dat,a ;
lab28b: clr si ;Daten senden oder Verbindung beenden
reti
;------------------------------------------------------------
; 30h MT Daten gesendet, NACK empfangen
sta30: setb sto
clr si
reti
;------------------------------------------------------------
; 38h MT, MR Arbitration verloren beim Senden von Adresse oder Daten (Transmitter)
; beim NACK (Receiver)
sta38: setb sto
clr si
reti
;------------------------------------------------------------
; 40h MR Adresse+R gesendet, ACK empfangen
sta40: clr si ;auf Daten vom Slave warten
reti
;------------------------------------------------------------
; 48h MR Adresse+R gesendet, NACK empfangen
sta48: setb sto
clr si
reti
;------------------------------------------------------------
; 50h MR Daten empfangen, ACK gesendet STANDARD
sta50: mov A,s1dat ;Daten vom Slave in Akku
cjne a,#21h,lab50a ; ! von Slave zum Beenden
clr aa
jmp lab50b
lab50a: call charout ;Datenausgabe
lab50b: clr si
reti
;------------------------------------------------------------
; 58h MR Daten empfangen, NACK gesendet
sta58: setb sto
clr si
reti
;------------------------------------------------------------
; 60h SR Adresse+W empfangen, ACK gesendet
sta60: clr si
reti
;------------------------------------------------------------
; 68h SR Arbitration verloren als adressierter Master,
; Adresse+W empfangen, ACK gesendet
sta68: setb sto
clr si
reti
;------------------------------------------------------------
; 70h SR General-Call empfangen, ACK gesendet
sta70: clr si
reti
;------------------------------------------------------------
; 78h SR Arbitration verloren als adressierter Master,
; General-Call empfangen, ACK gesendet
sta78: setb sto
clr si
reti
;------------------------------------------------------------
; 80h SR Daten empfangen, ACK gesendet (adressiert) STANDARD
sta80: mov A,S1DAT ;Daten vom Master in Akku
call charout ;Zeichen ausgeben
clr si
reti
;------------------------------------------------------------
; 88h SR Daten empfangen, NACK gesendet (adressiert)
sta88: clr si
reti
;------------------------------------------------------------
; 90h SR Daten empfangen, ACK gesendet (General Call)
sta90: mov A,S1DAT ;Daten vom Master in Akku
call charout ;Zeichen ausgeben
clr si
reti
;------------------------------------------------------------
; 98h SR Daten empfangen, NACK gesendet (General Call)
sta98: clr si
reti
;------------------------------------------------------------
; A0h SR Stop oder Repeated-Start empfangen
staA0: clr si
reti
;------------------------------------------------------------
; A8h ST Adresse+R empfangen, ACK gesendet
staA8: mov r5,#00h ;
call charin ;Zeicheneingabe
cjne a,#21h,labA8a ; ! von Slave zum Beenden
mov r5,#0FFh
labA8a: call charout ;Zeichen ausgeben
mov S1DAT,A ;
clr si ;Uebertragung
reti
;------------------------------------------------------------
; BOh ST Arbitration verloren als adressierter Master,
; Adresse+R empfangen, ACK gesendet
staB0: setb sto
clr si
reti
;------------------------------------------------------------
; B8h ST Daten gesendet, ACK empfangen STANDARD
staB8: cjne r5,#0FFh,labB8b
mov a,#0FFh
jmp labB8c
labB8b: call charin ;Zeicheneingabe
cjne a,#21h,labB8a ; ! von Slave zum Beenden
mov r5,#0FFh
jmp labB8c
labB8a: call charout ;Zeichen ausgeben
labB8c: mov S1DAT,A ;
clr si ;Uebertragung
reti
;------------------------------------------------------------
; C0h ST Daten gesendet, NACK empfangen
staC0: clr si
reti
;------------------------------------------------------------
; C8h ST AA=0, letzte Daten gesendet, ACK empfangen
staC8: mov S1DAT,0FFh ;S1DAT=11111111b
clr si
reti
;************************************************************
;************************************************************
; Interruptsprünge
org inter
jmp intera
org 8F00h
intera:
mov A,S1STA ;Je nach Statusinhalt
mov dptr,#9000h ;Sprung auf jeweilige
jmp A+dptr ;SUB-Routine
;------------------------------------------------------------
;------------------------------------------------------------
org 9000h
jmp sta00
;------------------------------------------------------------
org 9008h
jmp sta08
;------------------------------------------------------------
org 9010h
jmp sta10
;------------------------------------------------------------
org 9018h
jmp sta18
;------------------------------------------------------------
org 9020h
jmp sta20
;------------------------------------------------------------
org 9028h
jmp sta28
;------------------------------------------------------------
org 9030h
jmp sta30
;------------------------------------------------------------
org 9038h
jmp sta38
;------------------------------------------------------------
org 9040h
jmp sta40
;------------------------------------------------------------
org 9048h
jmp sta48
;------------------------------------------------------------
org 9050h
jmp sta50
;------------------------------------------------------------
org 9058h
jmp sta58
;------------------------------------------------------------
org 9060h
jmp sta60
;------------------------------------------------------------
org 9068h
jmp sta68
;------------------------------------------------------------
org 9070h
jmp sta70
;------------------------------------------------------------
org 9078h
jmp sta78
;------------------------------------------------------------
org 9080h
jmp sta80
;------------------------------------------------------------
org 9088h
jmp sta88
;------------------------------------------------------------
org 9090h
jmp sta90
;------------------------------------------------------------
org 9098h
jmp sta98
;------------------------------------------------------------
org 90A0h
jmp staA0
;------------------------------------------------------------
org 90A8h
jmp staA8
;------------------------------------------------------------
org 90B0h
jmp staB0
;------------------------------------------------------------
org 90B8h
jmp staB8
;------------------------------------------------------------
org 90C0h
jmp staC0
;------------------------------------------------------------
org 90C8h
jmp staC8
;************************************************************
end
Programmversion mit Bedienoberfläche
Das in Kapitel 3 beschriebene Assembler-Programm wurde um zur Kommunikation mit dem PC nötigen Zeilen ergänzt und wird nun über die serielle Schnittstelle mit einem PC-Programm angesprochen. Erstellt wurde dieses mit der Entwicklungsumgebung Microsoft Visual Basic 5.0 Enterprise Edition.
Grundlegende Funktion von mC- und PC-Programm
Um den mC mit dem PC-Programm ansprechen zu können, muß sich der mC im I²C-Bus-Status F8h befinden. Nun kann vom PC-Programm die Verbindung zum mC erstellt werden. Dabei beginnt das Programm die serielle Schnittstelle des PCs zu beanspruchen. Dann sendet es den Befehl 80h an den mC, worauf dieser seinen Status F8h zu melden hat. Geschieht dies korrekt, so schickt der PC nun die Adresse, die das Terminal laut den Einstellungen anzunehmen hat, an den mC, wo sie im entsprechende Register S1ADR gelegt wird. Weiters aktiviert der mC nun den I²C-Bus und den zugehörigen Interrupt.
Zu Beginn jeder Interrupt Service Routine des I²C-Busses sendet der Microcontroller seinen aktuellen Status an den PC. Der PC hat ebenfalls seinen eigenen Status, der in der Variablen „Status“ gespeichert ist. Erhält nun der PC das OnComm-Ereignis, welches durch den Eingang von Daten über die serielle Schnittstelle ausgelöst wird, so wählt er in einer auf den aktuellen PC-Status bezogenen Case-Anweisung den auszuführenden Programmcode. Hier wird die vom Microcontroller kommende Nachricht, die nun den aktuellen Status des Microcontrollers enthält, eingelesen. Somit kann der PC seinen Status aktualisieren. Gleichzeitig wird ermittelt, ob der neue Status eine korrekte Fortsetzung des alten Status darstellt oder ob eine Fehler aufgetreten ist. Entsprechend verlaufen die weiteren Vorgänge im PC.
Bestimmte Statuszustände im PC erwarten sofort einen weiteren Eingang an Daten vom mC. Dazu wird im PC die Eigenschaft „Enabled“ des Hauptfenster „FormMain“ auf false gesetzt und der Timer aktiviert. Können nun wie erwartet Daten empfangen werden, so wird der Timer deaktiviert und das eingegangene Byte wird verarbeitet. Tritt jedoch das OnComm-Ereignis nicht auf, so schließt der PC nach Ablauf des Timers auf ein Fehlverhalten des mC und gibt eine Fehlermeldung am Bildschirm aus.
Inbetriebnahme mit dem Microcontroller-Board
Um das Programm testweise mit einem Entwicklungs-Board in Betrieb nehmen zu können, muß vorerst mittels eines Terminalprogramms das Assembler-Programm über die serielle Schnittstelle in den mC geladen werden. Dabei darf das PC-Programm noch keinen Anspruch auf die Schnittstelle erheben. Dann ist das mC-Programm an der Adresse 8000h zu starten und die Verbindung mit dem Terminalprogramm zu trennen.
Nun wird mit dem PC-Programm über die Schnittstelle die Verbindung zum mC hergestellt, anschließend kann auch die Busverbindung erfolgen. Entnehmen Sie nähere Beschreibungen zu diesen Schritten dem zugehörigen Hilfesystem.
Hilfesystem
Das zum Programm gehörende Hilfesystem wurde mit Microsoft Help Workshop 4.02 erstellt.
Es beschreibt die Bedienung des Programms, so daß nähere Erläuterungen in dieser Dokumentation nicht erforderlich sind.
Anhang
Initialisierung
Sofort nach dem die Verbindung zum Microcontroller hergestellt wurde sendet der PC entsprechend den in der Record-Variablen „Einstellungen“ gespeicherten Einstellungen die folgenden Werte an den Microcontroller.
PC-Variable |
mC-Variable |
Beschreibung |
Einstellungen.OwnAddress |
S1ADR.0 bis S1ADR.6 |
Terminal-Adresse |
Einstellungen.GetGC |
S1ADR.7 |
General Call annehmen |
Kommunikationszeichen
Mit den folgenden festgelegten Werten fordert der PC den mC zu bestimmten Aktionen auf. Der mC empfängt diese Aufforderungen im Hauptprogramm und führt die entsprechende Aktion auch dort aus.
Code von PC |
Beschreibung |
80h |
Verbindung zu mC herstellen; mC-Status an PC; I²C-Bus aktivieren |
81h |
Verbindung zu mC trennen; I²C-Bus deaktivieren |
82h |
Startaufforderung an Bus; CALL START |
83h |
Stoppaufforderung an Bus; SETB STO |
84h |
AA rücksetzen; CLR AA |
85h |
AA setzen; SETB AA |
Gespeicherte Einstellungen
In der Record-Variablen „Einstellungen“ befinden sich die folgenden Einstellungen. Diese Variable wird bei jedem Programmstart aus der Datei „I2C.ini“, die sich im aktuellen Verzeichnis befinden soll, geladen. Existiert die Datei nicht, so werden die Standardeinstellungen verwendet. Bei Programmbeendigung wird die aktuelle Variable „Einstellungen“ in dieser Datei gespeichert.
Beschreibung |
Auf General Call reagieren |
Eigene Adresse |
An Speichern der Daten erinnern |
Wartezeit nach Aufforderung |
Serielle Schnittstelle |
Ausgewählter Slave oder General Call |
Slavetyp |
Slaveadresse |
Statuszustände in mC und PC
|
Kennung |
Modus |
Beschreibung |
XX |
- |
PC ohne Verbindung |
LC |
- |
Link Controller; Verbindungsversuch zu mC |
00 |
Alle |
Bus-Fehler |
F8 |
- |
PC mit mC verbunden, kein Bus-Betrieb |
LB |
MT, MR |
Link Bus; Verbindungsversuch mit Bus |
08 |
MT, MR |
Start gesendet |
10 |
MT, MR |
Repeated-Start gesendet |
|