USB Serial Communication Continuous


Closed Thread
Results 1 to 17 of 17
  1. #1
    Join Date
    Feb 2007
    Posts
    11

    Default USB Serial Communication Continuous

    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

  2. #2
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898

    Default

    I've never tried with a DEFINE OSC 20... but i think it's the main problem.

    Look how i did it in mine. (config fuse as well)

    and now
    Code:
    DoLow:
    LOW PORTC.0
    USBSERVICE
    PAUSE 30
    USBSERVICE
    return

    This example don't use instant interrupt, inserting a PAUSE and using On INTERRUPT GOTO might cause some problem for the USBSERVICE.

    next point...i don't know what's happen if you use both HSER_BAUD and HSER_SPBRG together... Assuming HSER_SPBRG may override the HSER_BAUD, you have a big problem as your SPBRG value is way out of range @20MHZ... but good @8MHZ.

    to have 2400 baud @20MHZ, you should use...
    Code:
    DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
    DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
    DEFINE HSER_SPBRG 129 ' 2400 Baud @ 20MHz, 0.17%
    DEFINE HSER_CLROERR 1 ' Clear overflow automatically
    I do believe the HSER_CLROERR may help a little bit.

    There's probably something else... i feel a bit lazy today
    Last edited by mister_e; - 10th February 2007 at 18:03.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  3. #3
    Join Date
    Feb 2007
    Posts
    11

    Default

    Quote Originally Posted by mister_e View Post
    I've never tried with a DEFINE OSC 20... but i think it's the main problem.

    Look how i did it in mine. (config fuse as well)
    I have tried it with a DEFINE OSC 48 as well....infact the USB interface works fine...i tried to switch on/off the LED pins on you demo and they work ...

    The config fuses are
    24 0E 3E 00 00 83 81 00 0F C0 0F E0 0F 40

    in either case (48 or 20)
    i have defined the PLL and OSC setting in the .inc file so the DEFINE directive has no effect


    in the case of :

    DoLow:
    LOW PORTC.0
    USBSERVICE
    PAUSE 30
    USBSERVICE
    return

    i found that this code does work...and it does generate a delay of 30ms on the Oscilloscope without affecting the Tx USB connection....The TX seems to be transmitting fine...
    Last edited by pic-ker; - 10th February 2007 at 18:01.

  4. #4
    Join Date
    Feb 2007
    Posts
    11

    Default

    Quote Originally Posted by mister_e View Post
    DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
    DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
    DEFINE HSER_SPBRG 129 ' 2400 Baud @ 20MHz, 0.17%
    DEFINE HSER_CLROERR 1 ' Clear overflow automatically

    I do believe the HSER_CLROERR may help a little bit.
    Thanks, I'll try that now...
    Last edited by pic-ker; - 10th February 2007 at 18:17.

  5. #5
    Join Date
    Feb 2007
    Posts
    11

    Default

    I havre tried all the above statements....

    DEFINE HSER_CLROERR 1 is now inculded...

    however im still getting errors...
    i transmit : 239 65 66 67
    I receive : 254 254 6 134 128
    (5 chars for tx of 4 chars)

    maybe its because i used SEROUT in conjunction with HSERIN ?

  6. #6
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898

    Default

    And... do you get always the same results or they are always different?
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  7. #7
    Join Date
    Feb 2007
    Posts
    11

    Default

    Differnet results each time...


    Anyway I have finally got the TX/RX to work !

    Heres the section of the TX code which works:

    IF USBBufferIn[7]=239 then
    SEROUT PORTC.0,T2400,[USBBUFFERIN[7]]
    gosub DoLow
    USBBufferin[7]=0

    if USBBufferIn[1]<>0 then
    SEROUT PORTC.0,T2400,[USBBufferIn[1]]
    gosub DoLow
    USBBufferIn[1]=0
    endif
    USBService
    if USBBufferIn[2]<>0 then
    SEROUT PORTC.0,T2400,[USBBufferIn[2]]
    gosub DoLow
    USBBufferIn[2]=0
    endif
    USBService
    if USBBufferIn[3]<>0 then
    SEROUT PORTC.0,T2400,[USBBufferIn[3]]
    gosub DoLow
    USBBufferin[3]=0
    endif
    USBService
    if USBBufferIn[4]<>0 then
    SEROUT PORTC.0,T2400,[USBBufferIn[4]]
    gosub DoLow
    USBBufferin[4]=0
    endif
    USBService
    if USBBufferIn[5]<>0 then
    SEROUT PORTC.0,T2400,[USBBufferIn[5]]
    gosub DoLow
    USBBufferin[5]=0
    endif
    USBService
    if USBBufferIn[6]<>0 then
    SEROUT PORTC.0,T2400,[USBBufferIn[6]]
    gosub DoLow
    USBBufferin[6]=0
    endif
    USBService
    endif

    gosub dousbin


    goto start

    DoLow:
    USBSERVICE
    PAUSE 65
    USBSERVICE
    return

    Notes:
    1. You need to use the T mode if you are directly connecting PIC's.
    2. Notice the Pause 65 - It now works great with a longer delay...and has no effect on the USB connection.


    Heres part of the modified RX code :

    DEFINE HSER_CLROERR 1 ' Clear overflow automatically
    Define HSER_RCSTA 90h
    Define HSER_BAUD 2400

    The oscillator is set to 20Mhz in both cases using : DEFINE OSC 20
    __________________________________________________ _______________

    Now that the wired link is working....I checked it using a FSK TX/RX pair
    and the problems are endless....
    Completely random characters etc
    Characters appear when i move my hand in the air !
    I have tried a passive Bandpass filter around 2400hz but it doesnt sove the problem...
    I have connected a Schottky TTL gate to the DataOut...for maintaining proper level transitions...
    Also when I connect a LED to the DataOut of the RX it keeps flickering at a fast rate (around 10kz on the oscilloscope),even when the Tx is off...which is probably whats causing the errors..

    Any ideas on how to fix this ? or is the RF module faulty ?

  8. #8
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,166

    Default

    pic-ker, I bet the RF receiver module you are trying to use has no squelch control and the toggling of the receiver output is the data slicer trying to interpret noise. You will have to put some kind of sync and preamble bytes in place before you transmit the data and, if the sync and preamble bytes are not received in order and correctly you should not accept the data. This is the common problem people have when using inexpensive rx and tx modules. Even with more expensive modules the same sync/preamble techniques should be used. Also you should send a computed checksum as the last byte and this checksum should be checked at the receiver end before using the data received.

    Dave Purola,
    N8NTA

  9. #9
    Join Date
    Feb 2007
    Posts
    11

    Default

    Quote Originally Posted by Dave View Post
    pic-ker, I bet the RF receiver module you are trying to use has no squelch control and the toggling of the receiver output is the data slicer trying to interpret noise. You will have to put some kind of sync and preamble bytes in place before you transmit the data and, if the sync and preamble bytes are not received in order and correctly you should not accept the data. This is the common problem people have when using inexpensive rx and tx modules. Even with more expensive modules the same sync/preamble techniques should be used. Also you should send a computed checksum as the last byte and this checksum should be checked at the receiver end before using the data received.

    Dave Purola,
    N8NTA
    Yeah, youre right, the module was really cheap ... it doesnt have a crystal based oscillator, rather there is an inductor coil which can be adjusted by a screwdriver....

    I think it would be better if I get another module :-) instead of doing all that syncing/CRCing etc

  10. #10
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,166

    Default

    pic-ker, Even if you buy a more expensive rf module pair you will still have the same problem. I speak of a squelch circuit that mutes the data line from the receiver when there is no received carrier. However you will still have to send some kind of sync byte for the program to lock onto for the data stream. Also if you don't send some kind of checksum with the data packet you will have no idea of the data bytes in the packet are valid.

    Dave Purola,
    N8NTA

  11. #11
    Join Date
    Feb 2007
    Posts
    11

    Default

    I am sending a sync packet of '239' in a frame of 6 characters, But I find that there is no need for error checking as I am using this mainly for text messaging..

    dave, do you have any kind of squelch circuit in mind ? and how do I detect when the carrier is present ?

  12. #12
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,166

    Default

    pic-ker, There is no easy way to add a squelch circuit unless the receiver you are using has an RSSI output available. This stands for "Reletive Signal Strength Indicator" and it is an output usually derived from the IF portion of the receiver. If this analog signal was to be compared to a reference voltage that signal strength would be the level that the signal has to be to (open or unsquelch or unmute) the the data stream.

    Dave Purola,
    N8NTA

  13. #13
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898

    Default

    Few post before you said you didn't use the RF for now.. is this still true?

    If you receive always different things, it sounds like a baudrate problem to me... dpending your config fuses settings, hardware it may ruine your whole life..

    try a simple serial comm before adding the USB.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  14. #14
    skimask's Avatar
    skimask Guest

    Default

    Quote Originally Posted by pic-ker View Post
    I am sending a sync packet of '239' in a frame of 6 characters, But I find that there is no need for error checking as I am using this mainly for text messaging..

    dave, do you have any kind of squelch circuit in mind ? and how do I detect when the carrier is present ?
    There's a big, long thread (Serin Serout Problem is what I think it's called) that's got loads of good info on how to use some of those cheap RF modules, explanations on the preambles, sync's, etc.etc., why you need them, how many to put out there, etc. Lots of answers for you in there...

  15. #15
    Join Date
    Feb 2007
    Posts
    11

    Default

    Quote Originally Posted by mister_e View Post
    Few post before you said you didn't use the RF for now.. is this still true?

    If you receive always different things, it sounds like a baudrate problem to me... dpending your config fuses settings, hardware it may ruine your whole life..

    try a simple serial comm before adding the USB.
    Its true, I tested the TX/RX using a wire initially and there were absolutely no problems with the baudrate or noise etc

    Now that I have attached the RF modules I get errors..its probably because this module uses ASK

    Ideally the module should not require CRC bits, what I mean is if you send a '1' you should get a '1'

    Im trying another data link from here:
    www.cappels.org/dproj/LCRFLINK/LCRFLINK.htm

    i'll try it and let you guys know...

  16. #16
    skimask's Avatar
    skimask Guest

    Default

    Quote Originally Posted by pic-ker View Post
    Its true, I tested the TX/RX using a wire initially and there were absolutely no problems with the baudrate or noise etc
    Now that I have attached the RF modules I get errors..its probably because this module uses ASK
    Ideally the module should not require CRC bits, what I mean is if you send a '1' you should get a '1'
    Im trying another data link from here:
    www.cappels.org/dproj/LCRFLINK/LCRFLINK.htm
    i'll try it and let you guys know...
    Most of those RF modules use ASK. And generally, they don't need CRC bits (that's all up to you), but what they do need is manchester encoding (aka bi-phase encoding) to keep the internal data slicer from losing it's mind.
    Search for and check that thread I mentioned earlier and you'll see. Basically, you end up cutting your data rate in half by changing all the 1's to '10' and 0's to '01'. Sounds silly but it works great.

  17. #17
    Join Date
    Feb 2007
    Posts
    11

    Default

    Quote Originally Posted by skimask View Post
    Most of those RF modules use ASK. And generally, they don't need CRC bits (that's all up to you), but what they do need is manchester encoding (aka bi-phase encoding) to keep the internal data slicer from losing it's mind.
    Search for and check that thread I mentioned earlier and you'll see. Basically, you end up cutting your data rate in half by changing all the 1's to '10' and 0's to '01'. Sounds silly but it works great.
    I got my RF module to work...I was using the +VCC from the USB port to power the receiver and that was causing some continuous ripple

    I used a battery supply,connected the grounds,used a 0.01uF decoupling cap and now it works..

    Thank you guys for your suggestions...
    I will post the complete project once the VB.net Code is complete..

Similar Threads

  1. Dynamic USB Serial Number (PIC18F4550)
    By awmt102 in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 16th July 2009, 17:03
  2. Serial data to USB
    By cooksydesign in forum USB
    Replies: 18
    Last Post: - 29th October 2008, 15:10
  3. USB and serial cable connection(s)
    By ardhuru in forum Schematics
    Replies: 3
    Last Post: - 18th August 2008, 15:26
  4. Bafo USB to serial adapter
    By ardhuru in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 29th July 2006, 18:48
  5. Serial to USB converter
    By jrt4fun in forum USB
    Replies: 6
    Last Post: - 8th August 2005, 15:14

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts