View previous topic :: View next topic |
Author |
Message |
JerryR
Joined: 07 Feb 2008 Posts: 164
|
PIC18F87J60 UART Receive Errors |
Posted: Wed Aug 30, 2023 8:46 am |
|
|
Hello Group:
I'm have a mature product that uses a PIC18F87J60 controller. All code was compiled using v5.078 PCWH. The controller uses an external 25 MHz crystal. I'm using all UARTS on this device and the suspect UART is number 3.
I am receiving eight bytes at 57600 baud from an external device. These eight bytes are confirmed correct using a logic analyser and o-scope. All eight bytes are processed into an array of proper length.
The first six bytes are received correctly, however, bytes 7 and 8 seem to be shifted one bit. Unfortunately bytes 7 and 8 are checksum, so need these bytes to be correct!
I suspect a baud rate mismatch, maybe?
Hint: other external devices seem to be able to send data successfully to the product.
Question: Is there a way to "tweak" the receive baud rate to see if that improves reception? I'm open to other suggestions,
Sorry, I can't post code here since proprietary.
Thanks group! |
|
![](templates/subSilver/images/spacer.gif) |
gaugeguy
Joined: 05 Apr 2011 Posts: 296
|
|
Posted: Wed Aug 30, 2023 9:28 am |
|
|
Because there are only discrete steps in setting the baud rate, when 57600 is selected it may actually end up being slightly higher or lower than the desired rate. You can set it to a different, slightly higher or slightly lower baud rate to get the PIC more closely matched to the sender baud. |
|
![](templates/subSilver/images/spacer.gif) |
JerryR
Joined: 07 Feb 2008 Posts: 164
|
|
Posted: Wed Aug 30, 2023 9:30 am |
|
|
Where are the tweak registers? |
|
![](templates/subSilver/images/spacer.gif) |
gaugeguy
Joined: 05 Apr 2011 Posts: 296
|
|
Posted: Wed Aug 30, 2023 9:37 am |
|
|
How does your code currently set the baud rate? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Wed Aug 30, 2023 10:26 am |
|
|
Post your clock setup & UART setups.
It is not likely to be a baud problem. If it was it is just as likely to affect
earlier bytes as the last two. So also show how the serial is being handled
(interrupt?).
What is the actual format of the data?. What is it coming from?. How
is it being connected (RS232 / RS485?).
Do you check the UART error bits in your receive? (Add ERRORS to the
RS232 setup, and read RS232_ERRORS after each byte is received. |
|
![](templates/subSilver/images/spacer.gif) |
JerryR
Joined: 07 Feb 2008 Posts: 164
|
|
Posted: Wed Aug 30, 2023 4:28 pm |
|
|
Hello guys and thanks for your quick replies. Sorry for tardy response, out fighting another fire.
As I mentioned, the product using this code is very mature and I was asked to add another board, connected through a short header, to serial port 3. I agree with Ttelmah that the same baud rate mismatch should affect the earlier bytes as well, but they are un-corrupted. But, all eight bytes are processed in the same manner.
Here's how the serial UART3 is set up:
#use rs232(stream=ETH,baud=57600,xmit=PIN_E7,rcv=PIN_E6,parity=N,bits=8,ERRORS)
Clock setup:
#use delay(clock=25000000)
Handling incoming bytes UART3 (ETH):
Code: |
if(kbhit(ETH))
{
ethByte = fgetc(ETH);
handleEdb((unsigned int8)ethByte);
}
void handleEdb(uint8_t data)
{
if(inCmdBuf >= USART_RX_BUF_SZ)
{
inCmdBuf = 0;
ciSTATE = READING_HEADER;
}
cmdBuf[inCmdBuf++] = data;
uint16_t ccsum = 0;
uint16_t i;
switch(ciState)
{
case READING_HEADER:
if(inCmdBuf == sizeof(cmdHdr_t))
{
// check the length. If the length > 0 then read the body
// otherwise process the message.
if(hdr->len == 0)
{
processCmd();
inCmdBuf = 0;
}
else
{
if(hdr->len > (USART_RX_BUF_SZ - sizeof(cmdHdr_t) - sizeof(uint16_t)))
{
// length is too long. bail
inCmdBuf = 0;
ciState = READING_HEADER;
}
else
{
body = (uint8_t*)(hdr+1);
ciState = READING_BODY;
}
}
}
break;
case READING_BODY:
if(inCmdBuf == (sizeof(cmdHdr_t) + hdr->len))
{
csum= &cmdBuf[inCmdBuf];
ciState = READING_CRC;
}
break;
case READING_CRC:
if(inCmdBuf == (sizeof(cmdHdr_t) + hdr->len + sizeof(uint16_t)))
{
i = hdr->len;
while(i--)
{
ccsum = Fletcher16(*(body++), ccsum);
}
if(ccsum == *csum)
{
body = (uint8_t*)(hdr+1);
processCmd();
}
ciState = READING_HEADER;
inCmdBuf = 0;
}
break;
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9168 Location: Greensville,Ontario
|
|
Posted: Thu Aug 31, 2023 5:26 am |
|
|
wow, I'm really curious about this 'pain'
hard to believe it's a timing issue, if the other UARTS are rock solid...
but 'shifted bits' does say ' timing'... BTDT on very long wires (15 miles...)
as for hardware, if you used a 14,745,600 xtal, the UART timing would be bang on ( 14,745,600 / 256 = 57,600 ). I'm assuming you can't go faster than 25MHz, so 29,xxx,xxx xtal can't be used.
I'm wondering if there's something else delaying the process ??
Maybe you cut a small test program, send known data to UART3 and see what happens ?
You've posted a 'good' head scratcher for sure !! |
|
![](templates/subSilver/images/spacer.gif) |
JerryR
Joined: 07 Feb 2008 Posts: 164
|
|
Posted: Thu Aug 31, 2023 6:08 am |
|
|
Hi Temtronic!
Yeah, it’s got me stuck right now. Like as it’s been said earlier, why it’s not affecting the earlier bytes is a mystery.
The “new” board that’s being developed uses an Atmel controller, and it’s possible that there’s a timing issue there that my logic analyser ignores. That would explain the other two uarts working well. AND I do know, from talking yesterday with an Engineer who worked with another add on board that he had to hand select the crystal for its Atmel processor. But this board’s transmit routine should be even more uniform, so, again, why only the last two bytes?
I’m going to hook my good scope up to the Atmel board and critically look at the 232 data coming from it. Might not be the receive after all.
Thanks for the added eyes! I’ll keep the group posted.
All the best |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9168 Location: Greensville,Ontario
|
|
Posted: Thu Aug 31, 2023 7:06 am |
|
|
hmmm...
he had to hand select the crystal for its Atmel processor.
as in EACH PCB, he had to do this
or
just 'do the math' to get the optimum xtal for the project
FWIW, in the early days of the 18F46K22, I could link both UARTS in 'series' to a PC and dump hours of data at 1 megabaud without losing a bit of data.
Perhaps use a 'terminal program' as a 'sniffer' instead of the logic analyzer ? I used an 'old' PC ,that had 2 REAL comports (RS-232,9 pins),Win98SE and RealTerm as my 'diagnostic' tool.....
I'll be real interested into WHAT is causing the problem !
Jay |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Thu Aug 31, 2023 7:53 am |
|
|
I really would suspect something is running out of time in this handling.
25MHz, is only 6.25MIPS. At 57600bps, a byte is 138uSec. So you have
just 868 instructions per byte. Now, assuming that lots of other things
may be happening before the code gets round to the kbhit test again,
I'd be suspicious that if you tested the error byte you may well find
that possibly an overrun error has occurred by the time you get back to
this.
Add a serial interrupt buffer for this. You can do this easily by letting the
compiler generate one for you:
#use rs232(stream=ETH,baud=57600,xmit=PIN_E7,rcv=PIN_E6,parity=N,bits=8,ERRORS, RECEIVE_BUFFER=16)
So long as the global interrupt is enabled for something, the compiler will
automatically add a software 16byte serial interrupt driven receive buffer
for you. Your code can otherwise stay the same.
See if this changes things. |
|
![](templates/subSilver/images/spacer.gif) |
JerryR
Joined: 07 Feb 2008 Posts: 164
|
|
Posted: Thu Aug 31, 2023 9:59 am |
|
|
Well guys- Critical measurements of the baud rate of the Atmel based board under development shows a bit width of 17.2uS, which corresponds to a baud rate of 58,139.
Interesting observation Ttelmah! I'll check to see if an overrun has occurred as well. I'll also add a buffer as you suggest. I'll also try shutting down other interrupts during reception to see if that improves things. There is a LOT of stuff going on in the processor!
The real problem is that my client doesn't want me to touch the Microchip code unless absolutely necessary. But I'll do what I have to do.
Yes, Temtronics, he had to custom pick a crystal (16 MHz originally, 18.432MHz final pick). I'm also thinking someone else had travelled this road before me. I might put this guy under a spot light and make him talk
More to come... THANKS for y'alls interest. |
|
![](templates/subSilver/images/spacer.gif) |
dyeatman
Joined: 06 Sep 2003 Posts: 1924 Location: Norman, OK
|
|
Posted: Thu Aug 31, 2023 12:07 pm |
|
|
One other thing, according to the datasheet the PLL can up the 25MHZ clock to 41.667MHZ
which would give more time with minimal s/w changes. Using a buffer
would give even more time. _________________ Google and Forum Search are some of your best tools!!!! |
|
![](templates/subSilver/images/spacer.gif) |
JerryR
Joined: 07 Feb 2008 Posts: 164
|
|
Posted: Thu Aug 31, 2023 12:58 pm |
|
|
Another good suggestion dyeatman thank you. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Fri Sep 01, 2023 6:06 am |
|
|
OK.
First thing to do is add BRGH1OK to your #USE RS232. The compiler normally
defaults to assuming this is not OK, and setting this will allow the baud rate
to be closer to a genuine 57600.
Then is the Atmel baud rate is 58139. Specify this as the rate to use on the
PIC. It'll actually probably select 58411, which I think is the closest the
PIC can get from your oscillator.
However understand that since bits are sent LSb first, it'd only be the
high bits that would change with a baud rate error. This is why I think
your problem is not actually this. |
|
![](templates/subSilver/images/spacer.gif) |
JerryR
Joined: 07 Feb 2008 Posts: 164
|
|
Posted: Fri Sep 01, 2023 9:26 am |
|
|
Ttelmah:
Yes, I'm starting to agree with you that timing is the real problem, not baud rate mismatch. Attempted the buffer, which made great sense, but compiler didn't like it because Pin E6 (RX) isn't a native UART receive pin .
I think there is a software derived buffer implemented on one of the two hardware UARTs.
I'm looking to confirm the timing issue, however, by looking for UART errors and making sure other interrupts are not flaking out the latter bytes. Might try a PLL to speed things up to see what effect that might have.
More later... |
|
![](templates/subSilver/images/spacer.gif) |
|