Guten Tag,
ich wollte mal mein 'Erstlingswerk' hier hereinstellen. Diese Routine soll mir zukünftig für Folgeprojekte zur Kommunikation mit dem PC dienen.
Die Routine übernimmt den Datenempfang über die serielle Schnittstelle im Interrupt.
Geprüft hab' ich die Routine mit einem eigenen Programm und den aktuellen Einstellungen im Listing.
Ich komme auf eine Übertragungsrate von ca. 1350 Zeichen/Sekunde (hin und zurück) also ca. 2700 Zeichen/Sekunde in eine Richtung.
Schönen Tag noch
Werner
ich wollte mal mein 'Erstlingswerk' hier hereinstellen. Diese Routine soll mir zukünftig für Folgeprojekte zur Kommunikation mit dem PC dienen.
Die Routine übernimmt den Datenempfang über die serielle Schnittstelle im Interrupt.
- Die Strings vom PC müssen mit CR/LF ($13/$10) getrennt werden, wobei das LF optional ist
- Längenbeschränkung auf 20 Zeichen (durch Anpassung der Konstanten CBuffSize erweiterbar)
- im Demoprogramm wird der String per 'PRINT' einfach zurückgeschickt (wobei wieder ein CR/LF) automatisch durch 'PRINT' angehängt wird; hier könnte die Auswertung erfolgen
- Die Routine benutzt ihren eigenen Puffer RSBuffer(CBuffsize) bzw. RSBuffstring, von Bascom wird nichts zusätzlich eingerichtet
- Das 'RETURN' am Ende der Routine wird von Bascom mit 'reti' übersetzt (hab' ich mit einem Disassembler geprüft)
Code:
[FONT="Courier New"][SIZE="2"]'------------------------------------------------------------------------------
'name : ser4.bas
'copyright : Laplace/Werner
'purpose : Testprogramm Serielles Interrupt- Handling
'micro : ATMega 8
'commercial addon needed : nein
'------------------------------------------------------------------------------
' Kleine bis große Nickligkeit (hat mich Stunden gekostet):
' SBR Reg,Bitmuster : Setze Bit in Register : 0 <= Bitmuster <= 255
' führt OR Operation: Reg OR Bitmuster aus !!
' SBRS Reg,Bitmuster : Springe, falls Bit gesetzt : 0 <= Bitmuster <= 7
' hier muss die Position des Bits angegeben werden !!
'------------------------------------------------------------------------------
$regfile = "m8def.dat"
$crystal = 16000000
$baud = 38400 ' 9600, 19200 ansonsten '8N1'
$hwstack = 40 ' im Moment nicht benötigt
$swstack = 24 ' im Moment nicht benötigt
$framesize = 24 ' im Moment nicht benötigt
'------------------------------------------------------------------------------
'------------------------------------------------------------------------------
'------------------------------------------------------------------------------
On URXC RS232Receive NoSave ' Keine automatische Register-Rettung
Enable URXC ' Interrupt (Byte über USART erhalten) enabled
Enable Interrupts ' Interrupts global zulassen
'------------------------------------------------------------------------------
'------------------------------------------------------------------------------
'------------------------------------------------------------------------------
Const CBuffsize = 20 ' Maximale Anzahl-1 der Stringzeichen
Const SkipChar = 10 ' LineFeed (ignorieren)
Const Terminator = 13 ' CarriageReturn (Stringende)
Const RS232DataPresent = &b10000000 ' Bit 7 (Maske für Registeroperationen)
Const RS232DataBranch = 7 ' Bit 7 für Branch (SBRS/SBRC)
mReg Alias R16
zReg Alias R17
fReg Alias R18
'z2reg Alias R18
'------------------------------------------------------------------------------
Dim RSBuffcount As Byte
Dim RSBuffer(CBuffsize) As Byte ' von 1..CBuffSize Zeichen
Dim RSBuffstring As String * CBuffsize At RSBuffer Overlay
Dim FlagReg As Byte ' Speicher für 8 Flags
'******************************************************************************
'***************************** HAUPTPROGRAMM **********************************
'******************************************************************************
FlagReg = 0 ' alle Flags zurücksetzen
RSBuffCount = 0 ' Zeichenzähler zurücksetzen
Do
$ASM
Mainwait0: ' Auf kompletten String von RS232 (vom PC) warten
lds fReg,{FlagReg} ' dazu FlagReg auf Bit 7 prüfen
SBRS fReg,RS232DataBranch ' Sprung, falls Bit 7 gesetzt ist
rjmp MainWait0 ' sonst weiter warten
$END ASM
Print RSBuffString ' STRING ZURÜCKSCHICKEN
$ASM
lds fReg,{FlagReg} ' FlagReg Bit 7
CBR fReg,RS232DataPresent ' (CBR: Clear Bit in Register)
sts {FlagReg},fReg ' löschen
$END ASM
Loop
End
'******************************************************************************
'********************* RS232- Interrupthandler (Receiver) *********************
'******************************************************************************
RS232Receive:
$ASM
push mReg ' 1.Arbeitsregister retten
IN mReg,SREG ' Statusregister einlesen
push mReg ' und sichern
push zReg ' 2.Arbeitsregister retten
PUSH fReg ' eigenes Flagregister retten
'..............................................................................
IN mReg,UDR ' Zeichen von COM-Schnittstelle einlesen
cpi mReg,SkipChar ' falls zu überlesen, dann fertig
breq RS232Receive4 ' -> Sprung zum Ende
lds fReg,{FlagReg} ' Flagregister lesen (nach fReg)
SBRC fReg,RS232DataBranch ' Sprung, falls das RS232Data Bit gelöscht
RJMP RS232Receive4 ' sonst beenden (gesendetes Byte geht verloren)
'------------------------------------------------------------------------------
lds zReg,{RSBuffCount} ' Zeichenzähler aus RAM lesen (nach zReg)
push YL ' Y-Pointer auf den Datenpuffer setzen
push YH
' ldi YL,low(RSBuffer) ' Tabellenoffset im Datensegment
' ldi YH,high(RSBuffer) ' .. so will's der Assembler
LOADADR RSBuffer(1),Y ' .. so will's BASCOM
' LOADADR RSBuffString,Y ' .. oder auch so
add YL,zReg ' Zeichenzähler um eins erhöhen
brcc RS232Receive0 ' und zum Y-Pointer addieren
inc YH
RS232Receive0:
cpi mReg,Terminator ' (CR #13): Endekennzeichen
brne RS232Receive2
RS232Receive1:
clr mReg ' Zeichen = #13, dann #0 eintragen UND
CLR zReg ' Zeichenzähler ebenfalls auf #0
SBR fReg,RS232DataPresent ' Bit 7: Flag für Daten vollständig setzen
sts {FlagReg},fReg ' im Flagregister setzen
rjmp RS232Receive3 ' MIT MASKE $80 !!!!
RS232Receive2:
inc zReg ' Anzahl gelesener Zeichen erhöhen
cpi zReg,CBuffsize ' Puffer schon voll
brsh RS232Receive1 ' Sprung, falls ja (dann als #13 behandeln)
RS232Receive3:
st Y,mReg ' Zeichen in Puffer eintragen
sts {RSBuffCount},zReg ' Counter eintragen
pop YH
pop YL
'..............................................................................
RS232Receive4: ' Lead-Out
POP fReg
pop zReg ' benutzte Register restaurieren
pop mReg ' sowiw flags wiederherstellen
OUT SREG,mReg
pop mReg
' RETI ' BASCOM ersetzt in diesem Fall, d.h. ISR-Routine
$END ASM ' die über ON 'Interrupt' 'Label' deklariert ist
RETURN ' dieses 'RETURN' durch 'RETI' (nicht RET)
[/SIZE][/FONT]
Geprüft hab' ich die Routine mit einem eigenen Programm und den aktuellen Einstellungen im Listing.
Ich komme auf eine Übertragungsrate von ca. 1350 Zeichen/Sekunde (hin und zurück) also ca. 2700 Zeichen/Sekunde in eine Richtung.
Schönen Tag noch
Werner