Explanation:
This program demonstrates how to create a serial input buffer ring.
The program receives a character into the buffer and sends it back. Try sending large volumes of characters.
This program uses an interrupt event to capture the incoming byte value and place it in the buffer ring. When a byte is received, the buffer ring is incremented to ensure the next byte is handled correctly.
Testing bkbhit will be 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 appropriate 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
#DEFINE USART_BLOCKING // Required, could use #define USART_TX_BLOCKING as the RX is interrupt driven.
// 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 our 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
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` ' <<< draining the buffer ring one character at a time
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 SubKey line: HSerSend bgetc — calls the function bgetc, which pulls the oldest byte out of the ring buffer and advances the read pointer, then immediately transmits that byte back
to the terminal; this only runs when bkbhit reports the buffer is non-empty.
See Also:
- HSerReceive — receiving a byte directly, called from the interrupt handler above
- HSerSend — sending a byte, used above to echo the buffered character

