![]() ![]() INFO - FAQ - CC2-Forum - CCPro-Forum |
|
' =========================================================================== ' Demoprogramm: Zweite Serielle Schnittstelle mit 255-Byte-Empfangsbuffer ' In OCBASIC 1.12a_e1 für Open-Maxi von Dietmar Harlos am 23. April 2021 ' =========================================================================== ' Das Betriebssystem unterstützt eine Serielle Schnittstelle mit Empfangs- ' buffer, die mittels SCI2-Modul realisiert ist. Das SCI1-Modul ist also frei. ' In diesem Beispielprogramm wird das SCI1-Modul verwendet, um eine zweite ' Serielle Schnittstelle auf der Open-Maxi zu realisieren. Der Empfang wird ' interruptgesteuert mit 255-Byte-Ringpuffer durchgeführt. Anhand der ' Funktion rxdSCI1 kann der Anwender feststellen, ob wenigstens ein Byte vom ' SCI1-Modul empfangen und in den Buffer eingefügt wurde. ' Die Subroutinen und Funktionen im Einzelnen: ' initSCI1 ... SCI1-Modul initialisieren ' baudSCI1 ... Setzen der Baudrate des SCI1-Moduls ' putSCI1 .... Senden eines Bytes über das SCI1-Modul ' getSCI1 .... Empfangen eines Bytes über das SCI1-Modul (var=getSCI1) ' rxdSCI1 .... Feststellen, ob ein Byte empfangen wurde und im Buffer ist ' TXD2 liegt an PORT[33] und RXD2 liegt an PORT[34]. Das sind die beiden ' niederwertigsten Ports vom fünften Byteport (BYTEPORT[5]). ' Zum Testen dieses Demoprogramms muß TXD2 mit RXD2 verbunden werden. ' Es ließe sich natürlich noch Hardware-Handshake realisieren. Die Ports RTS2 ' und CTS2 sind dafür reserviert. ' Im Kapitel 11 ("Serial Communications Interface (S08SCIV2)") im Data Sheet ' zum MC9S08AW60-Mikrocontroller ist das SCI1-Modul beschrieben: ' https://www.nxp.com/docs/en/data-sheet/MC9S08AW60.pdf ' An dieser Stelle möchte ich mich bei Dirk von "das |_ Team" und bei Norbert ' für ihre Unterstützung bedanken. ' --- Definitionen ---------------------------------------------------------- INCLUDE "omax.def" 'Definitionen für die Open-Maxi DEFINE zssbuffer &h2aa 'Buffer an 1. Adresse hinter dem USER-RAM, 256 Bytes lang DIM zssarray BYTE 'Bitarray DIM Sci1Err BIT[1] OF zssarray 'signalisiert Fehler beim Empfang DEFINE fSci1Err 0 DIM head BYTE ' Hallo Welt DIM tail BYTE ' ^head ^tail DIM a,b,c BYTE 'temporäre Variablen ' --- Unsere eigene Assembler-Interruptroutine ------------------------------ ' Die folgende Assembler-Interruptroutine befindet sich im "Serial ' Communications Interface 1 - Receive"-Interrupt und wird gestartet, wenn ' das SCI1-Modul ein Byte empfangen hat. ' Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei ' im Akkumulator der Wert #iSCI1r und im X-Register die Adresse von FREERAM ' übergeben wird. Beendet werden muß die Routine mit RTS. Falls mit ' gelöschtem Carry-Bit ("CLC") beendet wird, führt das Betriebssystem ' die Systemfunktionen zum Interrupt weiter aus. Wird dagegen mit gesetztem ' Carry-Bit ("SEC", bzw. "STC") beendet, ignoriert das System den Interrupt. ' Die folgenden Subroutinen müssen am Anfang des Programms stehen und sollten ' sinnvollerweise in einer INCLUDE-Datei untergebracht werden. ' Das Schlüsselwort INLASM kennzeichnet die folgende PROCEDURE als ' Assemblerroutine (IAR). Dadurch, und daß sie unmittelbar am Anfang ' des Programms steht, wird sie zu einer IIAR, also zu einer Assembler- ' Interruptroutine, die bei einem aktivierten User-Interrupt gestartet wird. ' Der OCBASIC-Compiler setzt automatisch ein "GOTO main" vor diese Routine. PROCEDURE UIRSci1r_iiar INLASM ! cbeqa #iSCI1r,sci1r_is 'Unterscheidung der Interruptquellen ! jmp UIRSci1r_iiar_next+2 'zur nächsten IIAR in der Kette springen ' Empfangsinterrupt für SCI1 ' Hardware interrupt requested when RDRF flag is 1. ' In 8-bit mode, to clear RDRF, read SCIxS1 with RDRF = 1 and then read the ' SCI data register (SCIxD). ' Clear the NF, FE and PF bit by reading SCIxS1 and then read the SCIxD. #sci1r_is 'SCI1 receive ! lda SCI1S1 ! bit #%00000111 'NF FE PF ! bne sci1r_err ! lda SCI1D 'Byte aus Register lesen ! clrh ! ldx tail ! sta zssbuffer,x ! incx ! cmpx head ! beq sci1r_err_1 'Buffer voll? Dann Fehler-Flag setzen ! stx tail ! sec 'Carry-Flag setzen (Betriebssystem ignoriert den Interrupt) ! rts 'Rücksprung zum Betriebssystem #sci1r_err ! lda SCI1D 'Byte aus Register lesen #sci1r_err_1 ! bset fSci1Err,zssarray 'Fehler-Flag setzen ! sec 'Carry-Flag setzen (Betriebssystem ignoriert den Interrupt) ! rts 'Rücksprung zum Betriebssystem END PROCEDURE ' SCI1-Modul initialisieren PROCEDURE initSCI1 INLASM ! ldhx #130 'SCI baud rate = 20E6/(16*130) = 9615.4 Baud (0.16% Abweichung) ! sthx SCI1BDH ! clr SCI1C1 'SCI Control Register 1 (SCIxC1) ! mov #%00101100,SCI1C2 'SCI Control Register 2 (SCIxC2) - Sender, Empfänger und Empfangsinterrupt aktiv ! clr SCI1C3 'SCI Control Register 3 (SCIxC3) ! rts END PROCEDURE ' Senden eines Bytes über das SCI1-Modul PROCEDURE putSCI1(datenbyte) INLASM #putSCI1_1 ! brclr bTDRE,SCI1S1,putSCI1_1 'Transmit Data Register Empty Flag (TDRE) im SCI Status Register 1 (SCIxS1) ! sta SCI1D 'SCI Data Register (SCIxD) ! rts END PROCEDURE ' Empfangen eines Bytes über das SCI1-Modul ' getSCI1 ist eine Funktion, kein Befehl, also "var=getSCI1" statt "getSCI1 var" FUNCTION getSCI1 INLASM #getSCI1_1 ! lda tail ! sub head ! beq getSCI1_1 'keine Daten im Buffer? Dann auf Daten warten ! clrh ! ldx head ! lda zssbuffer,x ! incx ! stx head ! clrx 'FwPush ! swi END FUNCTION ' Feststellen, ob ein Byte von der zweiten Seriellen Schnittstelle geholt werden kann ' Die Routine liefert ON und OFF zurück, also -1 und 0. FUNCTION rxdSCI1 INLASM ! clrx ! lda tail ! sub head ! beq rxdSCI1_1 'keine Daten? Dann OFF zurückliefern ! decx #rxdSCI1_1 ! txa ! sta OSTEMP ! jmp FwPushW 'das Word OSTEMP:A auf dem Rechenstack speichern END FUNCTION ' Setzen der Baudrate des SCI1-Moduls PROCEDURE baudSCI1(baudratenkonstante) INLASM ! tsta ! bpl baudSCI1_1 ! add #2 #baudSCI1_1 ! and #%111 ! lsla ! tax ! clrh ! lda $0a26,x 'aus der Baudratentabelle des Betriebssystems lesen ! sta SCI1BDH ! lda $0a27,x ! sta SCI1BDL ! rts END PROCEDURE ' Debugging PROCEDURE zssdebug ? ?"head="head; ?" tail="tail; ?" Sci1Err="Sci1Err FOR a=0 TO 255 ?peek(zssbuffer+a); NEXT a ?:? RETURN END PROCEDURE #UIRSci1r_iiar_next 'hier hinter folgt die nächste IIAR '(sofern vorhanden) ' --- Hauptprogramm --------------------------------------------------------- #main 'durch die IIAR am Programmbeginn wird ein "GOTO main" erzeugt PrintSpc=ON 'SPACE vor einem dezimalen PRINT End2Host=ON 'Bei Programmende gleich in den Host-Modus wechseln head=0 'Initialisierungen tail=0 zssarray=0 UIRSci1r=ON 'User-Assemblerroutine für "SCI1 Receive" aktivieren initSCI1 'SCI1-Modul initialisieren und aktivieren baudSCI1 R9600 'R300 'R38400 'Baudrate setzen WHILE TRUE ?"Sende" FOR a=33 TO 75 putSCI1 a NEXT a ?"Empfangen: "; WHILE rxdSCI1 PUT getSCI1 'getSCI1 ist eine Funktion, kein Befehl, also var=getSCI1 WEND ? zssdebug PAUSE 25 WEND END 'Programmende ' --- INCLUDE-Dateien ------------------------------------------------------- INCLUDE "om_fw.pro" 'INCLUDE-Datei für Firmwareroutinen ' --- Programmende --------------------------------------------------------- Passender Link: Bedienungsanleitung zur Open-Macro und Open-Maxi Meine Homepage: http://ccintern.dharlos.de |
Antwort schreiben |