# 16f886 UART woes :-(

#### Torbek

Joined Apr 19, 2019
19
ok this is simple, I will have a 'packets' of 16 bytes sent over uart @9600 baud, then a gap of about 4mS will indicate the start of a new packet.

I am trying to detect said gap between packets with a small loop involving TMR0, a file that decrements, and PIR1,RCIF. For some reason, I am struggling, not to detect the gap, but actually for the pic to acknowledge within the loop, any reception of serial data at all.

So you might ask if I have set UART Rx up properly. Well, I think so. To test this, I have put the following line above my bit of looped code to ensure I have set the port up correctly:

Code:
    btfss    PIR1,RCIF    ;Any data recieved?
goto    $-1 movf RCREG,w ;TEST call ERCHK ;tests for overrun and framing So yes we do get past the point above, and if it demonstrates anything at all, it should be true that the routine below loops back to 'WaitDTA' to reset the timing loop. Extra info, baud is correct, I am not getting frame or other error, and I moved to 20Mhz external xtal to eliminate errors but at 9600 really? I hope this makes some sort of sense, the code is below. Code:  btfss PIR1,RCIF ;Any data recieved? goto$-1
movf    RCREG,w        ;TEST
call    ERCHK

call    DLY500mS

WaitDTA:
movf    RCREG,w
call    ERCHK
banksel    PORTA
bcf        PORTC,RED
bcf        PORTC,GRN
clrf    flgs        ;???
movlw    d'146'        ;Confirmed 15mS (1/8x10^6)/4/256/2/60
movwf    TMR0CNT        ;Our tmr1 count variable
clrf    TMR0
bcf    INTCON,T0IF
movf    RCREG,w
call    ERCHK

btfsc    flgs,7
goto    Uerror
btfsc    flgs,6
goto    Uerror

bsf        PORTC,RED
bcf        PORTC,GRN

TMRLP:
btfss    INTCON,T0IF        ;every 250uS we will test TMR1, and hence check for comms
goto    $-1 bcf INTCON,T0IF decfsz TMR0CNT,f goto TMRLP btfsc PIR1,RCIF ;Any data recieved? goto WaitDTA ;Back round to next 250uS poll bsf PORTC,RED bsf PORTC,GRN ;<<< ROUTINE GETS HERE despite it breaking the 15mS timer!!! And below you can see the data out (for this test I have removed the gaps so that there is no break in data) along with the 15mS gap highlighted, where just the red LED (D2) is illuminated, then we get to the point where the red & green LED's are illuminated (D2&3). D0 is the serial data on RC7/RX/DT pin. You can see there are at least 3 instances of serial data that should result in the code going back to 'WaitDTA'..? This is driving me mad and I suspect it will be something stupid! #### AlbertHall Joined Jun 4, 2014 9,622 Please attach the whole code so I can test in the simulator. #### JohnInTX Joined Jun 26, 2012 4,007 btfss PIR1,RCIF ;Any data recieved? goto$-1
movf RCREG,w ;TEST
call ERCHK

call DLY500mS

You delay 500ms after the error check. On the next character(s), during the delay, you will set OERR because you did not process additional characters coming in. After that, RCIF will never be set.

There are probably more issues but that one jumped out.

If you are going to look for a 4ms gap, I would recommend using an interrupt-driven buffer that receives characters without having to poll for them nor run the risk of missing something with your other waits on timers. Just receive the characters, stuff them into a FIFO buffer and reset a 4ms timer. On interrupt, if RCIF, you have another character to buffer. If timeout, there's your gap - signal the main routine to process the buffer full of characters.

Good luck!

#### MrChips

Joined Oct 2, 2009
20,859
It is better to send a unique character to indicate the start of the data frame rather than trying to detect a gap in transmission.

#### Torbek

Joined Apr 19, 2019
19
btfss PIR1,RCIF ;Any data recieved?
goto \$-1
movf RCREG,w ;TEST
call ERCHK

call DLY500mS

You delay 500ms after the error check. On the next character(s), during the delay, you will set OERR because you did not process additional characters coming in. After that, RCIF will never be set.

There are probably more issues but that one jumped out.

If you are going to look for a 4ms gap, I would recommend using an interrupt-driven buffer that receives characters without having to poll for them nor run the risk of missing something with your other waits on timers. Just receive the characters, stuff them into a FIFO buffer and reset a 4ms timer. On interrupt, if RCIF, you have another character to buffer. If timeout, there's your gap - signal the main routine to process the buffer full of characters.

Good luck!
Ah yeah did not see that. Something that MPLAB does not simulate... Now I wonder why I did not get an O/run error... I will have a play tomorrow and see what happens but I suspect you are correct.

#### Torbek

Joined Apr 19, 2019
19
It is better to send a unique character to indicate the start of the data frame rather than trying to detect a gap in transmission.
Yes I have previously taken this approach however I want to relay LED's from a panel elsewhere in real-time with minimum delay. I would rather not have to compress each value into bytes. Instead, just sending 8 bits of info then inverting a second byte as a very crude check.

#### Beau Schwabe

Joined Nov 7, 2019
48
How are you sending the data? ... Could it be a Receive overrun error?

pg 159 of the datasheet:

The receive FIFO buffer can hold two characters. Anoverrun error will be generated If a third character, in itsentirety, is received before the FIFO is accessed. Whenthis happens the OERR bit of the RCSTA register is set.The characters already in the FIFO buffer can be readbut no additional characters will be received until theerror is cleared. The error must be cleared by eitherclearing the CREN bit of the RCSTA register or byresetting the EUSART by clearing the SPEN bit of theRCSTA register. "

#### Torbek

Joined Apr 19, 2019
19
JohnInTX has suggested the same Beau, so I will check this tomorrow. Interupts may be the best way to go.

#### jpanhalt

Joined Jan 18, 2008
9,043
Have you looked into using a script to simulate USART? It will certainly simulate USART in hardware.

It's been awhile (more than 2 years) but MPLab SIM shows for the 16F886 this:

Last edited: