I've been trying to add more NMEA sentences stored as data tables to the program for my GPS project, but am getting strange results. I can only describe the problem - don't really want to post my full code as it's a bit messy at the moment and you will all laugh
Right, so previously I had the following two sentences stored:
Code:
gpgga addwf PCL, F
DT "$PSRF103,00,01,00,00", 0
gpvtg addwf PCL, F
DT "$PSRF103,05,01,00,00", 0
This works fine, and im using a simple loop to retreive each character and send it. However, if I try to add another sentence above these two, when the bottom one is due to be sent, it only sends half of the string, and then the PIC resets - it's like i've used all the memory or something, which shouldn't be the case as i'm using a 16F628 and when programming the software states 850 ish words. I get the same result when I make one of the above two strings a lot longer, the loop only sends part of it and then the PIC resets. I have tried putting all of the data tables on a different page in memory but then it doesn't send anything (apart from the CR/LF at the end of the send loop).
This is the loop i'm using to send each character:
It sounds like your table is crossing a 256 byte boundary?, a BIG problem if you don't know about it - assuming your tables aren't too large?, easiest solution is to move them to the start of memory (ensure you have a 'goto' to jump past them though). Next easiest, is to move them to their own 256 byte boundary, but you have to set bit's correctly before you call the table. The more complicated option is to write the table routine so it automatically compensates for the boundary - and code for this has been posted here many times.
You legend Nigel! Put my tables at the beginning of memory and it works fine.
I can't believe in all the work i've done with PICs before that i've never even heard about this boundary limitation. I now understand why there is such a limitation though, but never found it mentioned in any of the tutorials I started with years ago - granted i've not fully been through yours so it might be in there.
You legend Nigel! Put my tables at the beginning of memory and it works fine.
I can't believe in all the work i've done with PICs before that i've never even heard about this boundary limitation. I now understand why there is such a limitation though, but never found it mentioned in any of the tutorials I started with years ago - granted i've not fully been through yours so it might be in there.
We've all been caught that way, and probably will be in the future, the reason is simple, you're adding to an 8 bit PCL, so it can only address 256 bytes, and the addition doesn't affect the extra PCL bits which allow it to address the rest of the memory.
May I suggest an alternative that allows in-line code strings which can be longer than 256 bytes and can straddle 256 byte boundaries (by correctly manipulating PCLATH along with PCL)?
Regards, Mike
Code:
;
; example usage of the _Print macro in your program
;
_Print "$PSRF103,00,01,00,00\r\n"
_Print "$PSRF103,05,01,00,00\r\n"
;
Code:
;******************************************************************
;
; _Print macro - print a string to the RS-232 port
;
_Print macro str ;
local String, Print
movlw low String ;
movwf PTRL ;
movlw high String ;
movwf PTRH ;
goto Print ;
String dt str,0
Print call PutString ; print string
endm
;
;******************************************************************
Code:
;******************************************************************
;
; PutStr - setup PTRL and PTRH to string address before entry
; - string must be terminated with a 00 byte
;
PutString
call GetTable ; get a table character |B0
andlw b'11111111' ; |B0
btfsc STATUS,Z ; a 00 byte, last character? |B0
return ; yes, return |B0
call Put232 ; output char |B0
incfsz PTRL,F ; increment pointer |B0
goto PutString ; |B0
incf PTRH,F ; |B0
goto PutString ; |B0
;
GetTable
movf PTRH,W ; |B0
movwf PCLATH ; |B0
movf PTRL,W ; |B0
movwf PCL ; |B0
;
;******************************************************************
May I suggest an alternative which allows in-line code strings which can be longer than 256 bytes and can straddle 256 byte boundaries (by correctly manipulating PCLATH along with PCL)?
Regards, Mike
Code:
;
; example usage of the _Print macro in your program
;
_Print "$PSRF103,00,01,00,00\r\n"
_Print "$PSRF103,05,01,00,00\r\n"
;
Code:
;******************************************************************
;
; _Print macro - print a string to the RS-232 port
;
_Print macro str ;
local String, Print
movlw low String ;
movwf PTRL ;
movlw high String ;
movwf PTRH ;
goto Print ;
String dt str,0
Print call PutString ; print string
endm
;
;******************************************************************
Code:
;******************************************************************
;
; PutStr - setup PTRL and PTRH to string address before entry
; - string must be terminated with a 00 byte
;
PutString
call GetTable ; get a table character |B0
andlw b'11111111' ; |B0
btfsc STATUS,Z ; a 00 byte, last character? |B0
return ; yes, return |B0
call Put232 ; output char |B0
incfsz PTRL,F ; increment pointer |B0
goto PutString ; |B0
incf PTRH,F ; |B0
goto PutString ; |B0
;
GetTable
movf PTRH,W ; |B0
movwf PCLATH ; |B0
movf PTRL,W ; |B0
movwf PCL ; |B0
;
;******************************************************************
You're very welcome Nigel. And for PIC18 (16-bit instruction core), there's another very tight and clean method I like that uses the return address from the stack and TBLPTR registers.
A nice feature on the PIC18's is that two ASCII characters are stored in each 'word' of memory in the DB tables.
;******************************************************************
;
; PutString - print in-line string via Stack and TBLPTR
;
; string must be terminated with a 00 byte and does not need
; to be word aligned
;
PutString
movff TOSH,TBLPTRH ; copy return address to TBLPTR
movff TOSL,TBLPTRL ;
clrf TBLPTRU ; assume PIC with < 64-KB
PutNext
tblrd *+ ; get in-line string character
movf TABLAT,W ; last character (00)?
bz PutExit ; yes, exit, else
rcall Put232 ; print character
bra PutNext ; and do another
PutExit
btfsc TBLPTRL,0 ; odd address?
tblrd *+ ; yes, make it even (fix PC)
movf TBLPTRH,W ; setup new return address
movwf TOSH ;
movf TBLPTRL,W ;
movwf TOSL ;
return ;
;
;******************************************************************