Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

flush RCREG in USART

Status
Not open for further replies.

zhaniko93

New Member
hello.
I'm interested and confused about RCREG flush just before I start receiving.
As I'm concerned, flush is just to clrf rcreg yes? I have seen where flush is done so:
Code:
RCREG=RCREG;
RCREG=RCREG;
RCREG=RCREG;

Or so:
Code:
   movfw RCREG 
   movfw RCREG 
   movfw RCREG

or just clrf. I am inetersted in what exactly flushing is and why it is required before getting anything? and also, is movfw RCREG a way to clear it or what? what does it actually do? I'm fully confused
 
If you're using the PIC line of MCUs there's no need to do anything to RCREG but read it. The location is read only and automatically cleared upon a successful read of the register.
 
movfw RCREG -

movfw means MOVe File into W. The contents of the file name after the instruction (in this case RCREG) get moved into W.

This is considered a "read" instruction and clears one level of RCREG upon executing the instruction. If RCREG is a 2 level buffer, you would read it twice to clear it completely.

The RSR (Receive Shift Register) cannot overwrite the contents in RCREG upon receiving a byte, which is why RCREG must be cleared in order for the RSR to transfer the received byte into RCREG. If RCREG is already full upon the RSR receiving the complete byte, it sets the Overrun Error Flag (OERR), which must be cleared in software by clearing bit CREN in register RCSTA, reading the RCREG register to clear it (i.e. move its contents into W), then setting bit CREN in register RCSTA.
 
Last edited:
so there's something in RCREG at the startup?
 

Attachments

  • 000esp02.gif
    000esp02.gif
    44.8 KB · Views: 515
So why is it needed to flush it at the startup? without flushing, it didn't work (I tried it and it didn't)
 
So why is it needed to flush it at the startup? without flushing, it didn't work (I tried it and it didn't)

When you say it didnt work, what exactly happens.??

Post your code.
 
Last edited:
Code:
        LIST P=16F628, R=DEC    ; Use the PIC16F628 and decimal system

        #include "P16F628.INC"  ; Include header file

        __config  _INTRC_OSC_NOCLKOUT & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_ON & _MCLRE_OFF
	errorlevel -302, -207, -203
        CBLOCK 0x20             ; Declare variable addresses starting at 0x20 
           TMP1
        ENDC
; -------------------------------- 
; SET ANALOG/DIGITAL INPUTS PORT A 
; -------------------------------- 
; 
        movlw 7 
        movwf CMCON             ; CMCON=7 set comperators off 
; 
; ---------------- 
; INITIALIZE PORTS 
; ----------------
BANKSEL CCP1CON

movlw b'00111100'
movwf CCP1CON

movlw b'00000101' ; TMR2 = on, prescale = 1:4
movwf T2CON

movlw b'01111101' ; set bits 9 - 2
movwf CCPR1L


 
; 
        movlw b'00000000'       ; set up portA 
        movwf PORTA

        movlw b'00000100'       ; RB2(TX)=1 others are 0 
        movwf PORTB

        bsf STATUS,RP0          ; RAM PAGE 1

        movlw 0x00 
        movwf TRISA             ; portA all pins input

        movlw b'11110010'       ; RB7-RB4 and RB1(RX)=input, others output 
        movwf TRISB

; ------------------------------------ 
; SET BAUD RATE TO COMMUNICATE WITH PC 
; ------------------------------------ 
; Boot Baud Rate = 9600, No Parity, 1 Stop Bit 
; 
        movlw 0x19              ; 0x19=9600 bps (0x0C=19200 bps) 
        movwf SPBRG 
        movlw b'00100100'       ; brgh = high (2) 
        movwf TXSTA             ; enable Async Transmission, set brgh

        bcf STATUS,RP0          ; RAM PAGE 0

        movlw b'10010000'       ; enable Async Reception 
        movwf RCSTA 
; 

; ------------------------------------ 
; PROVIDE A SETTLING TIME FOR START UP 
; ------------------------------------ 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Without the following code, on my PC I just can't control the PWM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        movfw RCREG 
       movfw RCREG 
      movfw RCREG            ; flush receive buffer 
; 
; --------- 
; MAIN LOOP 
; --------- 
; 
        call message            ; send "16F628 alive" 
loop    call receive            ; wait for a char 
        call send               ; send the char 
        goto loop 
