+ Reply to Thread
Page 1 of 2
1 2 Last
Results 1 to 15 of 25

Thread: Finding serial START bit by bit banging

  1. #1
    Oznog Excellent Oznog Excellent Oznog Excellent Oznog Excellent Oznog Excellent
    Join Date
    Apr 2004
    Location
    Austin, Tx
    Posts
    2,766

    Default Finding serial START bit by bit banging

    I've seen a number of routines that do bit banging on a serial port. But I don't get how they handle framing problems. There's an assumption that the code can start looking for the start bit at the start of the loop. If the code starts the loop in the middle of a byte though this won't work. First 0 in the bus it'll assume is a START bit. There's a good chance a 1 won't happen in the window it will look for the STOP bit in so it may realize there's a framing error.

    How does the bit banger figure out what the start of the byte's framing is?
    I thought what I'd do was I'd pretend I was one of those deaf-mutes.


  2. #2
    Super Moderator Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent
    Join Date
    Nov 2003
    Location
    Derbyshire, UK
    Posts
    29,794

    Default Re: Finding serial START bit by bit banging

    Quote Originally Posted by Oznog
    I've seen a number of routines that do bit banging on a serial port. But I don't get how they handle framing problems. There's an assumption that the code can start looking for the start bit at the start of the loop. If the code starts the loop in the middle of a byte though this won't work. First 0 in the bus it'll assume is a START bit. There's a good chance a 1 won't happen in the window it will look for the STOP bit in so it may realize there's a framing error.

    How does the bit banger figure out what the start of the byte's framing is?
    The whole point of asyncronous comms is that you MUST detect a clear start bit - if not the whole thing fails, this isn't a 'bit banging' problem, it occurs with hardware UART's as well. There are a number of simple steps you can take to help reject incorrect bytes, for a start test the STOP bit, if this is wrong, then the byte hasn't been read correctly. Secondly, use the parity bit, this will help detect some further errors.

    Generally micro-controller code does neither of these, it's not often required, and modern RS232 is reliable enough without.

    If you're trying to do wireless comms?, then RS232 is completely the wrong choice, wireless schemes (such as Manchester coding) add special start sequences to allow syncronisation of the receiver.
    PIC programmer software, and PIC Tutorials at:
    http://www.winpicprog.co.uk

  3. #3
    Mike, K8LH Excellent Mike, K8LH Excellent Mike, K8LH Excellent Mike, K8LH Excellent Mike, K8LH Excellent Mike, K8LH Excellent Mike, K8LH Excellent
    Join Date
    Jan 2005
    Location
    Michigan, USA
    Posts
    2,522

    Default

    If you check out the various bit-banged serial I/O examples on PICList (and elsewhere) you'll find they basically detect the start bit leading edge, delay approximately 1/2 bit time, then clock in the serial data in the middle of each data bit... There are examples for interrupt driven and non-interrupt serial I/O code...

    The interrupt driven half-duplex 12F683 demo on PICList uses IOC (interrupt on change) to detect a start bit leading edge, then turns off IOC, advances the TMR2 interrupt source by 1/2 bit time, clocks in the start/data/stop bits, and finally switches IOC back on after clocking in the stop bit...

    The interrupt driven full-duplex 16F819 demo on PICList uses TMR2 generated interrupts at 3X the bit rate and a state machine in the ISR (interrupt service routine) to detect a start bit within 00%-33% of the start bit period then clocks in the data bits during the 33%-66% portion of each bit period...

    Regards, Mike[/url]

  4. #4
    Oznog Excellent Oznog Excellent Oznog Excellent Oznog Excellent Oznog Excellent
    Join Date
    Apr 2004
    Location
    Austin, Tx
    Posts
    2,766

    Default Re: Finding serial START bit by bit banging

    Quote Originally Posted by Nigel Goodwin
    The whole point of asyncronous comms is that you MUST detect a clear start bit - if not the whole thing fails, this isn't a 'bit banging' problem, it occurs with hardware UART's as well. There are a number of simple steps you can take to help reject incorrect bytes, for a start test the STOP bit, if this is wrong, then the byte hasn't been read correctly. Secondly, use the parity bit, this will help detect some further errors.

    If you're trying to do wireless comms?, then RS232 is completely the wrong choice, wireless schemes (such as Manchester coding) add special start sequences to allow syncronisation of the receiver.
    I have a setup where the USART is already being used for something else and I need to read NMEA-0183 from a GPS, which is 4800 baud serial data with no parity, so I want to see how bad the resource hit is when bit-banging. No wireless here.

    I know failure to detect the START bit will make the scheme fail. How do we fix it? I imagine if there's a break between characters the code can wait for a long period of 1 on the bus and assume the next 0 is the start bit. But nowhere does the NMEA-183 protocol specification make any promises about such gaps and this needs to work with any GPS. Thus making a scheme which works with one GPS based on features not specified by the protocol proves little since another GPS may not do this.

    Or do we just kick the bit-time state counter over one every time it detects a bad STOP bit, until it starts consistently finding a 1 in the STOP bit time? That does seem like the way to do it.
    I thought what I'd do was I'd pretend I was one of those deaf-mutes.

  5. #5
    Super Moderator Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent
    Join Date
    Nov 2003
    Location
    Derbyshire, UK
    Posts
    29,794

    Default Re: Finding serial START bit by bit banging

    Quote Originally Posted by Oznog
    Or do we just kick the bit-time state counter over one every time it detects a bad STOP bit, until it starts consistently finding a 1 in the STOP bit time? That does seem like the way to do it.
    The answer is simple (as far your questions here are concerned), you simply make sure you don't miss the start bit!. Presumably though this is related to your request for multiple simultaneous serial inputs?, that makes it 'difficult'.
    PIC programmer software, and PIC Tutorials at:
    http://www.winpicprog.co.uk

  6. #6
    Oznog Excellent Oznog Excellent Oznog Excellent Oznog Excellent Oznog Excellent
    Join Date
    Apr 2004
    Location
    Austin, Tx
    Posts
    2,766

    Default Re: Finding serial START bit by bit banging

    Quote Originally Posted by Nigel Goodwin
    The answer is simple (as far your questions here are concerned), you simply make sure you don't miss the start bit!. Presumably though this is related to your request for multiple simultaneous serial inputs?, that makes it 'difficult'.
    Well not being able to recover the framing is a really unreliable port. Either the device was already sending before the device turned on/woke up, transmitter got reset, there was a clock jitter issue, noise on the cable, rare software/interrupt issues made it lose a bit-time, doesn't matter. These things happen.

    How does the hardware USART figure it out? I haven't seen an explanation. If there's a gap between characters the bus will remain high, it'll proceed through its bit times and wait for the next 1->0 transition which will always mean it'll always recognize the START bit after any gap longer than a normal char's transmission time. But is there a good way to do it when there's no gaps between characters?
    I thought what I'd do was I'd pretend I was one of those deaf-mutes.

  7. #7
    Super Moderator Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent
    Join Date
    Nov 2003
    Location
    Derbyshire, UK
    Posts
    29,794

    Default Re: Finding serial START bit by bit banging

    Quote Originally Posted by Oznog
    How does the hardware USART figure it out? I haven't seen an explanation.
    The hardware USART doesn't figure it out, it's no different than a software UART.

    You need to think more generally, and not just on the receive side - it's the transmit side which makes it easily possible.

    1) Don't send continuous data, a gap of more than one word should allow syncronisation to occur.

    2) Use handshaking.
    PIC programmer software, and PIC Tutorials at:
    http://www.winpicprog.co.uk

  8. #8
    motion Newbie
    Join Date
    Jul 2003
    Location
    Quezon City.PH
    Posts
    560

    Default

    I took a look at a summary of the nmea-0183 standard. A sentence is framed by a '$' character in the beginning and a <CR><LF> sequence at the end. Use this to check if you have a valid sentence in case the async port loses bit synchronism. Eventually, the receiver will recover synchronism and you should be able to get a properly framed sentence.
    "Having to do with Motion Control"

  9. #9
    Oznog Excellent Oznog Excellent Oznog Excellent Oznog Excellent Oznog Excellent
    Join Date
    Apr 2004
    Location
    Austin, Tx
    Posts
    2,766

    Default Re: Finding serial START bit by bit banging

    Quote Originally Posted by Nigel Goodwin
    You need to think more generally, and not just on the receive side - it's the transmit side which makes it easily possible.

    1) Don't send continuous data, a gap of more than one word should allow syncronisation to occur.

    2) Use handshaking.
    Remember this is for a GPS interface so it is impossible to do anything to the transmitted data.

    It will also read data from a PC. It will use the same code so the protocol details must be the same. If I dump a data file with a hyperterminal program, are there any implied gaps here or are all the bytes going to end up back to back?

    Quote Originally Posted by motion
    A sentence is framed by a '$' character in the beginning and a <CR><LF> sequence at the end. Use this to check if you have a valid sentence in case the async port loses bit synchronism. Eventually, the receiver will recover synchronism and you should be able to get a properly framed sentence.
    Detecting a framing error would probably not need to go to that level. First the STOP bit will be wrong more or less half the time, if you somehow don't see this then you can detect some nonsense ASCII codes (not alphanumeric, punctuation, space, <CR>, or <LF>), if you somehow don't see that then the sentence format will be wrong too.
    I thought what I'd do was I'd pretend I was one of those deaf-mutes.

  10. #10
    Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent
    Join Date
    Mar 2005
    Location
    Brisbane Australia
    Posts
    6,807

    Default Multiple channel RS232 doable.

    I think you need to track all the input channels simultaneously. This should be doable with a 20MHz 16F628.

    At 4800 baud you would need to interrupt at 3 times the bit rate. Your interrupts need to be at 5,000,000/4800/3 = 347 clock cycles. I just checked my interupt driven bit banger and the worst case path is only 17 cycles long. So, you could easily check 8 channels simultaneously. This would take 17*8 + the overhead of the interrupt, say 20, gives 156 cycles. Less than 50% of the processor time.

    I could modify my code to handle multiple channels if you like and post it.

    Mike.

  11. #11
    motion Newbie
    Join Date
    Jul 2003
    Location
    Quezon City.PH
    Posts
    560

    Default

    Detecting a framing error would probably not need to go to that level. First the STOP bit will be wrong more or less half the time, if you somehow don't see this then you can detect some nonsense ASCII codes (not alphanumeric, punctuation, space, <CR>, or <LF>), if you somehow
    don't see that then the sentence format will be wrong too.
    If you feel you can do a simpler job than checking for a '$' and a <CR>,<LF> sequence, I don't understand what's all the fuss about the start bit.
    "Having to do with Motion Control"

  12. #12
    Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent
    Join Date
    Mar 2005
    Location
    Brisbane Australia
    Posts
    6,807

    Default

    I wouldn't worry about framing errors and detecting stop bits etc. The only way to get into sync is to assume each bit is a start bit. The data will gradually sync up as more 1 bits are sent. Consider the case of sending 0xff, the only thing you would see with a scope would be the start bit.

    This diagram from Nigels tutorial shows it well.



    Note that the stop bit doesn't exist, it is just a gap to allow things to synchronize. Also note if all bits were 1 then the data would be a flat line.

    Mike.

  13. #13
    Super Moderator Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent Nigel Goodwin Excellent
    Join Date
    Nov 2003
    Location
    Derbyshire, UK
    Posts
    29,794

    Default

    Quote Originally Posted by Pommie
    Note that the stop bit doesn't exist, it is just a gap to allow things to synchronize. Also note if all bits were 1 then the data would be a flat line.
    Except for the start bit of course!.

    Quote Originally Posted by motion
    I don't understand what's all the fuss about the start bit.
    The fuss is the requirement to identify it!. Assuming the transmitter is sending continuous data, and you turn the receiver ON - there's no way it can identify the start bit in a continuous data stream, all it can do is indenify ANY zero bit. However, once you have a gap (all ones) longer than a single word, then it can syncronise on the next start bit.
    PIC programmer software, and PIC Tutorials at:
    http://www.winpicprog.co.uk

  14. #14
    Mike, K8LH Excellent Mike, K8LH Excellent Mike, K8LH Excellent Mike, K8LH Excellent Mike, K8LH Excellent Mike, K8LH Excellent Mike, K8LH Excellent
    Join Date
    Jan 2005
    Location
    Michigan, USA
    Posts
    2,522

    Default Re: Multiple channel RS232 doable.

    Quote Originally Posted by Pommie
    I just checked my interupt driven bit banger and the worst case path is only 17 cycles long. ~~~~ I could modify my code to handle multiple channels if you like and post it.

    Mike.
    Mike,

    Is that 17 instruction cycles for 3X bit rate interrupt driven RX only code? If so, that's incredible... I'd very much like to see your code Sir...

    Regards, Mike

  15. #15
    Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent
    Join Date
    Mar 2005
    Location
    Brisbane Australia
    Posts
    6,807

    Default Re: Multiple channel RS232 doable.

    Quote Originally Posted by Mike, K8LH
    Is that 17 instruction cycles for 3X bit rate interrupt driven RX only code? If so, that's incredible... I'd very much like to see your code Sir...
    I counted wrong, it's 18 cycles. However, the modified code is only 16. Here's the original code.

    Code:
    RecSkips        equ     20h
    InByte          equ     21h
    Cache           equ     22h
    TransferFlags   equ     23h
    
    
                    #define RS232In PORTB,2
    
    
                    decfsz  RecSkips,F
                    goto    DoneRS232
                    btfss   TransferFlags,b_receiving
                    goto    get_start_bit
                    bsf     STATUS,C
                    btfss   b_RS232In
                    bcf     STATUS,C
                    rrf     InByte,F
                    movlw   3
                    movwf   RecSkips
                    btfss   STATUS,C
                    goto    DoneRS232
                    movf    InByte,W
                    movwf   Cache
                    bsf     TransferFlags,b_byte_available
                    bcf     TransferFlags,b_receiving
                    goto    DoneRS232
    get_start_bit	incf    RecSkips,F;	set to 1
                    btfsc   b_RS232In
                    goto    DoneRS232
                    movlw   4
                    movwf   RecSkips
                    bsf     TransferFlags,b_receiving
                    movlw   80h
                    movwf   InByte
    DoneRS232
    
    It does away with the need to keep a count of bits received by setting the received byte to 80h. When the last bit is shifted into InByte then the carry will be set. This makes it a lot quicker.


    To make it multi channel, I found it easier to write a macro for each channel. To make sure that the timing is accurate, PORTB is read at the beginning of the interrupt and stored in a temporary variable.

    Here's the macro
    Code:
    ReceiveChannel  Macro   chan
                    rrf     PortTemp,F
                    decfsz  RecSkips+chan,F
                    goto    DoneRS232#v(chan)
                    btfss   b_receiving,chan
                    goto    g_strt#v(chan)
                    rrf     InByte+chan,F
                    movlw   3
                    movwf   RecSkips+chan
                    btfss   STATUS,C
                    goto    DoneRS232#v(chan)
                    movf    InByte+chan,W
                    movwf   cache+chan
                    bsf     b_byte_avail,chan
                    bcf     b_receiving,chan
                    goto    DoneRS232#v(chan)
    g_strt#v(chan)  incf    RecSkips+chan,F;	set to 1
                    btfsc   STATUS,C
                    goto    DoneRS232#v(chan)
                    movlw   4
                    movwf   RecSkips+chan
                    bsf     b_receiving,chan
                    movlw   80h
                    movwf   InByte+chan
    DoneRS232#v(chan)
                    endm
    
    And this is the code that would go in the interrupt routine.

    Code:
                    bcf     PIR1,CCP1IF;	reset special event trigger interupt
    
                    movfw   PORTB;		read all channels at once
                    movwf   PortTemp
    
                    ReceiveChannel  0
                    rrf     PortTemp,F;	skip bit 1
                    rrf     PortTemp,F;	skip bit 2
                    ReceiveChannel  1
                    ReceiveChannel  2
                    ReceiveChannel  3
                    ReceiveChannel  4
                    ReceiveChannel  5
    
    With the above code, if a byte is received on channel 3 (or any of 0 to 5), bit 3 of b_byte_avail will be set and the byte will be in cache+3.

    Mike.
    Last edited by Pommie; 6th July 2008 at 04:13 PM.

+ Reply to Thread
Page 1 of 2
1 2 Last

Tags for this Thread