gives a useful UART routine with interrupt driven receiver. It is MikroPascal, so for us peasants with MikroBasic, I have done a little translation and also modified it for a PIC16F877A running on a 12Mhz resonator (on an easyPic4 board if anyone wants to know).
It gives excellent results with the IDE usart tool, even at 2400 baud and a 1mS repeat rate set. Adding a 1000mS delay between the buffer read and Uart1 write command still captures all the buffer data up to the max buffer size set.
First the usage program, just calls the routines from the interrupt.
Code: Select all
program Pascal_Uart
'*******************************************************************************
include "UsartReceiver"
dim i as byte
'Could poll the bit RCIF if not using interrupts.
'In this case, do not set GIE, RCIE_bit {= PIE1.RCIE} or PEIE_bit{= INTCON.PEIE}
'Just poll for RCIF bit set on data rx
'*******************************************************************************
sub procedure interrupt()
if RCIF_bit = 1 then
UsartReceiverInterrupt 'call the interrupt service routine.
end if 'The interrupt flag RCIF_bit is cleared within it
end sub
'*******************************************************************************
Main:
ADCON1 = 0x07
porta = 0
trisa = 0xF0
Trisb = 00
portb = 0
Uart1_Init(2400) ' // Init Usart
UsartReceiverInit ' // <--- initialization of the unit
GIE_bit = 1 '// enable interrupts (needed by the uart receiver)
while true
if UsartCharPresent then 'main receive loop
i = ReadUsartByte '... // do something with it...
Uart1_write (i)
end if
wend
end.
Code: Select all
module UsartReceiver
include "Globals"
'/Based on application by D. Rosseel
'// Original: 17-08-2008
'// Latest update: 26-04-2010
'////AD version 19-05-2011 modifed from MikroPascal to MikroBasicPro
' History:
' 26-04-2010: used "bits" out of the definitions files instead of the full definition,
' e.g. "RCIF_bit" in stead of "PIR1.RCIF". No functionality change.
'
' Include file "Globals". The size of the receive buffer is defined there in "const UsartBuffSize = xxx":
'
' This unit receives Usart Data using the Usart hardware, interrupt based.
'
' A Usart receive buffer is implemented.
'
' It is a replacement for "Usart_Read(var error : byte) : byte;" from the "Usart Library".
' This unit provides the function "UsartCharPresent: boolean;" to find out if characters are received.
'
' It assumes the routine "Usart_Init(const baud_rate : longint)" has been called in advance.
'
' interface:
dim UsartBufferOverflow as boolean '(public variable)
' Indicates if a character was received while the UsartBuffer was full.
' Has to be set to "false" by the application that uses this unit.
sub function UsartCharPresent as boolean 'Returns "true" if at least one character is in the buffer (received but not yet read)
sub function ReadUsartByte as byte 'Returns the next received character in the Usart buffer
sub procedure UsartReceiverInterrupt
sub procedure UsartReceiverInit
' For the UsartBuffer a "Queue" mechanism is used:
'
' * The 2 pointers (WritePtr/ReadPtr) start at the same buffer address.
'
' * A new element is placed at the current [WritePtr], and WritePtr is incremented (WritePtr++).
' If it passes the buffer top address, it is 'folded back' to the lowest address.
' * The buffer is "not empty" now (anymore).
' * If WritePtr gets to be equal to ReadPtr after the WritePtr increment, the buffer is "full".
'
' * When you want to get a element off the buffer, you read the [ReadPtr] position,
' and the ReadPtr pointer gets incremented (ReadPtr++).
' If it passes the top buffer address, is folded back to the lowest address.
' * The buffer is "not full" now (anymore).
' * If ReadPtr is equal WritePtr after the ReadPtr increment, the buffer is "empty".
'*******************************************************************************
implements
dim UsartBuffer as byte[UsartBuffSize] 'buffer array
dim UsartBuffWritePtr, UsartBuffReadPtr as word 'pointers
dim UsartBufferEmpty, UsartBufferFull, UsartError as boolean
dim UsartData as byte
'*******************************************************************************
'Set up receiver
sub procedure UsartReceiverInit
UsartBuffWritePtr = 0
UsartBuffReadPtr = 0
UsartBufferEmpty = true
UsartBufferFull = false
UsartBufferOverflow = false
RCIF_bit = 0 '{= PIR1.RCIF} // clear interrupt flag
RCIE_bit = 1 '{= PIE1.RCIE} // enable Usart interrupts
PEIE_bit = 1 '{= INTCON.PEIE} // enable peripheral interrupts
end sub
'*******************************************************************************
'detect Char(s) in buffer by testing UsartBufferEmpty state
sub function UsartCharPresent as boolean
Result = false
if (UsartBufferEmpty = false) then
Result = true
end if
end sub
'*******************************************************************************
'Read byte(s) from UsartBuffer
sub function ReadUsartByte as byte
RCIE_bit = 0 ' Disable Usart Interrupts
if UsartBufferEmpty = false then
Result = UsartBuffer[UsartBuffReadPtr]
Inc(UsartBuffReadPtr)
if UsartBuffReadPtr = UsartBuffSize then
UsartBuffReadPtr = 0
end if
UsartBufferFull = false
UsartBufferEmpty = (UsartBuffReadPtr = UsartBuffWritePtr)
' assignment "=" (operator "=") looks like: =
'if UsartBuffReadPtr = UsartBuffWritePtr then
' UsartBufferEmpty = true
' end if
end if
RCIE_bit = 1 ' Enable Usart Interrupts again
end sub
'*******************************************************************************
sub procedure UsartReceiverInterrupt
UsartError = false
UsartData = RCREG ' this read action also clears the interrupt flag.
if (RCSTA and %00000110) > 0 then 'error
CREN_bit = 0
CREN_bit = 1 'Restart Usart reception
UsartError = true
end if
if UsartError = false then
if UsartBufferFull = false then
UsartBuffer[UsartBuffWritePtr] = UsartData
Inc(UsartBuffWritePtr)
if UsartBuffWritePtr = UsartBuffSize then
UsartBuffWritePtr = 0
end if
UsartBufferEmpty = false
UsartBufferFull = (UsartBuffWritePtr = UsartBuffReadPtr)
' assignment "=" (operator "=") looks like:
'if (UsartBuffWritePtr = UsartBuffReadPtr) then
' UsartBufferFull = true
' end if
else UsartBufferOverflow = true
end if
end if
end sub
end.
Code: Select all
module Globals
const UsartBuffSize = 30
implements
end.