; 
; ------------------------------------------- 
; RECEIVE CHARACTER FROM RS232 AND STORE IN W 
; ------------------------------------------- 
; This routine does not return until a character is received. 
; 
receive btfss PIR1,RCIF         ; (5) check for received data 
        goto receive
        movfw RCREG            ; save received data in W 
        call EnCheck
        return 
; 
; ------------------------------------------------------------- 
; SEND CHARACTER IN W VIA RS232 AND WAIT UNTIL FINISHED SENDING 
; ------------------------------------------------------------- 
; 
send  movwf TXREG
   bsf STATUS,RP0          ; RAM PAGE 1 
   WtHere1  btfss TXSTA,TRMT        ; (1) transmission is complete if hi 
        goto WtHere1

        bcf STATUS,RP0          ; RAM PAGE 0 
        return 
; 
; ------- 
; MESSAGE 
; ------- 
; 
message movlw  'H' 
        call send 
       movlw  'I' 
        call send 
       movlw ' '
        call send 
       movlw  'F' 
        call send 
       movlw  'r' 
        call send 
       movlw  'o' 
        call send 
      movlw  'm' 
        call send 
       movlw  ' '
        call send 
       movlw  'J' 
        call send 
       movlw  'a' 
        call send 
       movlw  'K' 
        call send 
       movlw  'o' 
        call send 
       movlw  0x0D 
        call send 
       
        return



EnCheck movwf TMP1
sublw 'w'
btfsc STATUS, Z
call Win
movfw TMP1
sublw 's'
btfsc STATUS, Z
call Ukan
movfw TMP1

return


Win incf CCPR1L
incf CCPR1L
incf CCPR1L
incf CCPR1L
incf CCPR1L
movlw 0xFF
movwf PORTA
retlw 0

Ukan decf CCPR1L
decf CCPR1L
decf CCPR1L
decf CCPR1L
decf CCPR1L
clrf PORTA
retlw 0

        END [\CODE]
 
hi,
It works fine for me , with and with out your flushes.???

Your PWM problem is some other cause.
 

Attachments

  • 000esp03.gif
    000esp03.gif
    10.8 KB · Views: 323
  • 000esp05.gif
    000esp05.gif
    11.3 KB · Views: 369
So you mean that those three movfw RCREG-s are useless? they aren't needed? than why doesn't it work on my pic? I think that in reality there is something different for which it's needed to flush.
 
zhaniko93 said:
So you mean that those three movfw RCREG-s are useless? they aren't needed? than why doesn't it work on my pic? I think that in reality there is something different for which it's needed to flush.

No offense but "in reality" your code is totally hosed.

I'm currently working with your code and making corrections. However, in your TRISB setup you have to set both bits RB1 and RB2 to assign them to the USART. From there the USART handles which is RX and which is TX.

Here is an excerpt taken from the 16F628 datasheet which states this -

**broken link removed**
 
Last edited:
Here...try this code -

Code:
		LIST 	         P=16F628	 ;processor is 16F628
		include		 <P16F628.INC>	 ;Include header file
		radix		 decimal	 ;all digits are decimal unless otherwise stated

		__config _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_ON & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT
		errorlevel	-302		 ;suppress all bank switching assembler messages
		
;-----------------
; EQUATES
;-----------------

TMP1		EQU		0x20		 ;RAM address of TMP1 register is hex address 0x20

; ----------------
; INITIALIZE PORTS
; ----------------

; portA all pins output

		movlw 		0x00
		banksel		TRISA
		movwf 		TRISA 

;RB4 - RB7 input, RB1/RX and RB2/TX assigned to USART, all else outputs

		movlw		b'11110110' 
		movwf 		TRISB

;enable PWM mode

		movlw		b'00111100'
		banksel		CCP1CON
		movwf		CCP1CON

;enable Timer2 with 1:4 prescaler

		movlw		b'00000101' ; TMR2 = on, prescale = 1:4
		movwf		T2CON

; set bits 9 - 2

		movlw		b'01111101'
		movwf		CCPR1L
		
;disable on chip comparator

		movlw		0x07
		movwf		CMCON

;initialize Port A

		movlw		b'00000000' 
		movwf		PORTA

;initialize Port B

	 	bcf		PORTB,0
		bcf		PORTB,3	

; ------------------------------------
; SET BAUD RATE TO COMMUNICATE WITH PC
; ------------------------------------

