I am writing a bootloader in GCBASIC but found the USART empty so decided to write my own. Here is a sample based on code by Steve on forum.
'USART test routines
#chip 16F877A,10
#option bootloader
#define SPBRG_Val 0x40
Initusart
mainloop:
wait 25 ms
HserTX_Print ("Please type in a character ")
HserTX(13)
HserTX(10)
Loopx:
inbyte = HserRX
If inbyte=0 then GOTO Loopx
HserTX_Print ("Message received, you entered a: ")
HserTX(inbyte)
HserTX(13)
HserTX(10)
goto mainloop
sub initusart
BSF TRISC,6 'PORTC.6 output
BSF TRISC,7 'PORTC.7 output
MOVLW SPBRG_Val 'baude rate
MOVWF SPBRG
movlw 0x24 'enable transmission and BRGH=1
movwf TXSTA
movlw 0x90 'enable serial port and receive
movwf RCSTA
end sub
sub HserTX (xmitdata)
LoopTransmit:
IF PIR1.TXIF OFF THEN goto LoopTransmit 'check if transmitter is busy
TXDATA = xmitdata
TXREG = TXDATA 'transmit data
end sub
sub HserTX_Print(PrintData$)
PrintLen = PrintData(0)
if PrintLen = 0 then exit sub
for SysPrintTemp = 1 to PrintLen
HserTX(PrintData(SysPrintTemp))
next
end sub
function HserRX 'check if data received, and if so, return data
IF PIR1.RCIF OFF THEN GOTO endreceiveserial
HserRX = RCREG
GOTO successreceiveserial
endreceiveserial:
HserRX = 0
successreceiveserial:
end function
function HserIn
HserIn = RCREG
end function
This version works; however, if I change SPBRG_Val to a variable
Dim SPBRG_Val as byte
SPBRG_Val=0x40
Now it does not work.
I also tried
sub initusart(baude)#NR
BSF TRISC,6 'PORTC.6 output
BSF TRISC,7 'PORTC.7 output
MOVLW baude 'baude rate
MOVWF SPBRG
movlw 0x24 'enable transmission and BRGH=1
movwf TXSTA
movlw 0x90 'enable serial port and receive
movwf RCSTA
end sub
and called it with
initusart SPBRG_Val
This did not work. I also changed (baude) to (baude as byte).
Are variables all global or are variables defined in a subroutine, local variables.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
"movlw" is used to load a literal (fixed number) into W (the accumulator). When using a number like 0x40, this works fine and places the correct value into W for the next instruction (move W into file register (variable) SPBRG. However, when "movlw variable" is used the address of the variable is loaded into W. This means that SPBRG is getting set to the location of SPBRG_Val, not its value.
The solution is to replace this assembly with a line of GCBASIC code:
SPBRG = SPBRG_Value
Another alternative is to change the first line to "movf SPBRG_Val,F", but I'd advise against using assembly code except where necessary.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am writing a bootloader in GCBASIC but found the USART empty so decided to write my own. Here is a sample based on code by Steve on forum.
'USART test routines
#chip 16F877A,10
#option bootloader
#define SPBRG_Val 0x40
Initusart
mainloop:
wait 25 ms
HserTX_Print ("Please type in a character ")
HserTX(13)
HserTX(10)
Loopx:
inbyte = HserRX
If inbyte=0 then GOTO Loopx
HserTX_Print ("Message received, you entered a: ")
HserTX(inbyte)
HserTX(13)
HserTX(10)
goto mainloop
sub initusart
BSF TRISC,6 'PORTC.6 output
BSF TRISC,7 'PORTC.7 output
MOVLW SPBRG_Val 'baude rate
MOVWF SPBRG
movlw 0x24 'enable transmission and BRGH=1
movwf TXSTA
movlw 0x90 'enable serial port and receive
movwf RCSTA
end sub
sub HserTX (xmitdata)
LoopTransmit:
IF PIR1.TXIF OFF THEN goto LoopTransmit 'check if transmitter is busy
TXDATA = xmitdata
TXREG = TXDATA 'transmit data
end sub
sub HserTX_Print(PrintData$)
PrintLen = PrintData(0)
if PrintLen = 0 then exit sub
for SysPrintTemp = 1 to PrintLen
HserTX(PrintData(SysPrintTemp))
next
end sub
function HserRX 'check if data received, and if so, return data
IF PIR1.RCIF OFF THEN GOTO endreceiveserial
HserRX = RCREG
GOTO successreceiveserial
endreceiveserial:
HserRX = 0
successreceiveserial:
end function
function HserIn
HserIn = RCREG
end function
This version works; however, if I change SPBRG_Val to a variable
Dim SPBRG_Val as byte
SPBRG_Val=0x40
Now it does not work.
I also tried
sub initusart(baude)#NR
BSF TRISC,6 'PORTC.6 output
BSF TRISC,7 'PORTC.7 output
MOVLW baude 'baude rate
MOVWF SPBRG
movlw 0x24 'enable transmission and BRGH=1
movwf TXSTA
movlw 0x90 'enable serial port and receive
movwf RCSTA
end sub
and called it with
initusart SPBRG_Val
This did not work. I also changed (baude) to (baude as byte).
Are variables all global or are variables defined in a subroutine, local variables.
These lines are causing the trouble:
MOVLW SPBRG_Val 'baude rate
MOVWF SPBRG
"movlw" is used to load a literal (fixed number) into W (the accumulator). When using a number like 0x40, this works fine and places the correct value into W for the next instruction (move W into file register (variable) SPBRG. However, when "movlw variable" is used the address of the variable is loaded into W. This means that SPBRG is getting set to the location of SPBRG_Val, not its value.
The solution is to replace this assembly with a line of GCBASIC code:
SPBRG = SPBRG_Value
Another alternative is to change the first line to "movf SPBRG_Val,F", but I'd advise against using assembly code except where necessary.
That was the problem. Undone by the obvious.