Serial/RS232 Buffer Ring

Explanation:

This program demonstrates how to create a serial input buffer ring.

The program receives a character into the buffer and sends back. Try sending large volumes of characters…​..

This program program uses an interrupt event to capture the incoming byte value and place in the buffer ring. When a byte is received the buffer ring is incremented to ensuer the next byte is handled correctly.

Testing bkbhit will set to True when a byte has been received. Reading the function bgetc will return the last byte received.

Demonstration program:

This demonstration program will support up to 256 bytes. For a larger buffer change the variables to words.

    #chip 16F1937
    // #chip mega4809
    // #chip mega328p, 16


    // Add PPS if appropiate for your chip
    // [change to your config] This is the config for a serial terminal

    // assumes USART1 ( or USART0 on AVRDx ), if you select USART1/2/3/4 then you MUST add the comport parameter to all HSerxxxxx functions.
    // turn on the RS232 and terminal port.
    // Define the USART settings
    #DEFINE USART_BAUD_RATE 9600

    // This assumes you are using an ANSI compatible terminal.  Use PUTTY.EXE it is very easy to use.

    //   Main program

    // Wait for terminal to settle
    wait 3 s

    // Create the supporting variables
    Dim next_in As Byte
    Dim next_out As Byte
    Dim syncbyte As Byte
    Dim temppnt As Byte

    // Constants etc required for Buffer Ring
    #DEFINE BUFFER_SIZE 8
    #DEFINE bkbhit (next_in <> next_out)

    // Define the Buffer
    Dim buffer( BUFFER_SIZE - 1 ) // we will use element 0 in the array as part of out buffer

    // Call init the buffer
    InitBufferRing

    HSerSend 10
    HSerSend 13
    HSerSend 10
    HSerSend 13
    HSerPrint "Started: Serial between two devices"
    HSerSend 10
    HSerSend 13


    // Get character(s) and send back
    // Get character(s) and send back
    Do

        //  Do we have data in the buffer?
        if bkbhit then

            // Send the next character in the buffer to the terminal, exposed via the function `bgetc` back the terminal
            HSerSend bgetc

        end if
    Loop


    // Supporting subroutines

    Sub readUSART

        buffer(next_in) = HSerReceive
        temppnt = next_in
        next_in = ( next_in + 1 ) % BUFFER_SIZE
        If ( next_in = next_out ) Then  // buffer is full!!
            next_in = temppnt
        End If

    End Sub

    Function bgetc
        Dim local_next_out as Byte    // maintain a local copy of the next_out variable to ensure it does not change when an Interrupt happens
        local_next_out = next_out
        bgetc = buffer(local_next_out)
        local_next_out=(local_next_out+1) % BUFFER_SIZE
        INTOFF
        next_out = local_next_out
        INTON
    End Function




    Sub InitBufferRing

        // Set the buffer to the first address
        next_in = 0
        next_out = 0
        // Interrupt Handler - some have RCIE and some have U1RXIE, so handle
        //
        // You would need to change the Interrupt if you use USART1,2,3, or 4
        //
        #IFDEF BIT( RCIE )
            On Interrupt UsartRX1Ready Call readUSART
        #ENDIF
        #IFDEF BIT( U1RXIE )
            On Interrupt UART1ReceiveInterrupt Call readUSART
        #ENDIF

        #IFDEF AVR
            #IFNDEF CHIPAVRDX
                //~ Support for legacy AVR
                On Interrupt UsartRX1Ready Call readUSART
            #ELSE
                //~ Support for AVRDx - AVRDx chips are USART0,USART1,USART2,USART3 and USART4 not USART.
                On Interrupt Usart0RXReady Call readUSART
            #ENDIF
        #ENDIF

    End Sub