; Boot Baud Rate = 9600, No Parity, 1 Stop Bit

		movlw 		0x19		; 0x19=9600 bps (0x0C=19200 bps)
		banksel		SPBRG
		movwf 		SPBRG
		bcf		TXSTA,SYNC	;enable async serial
                bsf		TXSTA,TXEN	;enable serial transmission
		
		banksel		RCSTA
		bsf		RCSTA,SPEN	;enable serial port
		bsf		RCSTA,CREN	;enable continuous receive

; ------------------------------------
; PROVIDE A SETTLING TIME FOR START UP
; ------------------------------------

; ---------
; MAIN LOOP
; ---------

		call		 message 	; send "16F628 alive"
loop		call		 receive	; wait for a char
		call 		 send		; send the char
		goto		 loop

; -------------------------------------------
; RECEIVE CHARACTER FROM RS232 AND STORE IN W
; -------------------------------------------

; This routine does not return until a character is received.

receive		 btfss		RCSTA,OERR
		 btfsc		RCSTA,FERR
		 call		SERIAL_ERR_CLR
receive_w8	 btfss 		PIR1,RCIF 	; (5) check for received data
		 goto 		receive_w8
		 movfw		RCREG		; save received data in W
        	 movwf		TMP1		
		 call		EnCheck
		 return
;
; -------------------------------------------------------------
; SEND CHARACTER IN W VIA RS232 AND WAIT UNTIL FINISHED SENDING
; -------------------------------------------------------------
;
send 		movwf		TXREG
	 	banksel		TXSTA	  	; RAM PAGE 1
WtHere1		btfss		TXSTA,TRMT 	; (1) transmission is complete if hi
		goto		WtHere1

		bcf		 STATUS,RP0 	; RAM PAGE 0
		return

; -------
; MESSAGE
; -------

;send message "HI From JaKo" along with hex value 0x0D

message		movlw		 A'H'
		call		 send
		movlw		 A'I'
		call		 send
		movlw		 A' '
		call		 send
		movlw		 A'F'
		call send
		movlw 		 A'r'
		call 		 send
		movlw 		 A'o'
		call 		 send
		movlw		 A'm'
		call		 send
		movlw 		 A' '
		call 		 send
		movlw 		 A'J'
		call 		 send
		movlw		 A'a'
		call 		 send
		movlw 		 A'K'
		call 		 send
		movlw		 A'o'
		call		 send
		movlw		 0x0D
		call		 send

		return

EnCheck 	movlw		 A'w'
		subwf		 TMP1,W
		btfsc 		 STATUS, Z
		call		 Win
		movlw		 A's'
		subwf		 TMP1,W
		btfsc 		 STATUS, Z
		call 		 Ukan
		movfw		 TMP1

		return

Win 		movlw		5
		addwf		CCPR1L,F
		movlw		0xFF
		movwf 		PORTA
		retlw		0

Ukan 		movlw		5
		subwf		CCPR1L,F
		clrf 		PORTA
		retlw		0

SERIAL_ERR_CLR	bcf		RCSTA,CREN
		movfw		RCREG
		movfw		RCREG
		bsf		RCSTA,CREN
		return

		END

After correcting the code I removed your other error code excludes besides the error 302. I also test assembled it in MPASM and it assembled fine with no errors returned.

I've also removed the RCREG flush instructions you had in there as well. I then added instructions to check the Overrun and Framing Error flags prior to waiting for the receive interrupt flag upon calling the receive subroutine. Also, I added a subroutine to clear the receive error condition upon a receive error occuring. These flags should be checked and addressed accordingly prior to receiving any serial data as serial receive is disabled upon the Overrun and Framing error flags being set.

I noticed that you're using the internal oscillator. However, serial communications is timing critical and the on chip oscillator may not be accurate enough for it to work reliably. I suggest using an external crystal oscillator. I use the high speed oscillator with a 20MHz crystal, but for the baud rate you're running at you'll probably only need a 4MHz crystal for your project.
 
Last edited:
Jon Wilder
Thank you very much I will read your code through and pay attention on every instruction and ask if any question arises
 
can you please tell me what is continuous receive? (CREN bit)
 
Bit CREN is the Continuous Receive Enable bit and is bit 4 of the RCSTA register. Just like bit TXEN in the TXSTA register enables asynchronous serial transmission, CREN enables asynchronous serial reception. ;)

