pic-ker
- 10th February 2007, 17:42
Hi everyone... Im working on a device to receive serial data wirelessly (2400 baud) and then transfer it to a PC using USB. I have completed the hardware and the PIC interface however im unable to get the 18F4550 to send correct data to the PC [I get 3 characters ok...and garbage later]
Tx is a PIC 18F4550 connected to USB and RF module
I found a great USBDemo code by mister_e on this site which i modified for this...
Tx code:
Clear
DEFINE OSC 20
CMCON = 7 ' TURN ANALOG COMPARATOR MODE OFF
Include "modedefs.bas"
TRISA = %11111111
TRISB = %00000000
TRISC = %10000000
TRISD = %00000000
TRISE = %00000000
PORTA = %00000000
PORTB = %00000000
PORTC = %00000000
PORTD = %00000000
PORTE = %00000000
T2CON = %00000101
UCFG var byte EXT
ucfg = %00010100
INTCON = %10100000
T0CON = %10000000
SerialData var byte
USBBufferSizeTX con 8 ' input
USBBufferSizeRX con 8 ' output
USBBufferCount Var Byte '
USBBufferIn var byte[8] ' store incomming USB data
USBBufferOut Var Byte[8] ' store outgoing USB data
TMR0IF VAR INTCON.2 ' TMR0 overflow int flag
TMR0ON VAR T0CON.7 ' TMR0 on/off bit
TMR0IE VAR INTCON.5 ' TMR0 interrupt enable/disable bit
' Macro(s) definition
' ===================
goto SwHwInit ' skip macros
asm
Reload_TMR0 macro
; Use to stop, reload, clear overflow flag and restart TMR0
BCF _TMR0ON ; stop timer
MOVE?CW d'65000',TMR0L ; reload for timebase ~100uSec
BCF _TMR0IF ; clear overflow flag
BSF _TMR0ON ; start timer
ENDM
SendUSB macro array
; Use to Copy an specific array to USBBufferOut AND send it
; to USB bus
variable i=0
while i<8
MOVE?BB (array+i),(_USBBufferOut+i)
i+=1
endw
L?CALL _DoUSBOut
endm
endasm
SwHwInit:
pause 500 ' Settle delay
usbinit ' initialise USB
PAUSE 20 ' Delay after initializing USB
@ Reload_TMR0 ; Reload timer0
ON INTERRUPT GOTO DoUSBService
' Main program start
' ==================
Start:
IF USBBufferIn[7]=239 then
SEROUT PORTC.0,N2400,[USBBUFFERIN[7]]
GOSUB DoLow
USBBufferin[7]=0
if USBBufferIn[1]<>0 then
SEROUT PORTC.0,N2400,[USBBufferIn[1]]
GOSUB DoLow
USBBufferIn[1]=0
endif
USBService
if USBBufferIn[2]<>0 then
SEROUT PORTC.0,N2400,[USBBufferIn[2]]
GOSUB DoLow
USBBufferIn[2]=0
endif
USBService
if USBBufferIn[3]<>0 then
SEROUT PORTC.0,N2400,[USBBufferIn[3]]
GOSUB DoLow
USBBufferin[3]=0
endif
USBService
if USBBufferIn[4]<>0 then
SEROUT PORTC.0,N2400,[USBBufferIn[4]]
GOSUB DoLow
USBBufferin[4]=0
endif
USBService
if USBBufferIn[5]<>0 then
SEROUT PORTC.0,N2400,[USBBufferIn[5]]
GOSUB DoLow
USBBufferin[5]=0
endif
USBService
if USBBufferIn[6]<>0 then
SEROUT PORTC.0,N2400,[USBBufferIn[6]]
GOSUB DoLow
USBBufferin[6]=0
endif
USBService
else
if USBBUFFERin[7]<>0 then
SEROUT PORTC.0,N2400,[USBBufferin[7]]
GOSUB DoLow
USBBUFFERin[7]=0
endif
USBSERVICE
endif
gosub dousbin
goto start
DoLow:
LOW PORTC.0
USBSERVICE
PAUSE 30
USBSERVICE
return
DoUSBIn:
tmr0ie = 0 ' disbale TMR0 int
USBBufferCount = USBBufferSizeRX ' RX buffer size
USBService ' keep connection alive
USBIn 1, USBBufferin, USBBufferCount, Timeout ' read data, if available
Timeout: '
@ Reload_TMR0
tmr0ie = 1 ' re-enable TMR0 int
PORTB = USBBUFFERIN[0] ' output to PORTB
return
DoUSBOut:
TMR0IE = 0 ' Disable TMR0 interrupt
WaitPC: '
USBBufferCount = USBBufferSizeTX ' TX buffer size
USBService ' keep connection alive
USBOut 1, USBBufferOut, USBBufferCount, Waitpc ' if bus available, transmit data
@ Reload_TMR0
tmr0ie=1 ' Re-Enable TMR0 interrupt
return
DISABLE
DoUSBService:
usbservice ' keep connection alive
@ Reload_TMR0 ; reload timer
RESUME ' getout of here
ENABLE
' The TX is working....i can see the o/p on the oscilloscope...i have given a 30ms break after every 2400baud character
'The VB Program transmits char=239[ for sync with receiver] on USBBufferin[7] and the rest are valid data
Here's the receiver code:
Clear
DEFINE OSC 20
DEFINE HSER_RCSTA 90h ' Set receive register to receiver enabled
DEFINE HSER_TXSTA 24h
DEFINE HSER_BAUD 2400 ' Set baud rate
DEFINE HSER_SPBRG 51 ' Set SPBRG directly (normally set by HSER_BAUD)
Include "modedefs.bas"
TRISA = %11111111
TRISB = %00000000
TRISC = %10000000
TRISD = %00000000
TRISE = %00000000
PORTA = %00000000
PORTB = %00000000
PORTC = %00000000
PORTD = %00000000
PORTE = %00000000
T2CON = %00000101 ' TMR2 on, prescaler 1:4
UCFG var byte EXT ' include UCFG register
ucfg = %00010100 ' enable internal USB pull-up, Full speed USB
INTCON = %10100000 ' Enable global and TMR0 interrupts
T0CON = %10000000 ' TMR0, CLK internal, prescaler 1:2, T0ON
RCIF VAR PIR1.5 ' Receive interrupt flag (1=full , 0=empty)
TXIF VAR PIR1.4 ' Transmit interrupt flag (1=empty, 0=full)
SerialData var byte
B0 VAR BYTE
USBBufferSizeTX con 8 ' input
USBBufferSizeRX con 8 ' output
USBBufferCount Var Byte '
USBBufferIn var byte[8] ' store incomming USB data
USBBufferOut Var Byte[8] ' store outgoing USB data
DataToSend var byte[8] ' store ADCs & pushButton data to send to USB
TMR0IF VAR INTCON.2 ' TMR0 overflow int flag
TMR0ON VAR T0CON.7 ' TMR0 on/off bit
TMR0IE VAR INTCON.5 ' TMR0 interrupt enable/disable bit
CR CON 13
Char VAR BYTE
goto SwHwInit ' skip macros
asm
Reload_TMR0 macro
; Use to stop, reload, clear overflow flag and restart TMR0
BCF _TMR0ON ; stop timer
MOVE?CW d'65000',TMR0L ; reload for timebase ~100uSec
BCF _TMR0IF ; clear overflow flag
BSF _TMR0ON ; start timer
ENDM
SendUSB macro array
; Use to Copy an specific array to USBBufferOut AND send it
; to USB bus
variable i=0
while i<8
MOVE?BB (array+i),(_USBBufferOut+i)
i+=1
endw
L?CALL _DoUSBOut
endm
endasm
SwHwInit:
pause 500 ' Settle delay
usbinit ' initialise USB
PAUSE 20 ' Delay after initializing USB
@ Reload_TMR0 ; Reload timer0
ON INTERRUPT GOTO DoUSBService
DataToSend[0] = 0
datatosend[2] = 0 'PORTA.2
datatosend[3] = 0 'PORTA.3
datatosend[4] = 0 'PORTA.4
datatosend[5] = 0 'PORTA.5
datatosend[6] = 0
datatosend[7] = 0
'Main Prog starts here
Start:
if RCIF then
HSERIN [DatatoSend[2]] ' take it
@ SendUSB _DataToSend
endif
gosub dousbin
goto Start
DoUSBIn:
tmr0ie = 0 ' disbale TMR0 int
USBBufferCount = USBBufferSizeRX ' RX buffer size
USBService ' keep connection alive
USBIn 1, USBBufferin, USBBufferCount, Timeout ' read data, if available
Timeout: '
@ Reload_TMR0
tmr0ie = 1 ' re-enable TMR0 int
PORTB = USBBUFFERIN[0] ' output to PORTB
' Not using USBBufferIn[1,2,3,4]
return
DoUSBOut:
TMR0IE = 0 ' Disable TMR0 interrupt
WaitPC: '
USBBufferCount = USBBufferSizeTX ' TX buffer size
USBService ' keep connection alive
USBOut 1, USBBufferOut, USBBufferCount, Waitpc ' if bus available, transmit data
@ Reload_TMR0
tmr0ie=1 ' Re-Enable TMR0 interrupt
return
DISABLE
DoUSBService:
usbservice ' keep connection alive
@ Reload_TMR0 ; reload timer
RESUME ' getout of here
ENABLE
' The VB Program receives the Serial Data using the USBBuffer[2]
I know the the connections work coz if i touch the RX pin i get a string of '255's in the VB prog...
Any suggestions why the text is garbled ? ( I have tried all combinations of T2400,N2400 etc...)
I have also tried using another PIC (628) to receive the serial data and convert it to a parallel o/p on its port and feed it to the 4550...but that doesnt work as well...
At the moment im testing it using two wires (data,gnd) between Tx and Rx and I will add the RF module later
Tx is a PIC 18F4550 connected to USB and RF module
I found a great USBDemo code by mister_e on this site which i modified for this...
Tx code:
Clear
DEFINE OSC 20
CMCON = 7 ' TURN ANALOG COMPARATOR MODE OFF
Include "modedefs.bas"
TRISA = %11111111
TRISB = %00000000
TRISC = %10000000
TRISD = %00000000
TRISE = %00000000
PORTA = %00000000
PORTB = %00000000
PORTC = %00000000
PORTD = %00000000
PORTE = %00000000
T2CON = %00000101
UCFG var byte EXT
ucfg = %00010100
INTCON = %10100000
T0CON = %10000000
SerialData var byte
USBBufferSizeTX con 8 ' input
USBBufferSizeRX con 8 ' output
USBBufferCount Var Byte '
USBBufferIn var byte[8] ' store incomming USB data
USBBufferOut Var Byte[8] ' store outgoing USB data
TMR0IF VAR INTCON.2 ' TMR0 overflow int flag
TMR0ON VAR T0CON.7 ' TMR0 on/off bit
TMR0IE VAR INTCON.5 ' TMR0 interrupt enable/disable bit
' Macro(s) definition
' ===================
goto SwHwInit ' skip macros
asm
Reload_TMR0 macro
; Use to stop, reload, clear overflow flag and restart TMR0
BCF _TMR0ON ; stop timer
MOVE?CW d'65000',TMR0L ; reload for timebase ~100uSec
BCF _TMR0IF ; clear overflow flag
BSF _TMR0ON ; start timer
ENDM
SendUSB macro array
; Use to Copy an specific array to USBBufferOut AND send it
; to USB bus
variable i=0
while i<8
MOVE?BB (array+i),(_USBBufferOut+i)
i+=1
endw
L?CALL _DoUSBOut
endm
endasm
SwHwInit:
pause 500 ' Settle delay
usbinit ' initialise USB
PAUSE 20 ' Delay after initializing USB
@ Reload_TMR0 ; Reload timer0
ON INTERRUPT GOTO DoUSBService
' Main program start
' ==================
Start:
IF USBBufferIn[7]=239 then
SEROUT PORTC.0,N2400,[USBBUFFERIN[7]]
GOSUB DoLow
USBBufferin[7]=0
if USBBufferIn[1]<>0 then
SEROUT PORTC.0,N2400,[USBBufferIn[1]]
GOSUB DoLow
USBBufferIn[1]=0
endif
USBService
if USBBufferIn[2]<>0 then
SEROUT PORTC.0,N2400,[USBBufferIn[2]]
GOSUB DoLow
USBBufferIn[2]=0
endif
USBService
if USBBufferIn[3]<>0 then
SEROUT PORTC.0,N2400,[USBBufferIn[3]]
GOSUB DoLow
USBBufferin[3]=0
endif
USBService
if USBBufferIn[4]<>0 then
SEROUT PORTC.0,N2400,[USBBufferIn[4]]
GOSUB DoLow
USBBufferin[4]=0
endif
USBService
if USBBufferIn[5]<>0 then
SEROUT PORTC.0,N2400,[USBBufferIn[5]]
GOSUB DoLow
USBBufferin[5]=0
endif
USBService
if USBBufferIn[6]<>0 then
SEROUT PORTC.0,N2400,[USBBufferIn[6]]
GOSUB DoLow
USBBufferin[6]=0
endif
USBService
else
if USBBUFFERin[7]<>0 then
SEROUT PORTC.0,N2400,[USBBufferin[7]]
GOSUB DoLow
USBBUFFERin[7]=0
endif
USBSERVICE
endif
gosub dousbin
goto start
DoLow:
LOW PORTC.0
USBSERVICE
PAUSE 30
USBSERVICE
return
DoUSBIn:
tmr0ie = 0 ' disbale TMR0 int
USBBufferCount = USBBufferSizeRX ' RX buffer size
USBService ' keep connection alive
USBIn 1, USBBufferin, USBBufferCount, Timeout ' read data, if available
Timeout: '
@ Reload_TMR0
tmr0ie = 1 ' re-enable TMR0 int
PORTB = USBBUFFERIN[0] ' output to PORTB
return
DoUSBOut:
TMR0IE = 0 ' Disable TMR0 interrupt
WaitPC: '
USBBufferCount = USBBufferSizeTX ' TX buffer size
USBService ' keep connection alive
USBOut 1, USBBufferOut, USBBufferCount, Waitpc ' if bus available, transmit data
@ Reload_TMR0
tmr0ie=1 ' Re-Enable TMR0 interrupt
return
DISABLE
DoUSBService:
usbservice ' keep connection alive
@ Reload_TMR0 ; reload timer
RESUME ' getout of here
ENABLE
' The TX is working....i can see the o/p on the oscilloscope...i have given a 30ms break after every 2400baud character
'The VB Program transmits char=239[ for sync with receiver] on USBBufferin[7] and the rest are valid data
Here's the receiver code:
Clear
DEFINE OSC 20
DEFINE HSER_RCSTA 90h ' Set receive register to receiver enabled
DEFINE HSER_TXSTA 24h
DEFINE HSER_BAUD 2400 ' Set baud rate
DEFINE HSER_SPBRG 51 ' Set SPBRG directly (normally set by HSER_BAUD)
Include "modedefs.bas"
TRISA = %11111111
TRISB = %00000000
TRISC = %10000000
TRISD = %00000000
TRISE = %00000000
PORTA = %00000000
PORTB = %00000000
PORTC = %00000000
PORTD = %00000000
PORTE = %00000000
T2CON = %00000101 ' TMR2 on, prescaler 1:4
UCFG var byte EXT ' include UCFG register
ucfg = %00010100 ' enable internal USB pull-up, Full speed USB
INTCON = %10100000 ' Enable global and TMR0 interrupts
T0CON = %10000000 ' TMR0, CLK internal, prescaler 1:2, T0ON
RCIF VAR PIR1.5 ' Receive interrupt flag (1=full , 0=empty)
TXIF VAR PIR1.4 ' Transmit interrupt flag (1=empty, 0=full)
SerialData var byte
B0 VAR BYTE
USBBufferSizeTX con 8 ' input
USBBufferSizeRX con 8 ' output
USBBufferCount Var Byte '
USBBufferIn var byte[8] ' store incomming USB data
USBBufferOut Var Byte[8] ' store outgoing USB data
DataToSend var byte[8] ' store ADCs & pushButton data to send to USB
TMR0IF VAR INTCON.2 ' TMR0 overflow int flag
TMR0ON VAR T0CON.7 ' TMR0 on/off bit
TMR0IE VAR INTCON.5 ' TMR0 interrupt enable/disable bit
CR CON 13
Char VAR BYTE
goto SwHwInit ' skip macros
asm
Reload_TMR0 macro
; Use to stop, reload, clear overflow flag and restart TMR0
BCF _TMR0ON ; stop timer
MOVE?CW d'65000',TMR0L ; reload for timebase ~100uSec
BCF _TMR0IF ; clear overflow flag
BSF _TMR0ON ; start timer
ENDM
SendUSB macro array
; Use to Copy an specific array to USBBufferOut AND send it
; to USB bus
variable i=0
while i<8
MOVE?BB (array+i),(_USBBufferOut+i)
i+=1
endw
L?CALL _DoUSBOut
endm
endasm
SwHwInit:
pause 500 ' Settle delay
usbinit ' initialise USB
PAUSE 20 ' Delay after initializing USB
@ Reload_TMR0 ; Reload timer0
ON INTERRUPT GOTO DoUSBService
DataToSend[0] = 0
datatosend[2] = 0 'PORTA.2
datatosend[3] = 0 'PORTA.3
datatosend[4] = 0 'PORTA.4
datatosend[5] = 0 'PORTA.5
datatosend[6] = 0
datatosend[7] = 0
'Main Prog starts here
Start:
if RCIF then
HSERIN [DatatoSend[2]] ' take it
@ SendUSB _DataToSend
endif
gosub dousbin
goto Start
DoUSBIn:
tmr0ie = 0 ' disbale TMR0 int
USBBufferCount = USBBufferSizeRX ' RX buffer size
USBService ' keep connection alive
USBIn 1, USBBufferin, USBBufferCount, Timeout ' read data, if available
Timeout: '
@ Reload_TMR0
tmr0ie = 1 ' re-enable TMR0 int
PORTB = USBBUFFERIN[0] ' output to PORTB
' Not using USBBufferIn[1,2,3,4]
return
DoUSBOut:
TMR0IE = 0 ' Disable TMR0 interrupt
WaitPC: '
USBBufferCount = USBBufferSizeTX ' TX buffer size
USBService ' keep connection alive
USBOut 1, USBBufferOut, USBBufferCount, Waitpc ' if bus available, transmit data
@ Reload_TMR0
tmr0ie=1 ' Re-Enable TMR0 interrupt
return
DISABLE
DoUSBService:
usbservice ' keep connection alive
@ Reload_TMR0 ; reload timer
RESUME ' getout of here
ENABLE
' The VB Program receives the Serial Data using the USBBuffer[2]
I know the the connections work coz if i touch the RX pin i get a string of '255's in the VB prog...
Any suggestions why the text is garbled ? ( I have tried all combinations of T2400,N2400 etc...)
I have also tried using another PIC (628) to receive the serial data and convert it to a parallel o/p on its port and feed it to the 4550...but that doesnt work as well...
At the moment im testing it using two wires (data,gnd) between Tx and Rx and I will add the RF module later