[FONT="Fixedsys"][SIZE="2"]
Const QuarzFrequenz = 16000000
Const BaudRate = 200000
Const MinUBRR = (QuarzFrequenz\16\Baudrate)-1 ' UBRR -Wert für 4800 Baud
$regfile = "m16def.dat"
$crystal = QuarzFrequenz
'------------------------------------------------------------------------------
On Urxc Rs232receive Nosave ' Keine automatische Register-Rettung
'Enable Urxc ' Interrupt (Byte über USART erhalten) enabled
'------------------------------------------------------------------------------
'------------------------------------------------------------------------------
'------------------------------------------------------------------------------
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 RSError 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
Dim I As Byte
'******************************************************************************
'***************************** HAUPTPROGRAMM **********************************
'******************************************************************************
Flagreg = 0 ' alle Flags zurücksetzen
Rsbuffcount = 0 ' Zeichenzähler zurücksetzen
RSError = "?"
GOSUB _INIT_USART ' USART initialisieren
Enable Interrupts ' Interrupts global zulassen
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
RCALL Analysiere
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 ' (LineFeed #10): Endekennzeichen
brne RS232Receive2
Rs232receive1:
clr mReg ' Zeichen = #10, 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 #10 behandeln)
Rs232receive3:
st Y,mReg ' Zeichen in Puffer eintragen
sts {RSBuffCount},zReg ' Counter oder (#0 OR RS232Data) 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)
'..............................................................................
'..............................................................................
'..............................................................................
$ASM
_INIT_USART:
LDI zReg,MinUBRR\255 ' lädt das Highbyte
LDI mReg,MinUBRR ' lädt daS Lowbyte der Baudrate
'..............................................................................
_SET_Baudrate:
OUT UBRRH,zReg
OUT UBRRL,mReg
'..............................................................................
LDI mReg,&B00011000 ' Setzen von RXEN,TXEN =1 & UCSZ2=0
OUT UCSRB,mReg
SBI UCSRB,RXCIE ' Setzen von RXCIE,
RET
$END ASM
'==============================================================================
'====================== String nach Byte/Word Routinen ========================
'==============================================================================
CharUpper: ' wandelt Kleinbuchstaben in Großbuchstaben
$ASM
cpi mReg,asc("z")+1
BRSH CharUpperE ' Sprung bei größer oder gleich
CPI mReg,asc("a")
BRLO CharUpperE ' Sprung kleiner
SUBI mReg,&H20
CharUpperE:
ret
'------------------------------------------------------------------------------
HexCharToNibble_X:
LD mReg,X+
HexCharToNibble:
RCall CharUpper
CPI mReg,asc("A")
BRLO HexCharToNibble01
CPI mReg,asc("G")
BRSH HexCharToNibbleErr
subi mReg,55
HexCharToNibbleOK:
clc
ret
HexCharToNibble01:
Subi mReg,asc("0")
cpi mReg,10
BRLO HexCharToNibbleOK
HexCharToNibbleErr:
clr mReg
sec
ret
'------------------------------------------------------------------------------
WordFrom4Char_X: ' ** 4 (String-)Zeichen in hexadezimaler Form
RCALL ByteFrom2Char_X ' ** nach WORD-Variable wandeln
MOV zReg,mReg ' E: Stringzeiger in X
ByteFrom2Char_X: ' A: LOW in mReg, High in zReg
ld mReg,X+ ' ** 2 (String-)Zeichen in hexadezimaler Form
rcall HexCharToNibble ' ** nach Byte-Variable wandeln
brcs ByteFrom2Char_Xe2 ' E: Stringzeiger in X
SWAP mReg ' A: LOW in mReg
push zReg ' Geänderte Register: X steht hinter letztem
mov zReg,mReg ' gelesenen Zeichen
ld mReg,X+ ' geändert : mReg bzw. mReg & zReg
rcall HexCharToNibble
brcs ByteFrom2Char_Xe1
add mReg,zReg
ByteFrom2Char_Xe1:
pop zReg
ByteFrom2Char_Xe2:
ret
'..............................................................................
WordFromString: ' 4 Zeichen von X^ lesen, nach Word wandeln
RCALL WordFrom4Char_X ' und nach Y^ eintragen
ST Y+,mReg
ST Y+,zReg
RET
'------------------------------------------------------------------------------
'---------------------- Byte/Word nach String-Routinen ------------------------
'------------------------------------------------------------------------------
BytetoHex_INT:
andi mReg,$0F
Cpi mReg,10
brsh ByteToHex_Y0
ori mReg,$30 '"0" addieren
ret
Bytetohex_y0:
Subi mReg,9 ' -10 + 1 => A Nach #1
ori mReg,$40 ' oder '@' ist gleich 'A'-1
ret
'------------------------------------------------------------------------------
ByteToHexChar_Y:
PUSH mReg
SWAP mReg ' High Nibble Zuerst
RCALL ByteToHex_INT
ST Y+,mReg
POP mReg
NibbleToHexChar_Y:
RCALL ByteToHex_INT
ST Y+,mReg
RET
'------------------------------------------------------------------------------
'------------------- Zeichen bzw. Stringausgabe -------------------------------
'------------------------------------------------------------------------------
sendstring: '
PUSH XL
PUSH XH
sendstring0:
LD mReg,X+
CPI mReg,0
BREQ sendstringE
RCALL sendchar
RJMP sendstring0
sendstringE:
POP XH
POP XL
RET
'------------------------------------------------------------------------------
SendRSBuffstring:
Loadadr RSBuffstring,X
SendString_X:
rcall sendstring
SendCRLF:
ldi mReg,13
' rcall sendchar
' ldi mReg,10
;..............................................................................
sendchar:
sbis UCSRA,UDRIE ' Warten bis UDR für das nächste
rjmp sendChar ' Byte bereit ist
out UDR,mReg
ret
$end Asm
'------------------------------------------------------------------------------
'------------------------------------------------------------------------------
$ASM
Value_mReg_To_Y: ' Liest 2 Hex-Zeichen aus dem IN-Puffer (Y)
PUSH mReg
LDI mReg,ASC("$")
ST Y+,mReg
pop mReg
RCALL ByteToHexChar_Y ' und wandelt nach Byte (in mReg)
LDI mReg,ASC(",")
ST Y+,mReg
RET
'...............................................................................
USARTStatus:
LoadAdr RSBuffer(2),Y
USARTStatus1:
IN mReg,UBRRL ' UBRRL
RCALL Value_mReg_To_Y
CLI
IN mReg,UBRRH
IN mReg,UCSRC ' UCRSC
SEI
RCALL Value_mReg_To_Y
IN mReg,UCSRB ' UCRSB
RCALL Value_mReg_To_Y
IN mReg,UCSRA ' UCRSA
RCALL Value_mReg_To_Y ' ByteToHexChar_Y
clr mReg
ST -Y,mReg ' Komma mit #0 überschreiben
RET
$END ASM
'------------------------------------------------------------------------------
Dim ii as word, Ptr as Word, TestVar as word
Analysiere:
Select case RSBuffer(1)
case "X" : LoadAdr RSBuffer(2),X
LoadAdr TestVar,Y
RCALL WORDFromString
LD mReg,X+ ' 1 Zeichen überlesen
Loadadr Ptr,Y
ST Y+,XL
ST Y+,XH
for ii=0 to TestVar '###################################
Loadadr Ptr,Y ' diese Mischung von Assembler und
LD XL,Y+ ' BASCOM (in einer for..next Schleife)
LD XH,Y+ ' ist grenzwertig und nicht gerade
RCALL SendString_X ' empfehlenswert (aber funktioniert)
Next ii '###################################
case "B" : LoadAdr RSBuffer(2),X
RCALL WordFrom4Char_X
RCALL _Set_BaudRate
LoadAdr RSBuffer(2),Y
push mReg
mov mReg,zReg
RCALL ByteToHexChar_Y
POP mReg
RCALL ByteToHexChar_Y
clr mReg
st Y+,mReg
RCALL SendRSBuffString
case "Y" : RCALL SendRSBuffString
case "S" : RCALL USARTStatus
RCALL SendRSBuffString
case else : LoadAdr RSError,X
RCALL SendString_X
End Select
RETURN
[/SIZE][/FONT]