You can locate this information on page 80 of the 16F628A datasheet -

**broken link removed**

The 16F628 data sheet can be found here -

https://www.electro-tech-online.com/custompdfs/2010/12/40044F.pdf

Now there's also bit SREN which is Single Receive Enable. However, you have to set that bit every time you expect to receive data as the hardware will clear it upon completion of receiving one byte of serial data. CREN will stay set until you clear it in software, which you should never have to do.
 
Last edited:
I just made a few more slight changes to the code...mainly for the sake of making it easier to read. Changes made -

Added Code Protection Off and Data Code Protection Off to the configuration word
Changed the cblock directive to an "Equates" line

About cblock...while it works, you mainly only use that for the sake of defining multiple RAM register labels. Since you only have 1 RAM register label, a single Equates line is all that is needed and helps to tighten up the code a bit.
 
Last edited:
Here...try this code -

Code:
; -------------------------------------------------------------
; SEND CHARACTER IN W VIA RS232 AND WAIT UNTIL FINISHED SENDING
; -------------------------------------------------------------
;
send 		movwf		TXREG
	 	banksel		TXSTA	  	; RAM PAGE 1
WtHere1	btfss		TXSTA,TRMT 	; (1) transmission is complete if hi
		goto		WtHere1

		bcf		 STATUS,RP0 	; RAM PAGE 0
		return


Hi,

Just thought you could improve your code -


Code:
; -------------------------------------------------------------
; CHECK PREVIOUS TRANSMISSION COMPLETE AND SEND NEW BYTE
; -------------------------------------------------------------------
;
send 		
	 	banksel	TXSTA	  	; RAM PAGE 1
WtHere1	btfss		TXSTA,TRMT 	;  previous transmission is complete ?
		goto		WtHere1
                banksel 0                            ; RAM PAGE 0
                movwf	TXREG                ; load and send new byte
		return
 
Last edited:
Hi,

Just thought you could improve your code -


Code:
;
; -------------------------------------------------------------
; SEND CHARACTER IN W VIA RS232 AND WAIT UNTIL FINISHED SENDING
; -------------------------------------------------------------
;
send 	 	banksel		TXSTA	  	; RAM PAGE 1
WtHere1		btfss		TXSTA,TRMT 	; (1) transmission is complete if hi
		goto		WtHere1

		banksel		0 	; RAM PAGE 0
		movwf		TXREG
		return

Ah I see what you've done here. Allow it to send the byte without the code having to be tied to the UART while sending the byte unless it tries to send the next byte prior to the previous byte send being completed. Good one!
 
Last edited:
Many of us old timers use the TXIF flag which is located in bank 0 on 16F devices (except for the new "enhanced" 16F devices);

Code:
;
Get232  btfss   PIR1,RCIF       ; character available?            |B0
        goto    Get232          ; no, branch, else                |B0
        movf    RCREG,W         ; get character                   |B0
        return                  ;                                 |B0
;
Put232  btfss   PIR1,TXIF       ; transmit buffer empty?          |B0
        goto    Put232          ; no, branch, else                |B0
        movwf   TXREG           ; send character                  |B0
        return                  ;                                 |B0
If it helps anyone, here's a 16F88 demo' I posted for Mosaic to try with Hyperterminal. It would need minor changes for a 16F628A;

Code:
;******************************************************************
;*                                                                *
;*  Filename: 16F88 USART Test.asm                                *
;*    Author: Mike McLaren, K8LH                                  *
;*   (C)2010: Micro Application Consultants                       *
;*      Date: 19-Aug-06                                           *
;*                                                                *
;*   16F88 USART Test Program                                     *
;*                                                                *
;*                                                                *
;*     MPLab: 7.40    (tabs=8)                                    *
;*     MPAsm: 5.03                                                *
;*                                                                *
;******************************************************************

        processor PIC16F88
        include   P16F88.INC
        errorlevel -302
        list st=off

        __CONFIG  _CONFIG1, _LVP_OFF&_PWRTE_ON&_WDT_OFF&_INTRC_IO
        __CONFIG  _CONFIG2, _IESO_OFF&_FCMEN_OFF
;
;       _CP_OFF                 ; default, no code protect
;       _CCP1_RB0               ; default, CCP1 on RB0 pin
;       _DEBUG_OFF              ; default, debug mode off
;       _WRT_PROTECT_OFF        ; default, write protect off
;       _CPD_OFF                ; default
;       _LVP_OFF                ; -- low voltage programming off
;       _BODEN_ON               ; default, brown out detect on
;       _MCLR_ON                ; default,
;       _PWRTE_ON               ; -- power up timer enabled
;       _WDT_OFF                ; -- watch dog timer off
;       _INTRC_IO or _HS_OSC    ; -- INTOSC
;

PtrL    equ     h'20'           ; PutString routine
PtrH    equ     h'21'           ; PutString routine

;
;  PutStr macro - print in-line character string
;
PutStr  macro   str             ;
        local   String, Print
        movlw   low String      ;
        movwf   PtrL            ;
        movlw   high String     ;
        movwf   PtrH            ;
        goto    Print           ;
String  dt      str,0
Print   call    PutString       ; print string
        endm

;******************************************************************
;*                                                                *
;******************************************************************
        org     0x000
v_reset
        clrf    STATUS          ; force bank 0, IRP 0             |B0
        clrf    PORTA           ; clear PORT A latches            |B0
        clrf    PORTB           ; clear PORT B latches            |B0
        bsf     STATUS,RP0      ; bank 1                          |B1
        clrf    ANSEL           ; setup PORT A digital I/O        |B1
        clrf    TRISA           ; setup PORT A all outputs        |B1
        movlw   b'00100100'     ;                                 |B1
        movwf   TRISB           ; set RB5/TX & RB2/RX as inputs   |B1

        movlw   b'01110000'     ;                                 |B1
        movwf   OSCCON          ; select 8-MHz INTOSC clock       |B1
Stable  btfss   OSCCON,IOFS     ; Int Osc Freq Stable bit set?    |B1
        goto    Stable          ; no, branch and wait             |B1

        movlw   d'25'           ; 25 (8-MHz) or 64 (20-MHz)       |B1
        movwf   SPBRG           ; 19200 baud                      |B1
        movlw   b'00100100'     ; TXEN=1, SYNC=0, BRGH=1, TX9=0   |B1
        movwf   TXSTA           ; Async, 8, 1, none               |B1
        bcf     STATUS,RP0      ; select Bank 0                   |B0
        movlw   b'10010000'     ; SPEN=1, TX9=0, CREN=1, ADDEN=0  |B0
        movwf   RCSTA           ; enable serial port              |B0
        movf    RCREG,W         ; flush Rx Buffer                 |B0
        movf    RCREG,W         ;                                 |B0

        PutStr  "\x1b[2J"       ; home cursor, clear screen       |B0
        PutStr  "K8LH 16F88 UART Test v1.0\r\n\n\n"

Loop    call    Get232          ;                                 |B0
        call    Put232          ;                                 |B0
        goto    Loop            ;                                 |B0

;******************************************************************
;
Get232  btfss   PIR1,RCIF       ; character available?            |B0
        goto    Get232          ; no, branch, else                |B0
        movf    RCREG,W         ; get character                   |B0
        return                  ;                                 |B0
;
Put232  btfss   PIR1,TXIF       ; transmit buffer empty?          |B0
        goto    Put232          ; no, branch, else                |B0
        movwf   TXREG           ; send character                  |B0
        return                  ;                                 |B0
;
PutString
        call    GetTable        ; get a table character           |B0
        andlw   b'11111111'     ;                                 |B0
        skpnz                   ; 00 byte, last character?        |B0
        return                  ; yes, return                     |B0
        pagesel Put232          ;                                 |B0
        call    Put232          ; else,output character           |B0
        incf    PtrL,F          ; increment pointer               |B0
        skpnz                   ;                                 |B0
        incf    PtrH,F          ;                                 |B0
        pagesel PutString       ;                                 |B0
        goto    PutString       ;                                 |B0
GetTable
        movf    PtrH,W          ;                                 |B0
        movwf   PCLATH          ;                                 |B0
        movf    PtrL,W          ;                                 |B0
        movwf   PCL             ;                                 |B0

        end
 
Last edited:
Most of us old timers use the TXIF flag which is located in bank 0 on 16F devices (except for the new "enhanced" 16F devices);

Yes but TXIF is set anytime you set TXEN whereas TRMT is clear up until the transmit is complete. Thus you can load TXREG, then have your code go off and do other things, then poll the TRMT bit prior to transmitting the next byte. This way your code isn't tied to the UART during the transmit period.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top