' Name : SERBUFX.pbp ' Compiler : PICBASIC PRO Compiler 2.6 ' Assembler : PM or MPASM ' Target PIC : 40-pin 16F877, 877A or similar ' Hardware : LAB-X1 Experimenter Board ' Oscillator : 4MHz external crystal ' Keywords : HSERIN, ON INTERRUPT, LCDOUT ' Description : PICBASIC PRO program to demonstrate an interrupt-driven ' input buffer for Hserin using On Interrupt. Pin definitions compatible ' with LAB-X1 and PIC16F877. ' ' Defines for LCD and USART Define HSER_RCSTA 90h Define HSER_TXSTA 24h Define HSER_BAUD 9600 Define LCD_DREG PORTD Define LCD_DBIT 4 Define LCD_RSREG PORTE Define LCD_RSBIT 0 Define LCD_EREG PORTE Define LCD_EBIT 1 RCIF VAR PIR1.5 ' Alias RCIF (USART Receive Interrupt Flag) OERR VAR RCSTA.1 ' Alias OERR (USART Overrun Error Flag) CREN VAR RCSTA.4 ' Alias CREN (USART Continuous Receive Enable) LED VAR PORTD.0 ' Alias LED to PORTD.0 buffer_size CON 32 ' Sets the size of the ring buffer buffer VAR BYTE[buffer_size] ' Array variable for holding received characters index_in VAR BYTE ' Pointer - next empty location in buffer index_out VAR BYTE ' Pointer - location of oldest character in buffer bufchar VAR BYTE ' Stores the character retrieved from the buffer i VAR BYTE ' loop counter col VAR BYTE ' Stores location on LCD for text wrapping errflag VAR BYTE ' Holds error flags ADCON1 = 7 ' Set PortA and E to digital operation ' Initialize variables index_in = 0 index_out = 0 i = 0 col = 1 Low PORTE.2 ' LCD R/W line low (W) Pause 100 ' Wait for LCD to start LCDOut $fe,1 ' Clear LCD INTCON = %11000000 ' Enable interrupts ON INTERRUPT GoTo serialin ' Declare interrupt handler routine PIE1.5 = 1 ' Enable interrupt on USART ' Main program starts here - blink an LED at 1Hz mainloop: High LED ' Turn on LED connected to PORTD.0 For i = 0 to 250 ' Delay for .5 seconds (250*2mS) Pause 2 ' Use a short pause within a loop Next i ' instead of one long pause Low LED ' Turn off LED connected to PORTD.0 For i = 0 to 250 ' Delay for .5 seconds (250*2mS) Pause 2 ' Use a short pause within a loop Next i ' instead of one long pause display: ' dump the buffer to the LCD IF errflag Then error ' Handle error if needed IF index_in = index_out Then mainloop ' loop if nothing in buffer GoSub getbuf ' Get a character from buffer LCDOut bufchar ' Send the character to LCD col = col + 1 ' Increment LCD location IF col > 20 Then ' Check for end of line col = 1 ' Reset LCD location LCDOut $fe,$c0,REP " "\20 ' Clear line-2 of LCD LCDOut $FE,2 ' Tell LCD to return home EndIF GoTo display ' Check for more characters in buffer ' Subroutines Disable ' Don't check for interrupts in this section getbuf: ' move the next character in buffer to bufchar index_out = (index_out + 1) ' Increment index_out pointer (0 to 63) IF index_out > (buffer_size-1) Then index_out = 0 ' Reset pointer if outside of buffer bufchar = buffer[index_out] ' Read buffer location Return error: ' Display error message if buffer has overrun IF errflag.1 Then ' Determine the error LCDOut $FE,$c0,"Buffer Overrun" ' Display buffer error on line-2 Else LCDOut $FE,$c0,"USART Overrun" ' Display usart error on line-2 EndIF LCDOut $fe,2 ' Send the LCD cursor back to line-1 home For i = 2 to col ' Loop for each column beyond 1 LCDOut $fe,$14 ' Move the cursor right to the right column Next i errflag = 0 ' Reset the error flag CREN = 0 ' Disable continuous receive to clear overrun flag CREN = 1 ' Enable continuous receive GoTo display ' Carry on ' Interrupt handler serialin: ' Buffer the character received IF OERR Then usart_error ' Check for USART errors index_in = (index_in + 1) ' Increment index_in pointer (0 to 63) IF index_in > (buffer_size-1) Then index_in = 0 ' Reset pointer if outside of buffer IF index_in = index_out Then buffer_error ' Check for buffer overrun HSerin [buffer[index_in]] ' Read USART and store character to next empty location IF RCIF Then serialin ' Check for another character while we're here Resume ' Return to program buffer_error: errflag.1 = 1 ' Set the error flag for software ' Move pointer back to avoid corrupting the buffer. MIN insures that it ends up within the buffer. index_in = (index_in - 1) MIN (buffer_size - 1) HSerin [buffer[index_in]] ' Overwrite the last character stored (resets the interrupt flag) usart_error: errflag.0 = 1 ' Set the error flag for hardware Resume ' Return to program End