This is a multi-part message in MIME format. ------=_NextPart_000_001F_01C0B112.3CDBF670 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit > anyone here have implemented a FIFO (First In, First Out) buffer for the > hardware USART of a PIC? I'm using a PIC16F877 and it does have to receive > USART and put it on a buffer for later processing. > > How do I implement it? I think I need two variables and an array, like: The attached file contains macros that implement and manipulate FIFOs. They are supposed to work on both the 16xxx and 17xxx families. However, I sortof remember some changes were made since the last time they were verified on the 16xxx family. That's why I haven't added them to my "standard" macros yet in STD.INS.ASPIC at http://www.embedinc.com/pic. ------=_NextPart_000_001F_01C0B112.3CDBF670 Content-Type: text/plain; name="fifo.txt" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="fifo.txt" ; ;*********************************************************************** ; ; Macro FIFO_DEFINE name size ; ; Define a first in, first out queue. The symbol NAME will be defined = as ; the first byte of the queue structure. Size is the maximum number = of ; data bytes the queue can hold. The format of a FIFO is: ; ; name+0 - number of data bytes currently in the queue ; ; name+1 - offset into the queue of where to put the next byte + 1 ; ; name+2 - offset into the queue of where to get the next byte = from + 1 ; ; name+3 thru name+2+size - Data buffer. Sequential bytes are = written ; and read at decreasing addresses until the start of the buffer = is ; reached, in which case the next address wraps back to the end of = the ; buffer. ; fifo_ofs_n equ 0 ;offset from FIFO label for number of bytes = in buffer fifo_ofs_put equ 1 ;offset from FIFO label for PUT index fifo_ofs_get equ 2 ;offset from FIFO label for GET index fifo_ofs_buf equ 3 ;offset from FIFO label for start of buffer fifo_define macro name, size name res 1 ;number of data bytes currently in the = queue res 1 ;put offset res 1 ;get offset res size ;the data buffer endm ; ;*********************************************************************** ; ; Macro FIFO_INIT name ; ; Initialize the FIFO at NAME. The register bank must be set for = access ; to the FIFO state. SIZE is the number of data bytes the FIFO was ; defined for. ; fifo_init macro name clrf name + fifo_ofs_n ;indicate the FIFO is empty movlw 1 movwf name + fifo_ofs_put ;init PUT index movwf name + fifo_ofs_get ;init GET index endm ; ;*********************************************************************** ; ; Macro FIFO_SKIP_EMPTY name ; ; Skips the next instruction after the macro if the FIFO at NAME is ; empty. The register bank must be set for access to the FIFO state. ; fifo_skip_empty macro name if fam_16 || fam_12 movf name + fifo_ofs_n ;set Z if FIFO empty skip_z exitm endif if fam_17 tstfsz name + fifo_ofs_n ;skip if FIFO empty exitm endif error "Macro FIFO_SKIP_EMPTY not implemented for this = processor" endm ; ;*********************************************************************** ; ; Macro FIFO_SKIP_NEMPTY name ; ; Skips the next instruction after the macro if the FIFO at NAME ; contains at least one data byte. The register bank must be set for ; access to the FIFO state. ; ; W may be trashed. ; fifo_skip_nempty macro name if fam_16 || fam_12 movf name + fifo_ofs_n ;set Z if FIFO empty skip_nz ;FIFO not empty ? exitm endif if fam_17 decf name + fifo_ofs_n, w ;set borrow flag if FIFO is empty skip_nborr ;FIFO not empty ? exitm endif error "Macro FIFO_SKIP_NEMPTY not implemented for this = processor" endm ; ;*********************************************************************** ; ; Macro FIFO_SKIP_FULL name size ; ; Skips the next instruction after the macro if the FIFO at NAME is ; completely full. The register bank must be set for access to the ; FIFO state. ; ; W is trashed. ; fifo_skip_full macro name, size movlw size ;get max bytes the FIFO can hold subwf name + fifo_ofs_n, w ;compare to number of bytes = currently in FIFO skip_wle ;FIFO is completely full ? endm ; ;*********************************************************************** ; ; Macro FIFO_SKIP_NFULL name size ; ; Skips the next instruction after the macro if the FIFO at NAME is ; not completely full. The register bank must be set for access to ; the FIFO state. ; ; W is trashed. ; fifo_skip_nfull macro name, size movlw size ;get max bytes the FIFO can hold subwf name + fifo_ofs_n, w ;compare to number of bytes = currently in FIFO skip_wgt ;FIFO is completely full ? endm ; ;*********************************************************************** ; ; Macro FIFO_PUT name size data ; ; Add the byte in DATA as the last byte in the FIFO at NAME. SIZE = must ; be the maximum number of bytes the FIFO was defined to hold. The ; register bank must be set for access to the FIFO and DATA. Since = the ; FIFO is usually not in global RAM, this means DATA must be either in ; global RAM or in the same register bank as the FIFO. ; ; The FIFO may be trashed if it is already full. This should be = checked ; before this macro is called. ; ; Note that if the FIFO could be accessed from the interrupt service ; routine, then interrupts should be temporarily disabled around this ; macro. ; ; W is trashed. ; fifo_put macro name, size, data ; ; 12 and 16 family processors. ; if fam_16 || fam_12 movlw name + (fifo_ofs_buf - 1) ;get address for buffer index = 0 addwf name + fifo_ofs_put, w ;make address of where to write = this new byte movwf fsr ;point to where to write the byte movf data, w ;get the data byte into W movwf indf ;write the data byte into the buffer incf name + fifo_ofs_n ;indicate one more byte now in the = FIFO movlw size ;get offset for last byte in buffer decf name + fifo_ofs_put ;update buffer index to next byte, = set Z on wrap skip_nz ;not just decrement past beginning of = buffer ? movwf name + fifo_ofs_put ;wrap back to end of buffer exitm endif ; ; 17 family processors. ; if fam_17 movlw name + (fifo_ofs_buf - 1) ;get address for buffer index = 0 addwf name + fifo_ofs_put, w ;make address of where to write = this new byte movwf fsr0 ;point to where to write the byte movfp data, indf0 ;write the data byte into the buffer incf name + fifo_ofs_n ;indicate one more byte now in the = FIFO movlw size ;get offset for last byte in buffer dcfsnz name + fifo_ofs_put ;update buffer index, skip on not = wrap movwf name + fifo_ofs_put ;wrap back to end of buffer exitm endif error "Macro FIFO_PUT not implemented for this processor" endm ; ;*********************************************************************** ; ; Macro FIFO_GET name size data ; ; Get the next byte from the FIFO at NAME into DATA. SIZE must ; be the maximum number of bytes the FIFO was defined to hold. The ; register bank must be set for access to the FIFO and DATA. Since = the ; FIFO is usually not in global RAM, this means DATA must be either in ; global RAM or in the same register bank as the FIFO. ; ; The FIFO may be trashed if it is already empty. This should be ; checked before this macro is called. ; ; Note that if the FIFO could be accessed from the interrupt service ; routine, then interrupts should be temporarily disabled around this ; macro. ; ; W is trashed. ; fifo_get macro name, size, data ; ; 12 and 16 family processors. ; if fam_16 || fam_12 movlw name + (fifo_ofs_buf - 1) ;get address for buffer index = 0 addwf name + fifo_ofs_get, w ;make address of where to read = new byte from movwf fsr ;point to where to read the byte from movf indf, w ;get the data byte movwf data ;pass it back decf name + fifo_ofs_n ;indicate one less byte now in the = FIFO movlw size ;get offset for last byte in buffer decf name + fifo_ofs_get ;update buffer index to next byte, = set Z on wrap skip_nz ;not just decrement past beginning of = buffer ? movwf name + fifo_ofs_get ;wrap back to end of buffer exitm endif ; ; 17 family processors. ; if fam_17 movlw name + (fifo_ofs_buf - 1) ;get address for buffer index = 0 addwf name + fifo_ofs_get, w ;make address of where to read = new byte from movwf fsr0 ;point to where to read the byte from movpf indf0, data ;get the data byte and pass it back decf name + fifo_ofs_n ;indicate one less byte now in the = FIFO movlw size ;get offset for last byte in buffer dcfsnz name + fifo_ofs_get ;update buffer index, skip on not = wrap movwf name + fifo_ofs_get ;wrap back to end of buffer exitm endif error "Macro FIFO_PUT not implemented for this processor" endm ------=_NextPart_000_001F_01C0B112.3CDBF670-- ******************************************************************** Olin Lathrop, embedded systems consultant in Littleton Massachusetts (978) 742-9014, olin@embedinc.com, http://www.embedinc.com -- http://www.piclist.com hint: The PICList is archived three different ways. See http://www.piclist.com/#archives for details.