Jennifer Loiacono
President
Automaton Engineering, Inc.
P.O. Box 10282
Brooksville, FL 34603When receiving serial data on the PIC18C442, the value
is not reflected correctly in the RCREG reception register. However, the
signal on the receiving PIC is perfect in terms of timing and accuracy.
Despite accurate signal levels, debugging RCREG immediately after data is
received reveals that the byte seems to flip back and forth.
e.g., a byte equal to 4 (dec) will oscillate between 4 and 32. A byte equal
to 1 will oscillate between 1 and 128, etc.
Again, this value is being read immediately after reception (triggered by RX
interrupt), so it is highly unlikely that program code could be altering the
register after reception.
Has anyone seen a problem like this before, or perhaps have any ideas as to
its cause? I have been stumped on this for a while, so ANY help would be
greatly appreciated!
Jennifer Loiacono
Automaton Engineering, Inc.
P.O. Box 10282
Brooksville, FL 34603
> Jennifer Loiacono
> President
> Automaton Engineering, Inc.
> P.O. Box 10282
> Brooksville, FL 34603When receiving serial data on the PIC18C442, the
value
> is not reflected correctly in the RCREG reception register. However, the
> signal on the receiving PIC is perfect in terms of timing and accuracy.
> Despite accurate signal levels, debugging RCREG immediately after data is
> received reveals that the byte seems to flip back and forth.
>
> e.g., a byte equal to 4 (dec) will oscillate between 4 and 32. A byte
equal
> to 1 will oscillate between 1 and 128, etc.
>
> Again, this value is being read immediately after reception (triggered by
RX
> interrupt), so it is highly unlikely that program code could be altering
the
> register after reception.
>
> Has anyone seen a problem like this before, or perhaps have any ideas as
to
> its cause? I have been stumped on this for a while, so ANY help would be
> greatly appreciated!
It usually happens when the serial data is not in the right form before it
hits the PIC pin (wrong voltage levels, skewed pulses, parity bit
mismatch...): where is it coming from? Straight from a PC port? From an
optocoupler? from a rf receiver? Need more info.
The transmission is from PIC to PIC - one USART to another. The sending PIC
is a 16F627. The scope readings show perfect 5V signals at 9600 baud.
There is no parity bit, only 8 data bits, plus start and stop bit.
How do you 'print' out the data received? By outputing them to LEDs?
Transmitting the received data again to a PC? I am trying to see if
it's possibly the code.
Rudy
> The transmission is from PIC to PIC - one USART to another. The
sending PIC {Quote hidden}
> is a 16F627. The scope readings show perfect 5V signals at 9600 baud.
> There is no parity bit, only 8 data bits, plus start and stop bit.
>
> Jen
>
> > > Despite accurate signal levels, debugging RCREG immediately
> > after data is
> > > received reveals that the byte seems to flip back and forth.
> > >
> > > e.g., a byte equal to 4 (dec) will oscillate between 4 and
> > 32. A byte
> > equal
> > > to 1 will oscillate between 1 and 128, etc.
> > >
> > > Again, this value is being read immediately after reception
> > (triggered by
> > RX
> > > interrupt), so it is highly unlikely that program code
> > could be altering
> > the
> > > register after reception.
> > >
> > > Has anyone seen a problem like this before, or perhaps have
> > any ideas as
> > to
> > > its cause? I have been stumped on this for a while, so ANY
> > help would be
> > > greatly appreciated!
> >
The value is transmitted (also via USART - possibly a clue?) to a serial
LCD. The code is listed below. All references to AARGBx, BARGBx, and
FXDxxxxxx registers/routines are part of the standard math libraries
provided by Microchip. I have used them extensively, and they never SEEM to
cause any other problems.
;generic display routine
SERDISP BTFSS TXSTA,TRMT ;if transmit shift register full
GOTO SERDISP ;loop until ready
BSF TXSTA,TXEN ;enable transmission
MOVFF CHARIN,TXREG ;move new character into buffer
RETURN
;divide by powers of 10 to get one decimal character at a time
MOVFF RCREG,AARGB0 ;move limit into dividend register
MOVLW 0x64 ;100d
MOVWF BARGB0 ;move to divisor register
CALL FXD0808U ;unsigned 8x8 division
MOVLW 0x16 ;load high byte of PC for table lookup vector
MOVWF PCLATH ;program counter latch high
MOVF AARGB0,W ;move quotient to wreg for code lookup
CALL ASC_TBL ;lookup hex code for ascii character
MOVWF CHARIN ;move value to character holding register
CALL SERDISP ;display character
MOVFF REMB0,AARGB0 ;move remainder to use as next divisor
MOVLW 0x0A ;10d
MOVWF BARGB0 ;move to divisor register
CALL FXD0808U ;unsigned 8x8 division
MOVLW 0x16 ;load high byte of PC for table lookup vector
MOVWF PCLATH ;program counter latch high
MOVF AARGB0,W ;move quotient to wreg for code lookup
CALL ASC_TBL ;lookup hex code for ascii character
MOVWF CHARIN ;move value to character holding register
CALL SERDISP ;display character
MOVLW 0x16 ;load high byte of PC for table lookup vector
MOVWF PCLATH ;program counter latch high
MOVF REMB0,W ;move remainder to wreg for code lookup
CALL ASC_TBL ;lookup hex code for ascii character
MOVWF CHARIN ;move value to character holding register
CALL SERDISP ;display character
MOVLW 0x20 ;space
MOVWF CHARIN
CALL SERDISP
RETURN
----- In Response To -----
Jen,
How do you 'print' out the data received? By outputing them to LEDs?
Transmitting the received data again to a PC? I am trying to see if
it's possibly the code.
Rudy
> The transmission is from PIC to PIC - one USART to another. The
sending PIC {Quote hidden}
> is a 16F627. The scope readings show perfect 5V signals at 9600 baud.
> There is no parity bit, only 8 data bits, plus start and stop bit.
>
> Jen
>
> > > Despite accurate signal levels, debugging RCREG immediately
> > after data is
> > > received reveals that the byte seems to flip back and forth.
> > >
> > > e.g., a byte equal to 4 (dec) will oscillate between 4 and
> > 32. A byte
> > equal
> > > to 1 will oscillate between 1 and 128, etc.
> > >
> > > Again, this value is being read immediately after reception
> > (triggered by
> > RX
> > > interrupt), so it is highly unlikely that program code
> > could be altering
> > the
> > > register after reception.
> > >
> > > Has anyone seen a problem like this before, or perhaps have
> > any ideas as
> > to
> > > its cause? I have been stumped on this for a while, so ANY
> > help would be
> > > greatly appreciated!
> >
On 23-Jan-02 Jennifer Loiacono wrote:
> Jennifer Loiacono
> President
> Automaton Engineering, Inc.
> P.O. Box 10282
> Brooksville, FL 34603When receiving serial data on the PIC18C442, the value
> is not reflected correctly in the RCREG reception register. However, the
> signal on the receiving PIC is perfect in terms of timing and accuracy.
> Despite accurate signal levels, debugging RCREG immediately after data is
> received reveals that the byte seems to flip back and forth.
>
> e.g., a byte equal to 4 (dec) will oscillate between 4 and 32. A byte equal
> to 1 will oscillate between 1 and 128, etc.
I'm not quite clear on what you mean by " oscillate between 1 and 128".
If I've missunderstood then please ignore me, but it sounds to me that you
reading the RCREG multiple times for each recieved character ?
I'm pretty sure that isn't allowed by the PIC. You should read RCREG
ONCE and ONLY ONCE for each recieved character.
RCREG should be read ONCE each time the RCIF bit in PIR1 is set. Reading RCREG
will reset this bit automagically ready for the next character.
I tried debugging RCREG directly as a last resort. Previously, I had been
moving the value out to another register first; thus, one read per
character. However, the results are the same either way.
I would like to suggest you to narrow down the range to locate the bug. You
may bypass all communication-unrelated codes and focus on the serial port
operation. Just to verify the TX/RX is correct. One thing can try is keeping
sending an identical printable char to the receiver and let the receiver
display it as directly and quickly as possible. I still suspect the
receiving port is unintentionally accessed if the waveform to the receive
pin is correct.
Multiple reads of RCREG wouldn't change its content.
Look at the waveform of an '4' togather with the start/stop bits. If two
'4's are sent back-to-back and the receiver not interpret the start bit
properly, it could receive a '32'. Similar thing happens to '1' and '128'
depending on the interval between characters. So it is possible the
receiving was interrupted and restarted during a byte reception.
On 24-Jan-02 Jennifer Loiacono wrote:
> I tried debugging RCREG directly as a last resort. Previously, I had been
> moving the value out to another register first; thus, one read per
> character. However, the results are the same either way.
Ok. My understanding and conclusions were wrong !!
Maybe you have very fast ringing on the edges of the signal. You do not
say what board/drivers/etc you are using. Ringing is very likely with fast
signals on wirewrap and protoboards. However I have never seen a problem
like yours.
On Thu, 24 Jan 2002 10:32:05 -0500, Jennifer Loiacono wrote:
>The value is transmitted (also via USART - possibly a clue?) to a serial
>LCD. The code is listed below. All references to AARGBx, BARGBx, and
>FXDxxxxxx registers/routines are part of the standard math libraries
>provided by Microchip. I have used them extensively, and they never SEEM to
>cause any other problems.
>
>
>;generic display routine
>
>SERDISP BTFSS TXSTA,TRMT ;if transmit shift register full
> GOTO SERDISP ;loop until ready
> BSF TXSTA,TXEN ;enable transmission
> MOVFF CHARIN,TXREG ;move new character into buffer
> RETURN
>
Sorry, but I've lost track of which processor this code is running on.
If it's the 16F627 that I've seen mentioned previously, note that
TXSTA and TXREG are in two different register banks, banks 1 and 0
respectively.
Please ignore this post if they're in the same bank on the processor
you're using.
Instead of using the serial LCD, I would recommend trying to see if your
PIC18 got the correct serial data first (i.e. try limitting the # of data
transmission to find out where the error occurs). You can try it by simply
outputting the byte received in RCREG into PORTB for example. Hook up 8
LEDs there, and see if you get the correct data all the time, or it
alternates like you said before. If it's correct, then we can rule out the
possibility of the error of serial reception. If it's not, then, we can go
on from there.
All I needed was a delay between successive transmissions. Back to back TX
would occasionally cause the receiving USART to misinterpret start/stop bits
as data bits should it miss anything in between.
The core process on the receiving PIC18 was a high priority interrupt that
MUST take precedence over support functions. On the other hand, it was
unnecessary to transmit this data constantly, as it is seldom changed at
runtime.
Hi,
I'm going a bit of topic here but I'll remain within PIC domain trust me.
I don't have an answer for your exact question but instead some minor
questions.
From your code posting:
<snip>
;divide by powers of 10 to get one decimal character at a time
MOVFF RCREG,AARGB0 ;move limit into dividend register
MOVLW 0x64 ;100d
MOVWF BARGB0 ;move to divisor register
CALL FXD0808U ;unsigned 8x8 division
MOVLW 0x16 ;load high byte of PC for table
lookup vector
MOVWF PCLATH ;program counter latch high
MOVF AARGB0,W ;move quotient to wreg for code
lookup
CALL ASC_TBL ;lookup hex code for ascii character
MOVWF CHARIN ;move value to character holding
register
CALL SERDISP ;display character
MOVFF REMB0,AARGB0 ;move remainder to use as next
divisor
MOVLW 0x0A ;10d
MOVWF BARGB0 ;move to divisor register
CALL FXD0808U ;unsigned 8x8 division
MOVLW 0x16 ;load high byte of PC for table
lookup vector
MOVWF PCLATH ;program counter latch high
MOVF AARGB0,W ;move quotient to wreg for code
lookup
CALL ASC_TBL ;lookup hex code for ascii character
MOVWF CHARIN ;move value to character holding
register
CALL SERDISP ;display character
MOVLW 0x16 ;load high byte of PC for table
lookup vector
MOVWF PCLATH ;program counter latch high
MOVF REMB0,W ;move remainder to wreg for code
lookup
CALL ASC_TBL ;lookup hex code for ascii character
MOVWF CHARIN ;move value to character holding
register
CALL SERDISP ;display character
<snip>
All this for translating an recevied byte to ascii represenatation ??
I'm very curious how many program cycles there are in this snippet,
can you measure it ? ( either simulate or place breaks at entry/exit
and check number of cycles in between ).
Anyway I would propose something like this instead:
;-------------------------------------------
;Fast binary to decimal conversion (0..255)
;
;Input: in W
;Temp: AARGB0
;Output one digit at a time, seq. Hund:Tens:Ones (real ASCII)
; pseudo routine SERDISP used for byte output
;
;
;
;Size: ? instructions
;Execution time (with return): ?
;
;25-January-2001 by Tony Kübek ****untested****
;
; Stripped (limited to 8-bit input, no digit ram) version of :
; www.piclist.com/techref/microchip/math/radix/b2a-16b3a2-ng.htm
; as per:
;8-July-2000 by Nikolai Golovchenko
;23-Aug-2001
;Based on 8bit BIN2BCD of Scott Dattalo
;-------------------------------------------
bin2dec255fast
movwf AARGB0 ; save number
swapf AARGB0, w ;Add the upper and lower nibbles
addwf AARGB0, w ;to get the one's digit
andlw 0x0F
skpndc ;Go through a binary to bcd
addlw 0x16 ;conversion for just the one's
skpndc ;digit
addlw 0x06
addlw 0x06
skpdc
addlw -0x06
btfsc AARGB0, 4 ;bit 4 is a special case
addlw 0x16 - 1 + 0x6
skpdc
addlw -0x06
;now adjust the ten's digit
btfsc AARGB0, 5 ;2^5 = 32, so add 3 to the ten's
addlw 0x30 ;digit if bit 5 is set
btfsc AARGB0, 6 ;2^6 = 64, so add 6
addlw 0x60 ;if bit 6 is set
btfsc AARGB0, 7 ;2^7 = 128, so add 2 (the ten's
addlw 0x20 ;digit) if bit 7 is set
addlw 0x60 ;convert the ten's digit to bcd
;if there's a carry, then the input
skpc ;was greater than 99.
goto between_0_199
between_100_255
; number greater than 100
addlw -0x60
; rotate top bit of input into carry to see if number is above 200
rlcf AARGB0,F
movwf AARGB0 ; save tens and ones ( packed bcd )
; if carry set send hundred digit '2' else '1'
movlw 0x31
skpnc
movlw 0x32
; and display the hundred digit
CALL SERDISP ;display character in w
goto send_tens_ones
between_0_199
; number less than 200, hundred can only be '0' or '1'
rlcf AARGB0,F ; save top bit into carry
movwf AARGB0 ; save tens and ones ( packed bcd )
movlw 0x30
skpnc
movlw 0x31
; and display the hundred digit
CALL SERDISP ;display character in w
send_tens_ones
; prepare tens digit
swapf AARGB0,w
andlw 0x0f ; strip top nibble
addlw BYTE_OFFSET ; make ascii
; and display the tens digit
CALL SERDISP ;display character in w
; prepare ones digit
movf AARGB0,w
andlw 0x0f
addlw BYTE_OFFSET ; make ascii
; and display the ones digit
CALL SERDISP ;display character in w
; done
return
Perhaps some minor modifications are needed.
Optimisations can be plentiful, in particular if more ram are available.