Charles is right. You are not looking at the serial port while your code is sending MessageA thrice and then pausing for 1000 ms. During that time, whatever comes in is bound to overflow the receive register. Cloerr will mitigate the problem to an extent, but imagine, you just received your "d" and are waiting for the decimal values for B0, B1 or B2. During that time if the input packet has already finished, you're in trouble. That's because the DEC modifier parses numbers only. If it doesn't find a number, either your number read is wrong or it will end up waiting indefinitely on the "d".
Ideal solution, put in an interrupt routine to capture the incoming serial characters. Catch them to a circular buffer and read that buffer often. How to do it? This is how I would do it....
Code:
' These variables are used to save the machine state on interrupt
wsave var byte $20 SYSTEM ' location for W if in bank0
wsave1 var byte $A0 SYSTEM ' location for W if in bank1
wsave2 var byte $120 SYSTEM ' location for W if in bank2
wsave3 var byte $1A0 SYSTEM ' location for W if in bank3
ssave var byte BANK0 SYSTEM ' location for STATUS register
psave var byte BANK0 SYSTEM ' location for PCLATH register
fsave var byte BANK0 SYSTEM ' location for FSR register
intR0 var byte BANK0 SYSTEM ' interrupt temporary variables
intR1 var byte BANK0 SYSTEM
' Receive buffer
RxBuf var byte[16] ' buffer holding received chars
WrPtr var byte ' write index
RdPtr var byte ' write index
' define the interrupt handler
define INTHAND _IntHandler
goto OverInterrupt
IntHandler:
'*******************************************************************************
' Interrupts can be from a number of sources. See INTCON p25
' We use the following
' RBIF - interrupt on RB change
' T0IF - Timer0 overflow interrupt
IntHandler:
asm ; identify the interrupt source
movf FSR,w
movwf fsave ; save the fsr
btfss PIE1,RCIE ; if enabled and
goto EndInt
btfss PIR1, RCIF ; receive interrupt?
goto EndInt
RxISR
movlw 6
andwf RCSTA,w ;FERR(4) + OERR(2)
btfss STATUS,Z ;not set
bcf RCSTA,CREN ;clear errors
bsf RCSTA,CREN ;by putting CREN=0,1
;
movf _WrPtr, W
addlw low (_RxBuf)
movwf FSR
movf RCREG,w
movwf INDF ;RxBuf[WrPtr]=RCREG
;
incf _WrPtr
movlw 0fh
andwf _WrPtr
EndInt
movf fsave,w ;restore the FSR
movwf FSR
movf psave,w ;restore PCH
movwf PCLATH
swapf ssave, W ;restore STATUS
movwf STATUS
swapf wsave, F
swapf wsave, W ;restore W
retfie
ENDASM
' initialize the serial buffer
Ser_Init:
RCSTA=$90 ' Enable serial port & continuous receive
TXSTA=$20 ' Enable transmit, BRGH = 0
SPBRG=25 ' 2400 Baud @ 4MHz, 0.0%
RdPtr=0
WrPtr=0
return
' read a serial character
Ser_Getc:
while RdPtr=WrPtr:wend
gr[0]=RxBuf[RdPtr]
RdPtr=RdPtr+1
RdPtr=RdPtr & $0f
return
' read the value of a hex digit to gr[0]
Ser_GetHex:
gosub Ser_Getc
if gr[0]>"9"then gr[0]=gr[0]-7
gr[0]=gr[0]-"0"
return
' read the value of 2 hex digits to gr[0]
Ser_GetHex2:
gosub Ser_GetHex
gr[1]=gr[0]<<4
gosub Ser_GetHex
gr[0]=gr[1]+gr[0]
return
ProcessRX:
while RdPtr <> WrPtr
gosub Ser_GetC
if gr[0]="d" then ProcRX10 ' Proceed only after we get the "d"
wend
return
ProcRX10:
' process the data here
This is just a framework and is incomplete. Use it at your own risk.
Jerson
Bookmarks