Really weird UART problem

Thread Starter

Los Frijoles

Joined May 16, 2009
10
I am re-programming a digital radio transmitter that I built about a year and a half ago to include a working "terminal" interface. The board is based around a PIC18F4550 running at 48Mhz using the PLL off of a 16Mhz crystal and at the time I did not know how easy it was to do USB with these, so there is no USB interface on the board (that would have saved me so much time now).

Anyway, I am having trouble with the USART on the chip receiving characters properly. The computer can read characters the chip sends just fine, but the chip cannot read characters the computer sends to it. Right now the chip's program just echoes back whatever it receives. The only problem is that it throws a frame error every time it receives a character and the character it sends back is definately not what I sent it, but what it sends back stays consistent (i.e. when I type 'a' into the terminal I always get back an 'O' no matter the baud rate). I recently figured out the pattern in these errors (as in figured out just a few minutes ago), but it is really complex and I am not even sure it is actually a pattern and I definately don't know how to correct it other than using a lookup table which could take a while to generate.

On the chip end, the serial hardware on the PCB consists of a MAX232 hooked up to an old serial port I grabbed off an ancient motherboard with the other end hooked up to TX and RX on the chip. The computer hardware consists of a USB->Serial cable (one of those cheap ones with the translucent blue ends and the silver cable between, called "Huge Pine USB to Serial ports" in the device manager) and Realterm running on the computer.

Has anyone here ever seen this before or have any ideas on how to fix this without resorting to a hack like a lookup table?
 

DonQ

Joined May 6, 2009
321
Most of this sounds like a baud-rate error. Depending on the PIC clock, dividers, and serial port setting, you might have something close, but not close enough, to the right baud rate. Some serial receivers are better than others at adjusting to baud rate deviations. There are also two modes that you can set the PIC serial to use. The one that uses the divide by 16 mode is generally better the clock/baud you are using allows this.

I would guess that the receiver in the USB thingy is good at adjusting for bad baud-rate, but the PIC is not so good.

Do you know that the PC is actually getting the right characters? i.e. does it ever print a whole word from the PIC? Or is it possible that the problem is going both ways? If this is the case, your baud rate might be set really wrong.
 

Thread Starter

Los Frijoles

Joined May 16, 2009
10
For baud rate calculation I used the Baud=Fosc/(4*(SPBRG+1)) equation to calcuate the value for the baud rate generator. It is possible that I am using the wrong numbers/wrong equation altogether.

Here is what I assumed (tell me if I am wrong):
Since I am running the PLL, the clock frequency is 96Mhz which is divided by two to get the system clock, giving 48,000,000 for Fosc. I set the baud rate generator to use a 16-bit baud rate and I set the baud rate generator into "high" mode, so using the table on page 243 of the 18F4550 datasheet I got the above equation to use. I used a baud rate generator value of 9999 which my calculator tells me should give me exactly 1200 baud.

On the computer end, I have realterm set up to use 1200 baud with 8 data bits and 1 stop bit. The serial cable has fifo enabled.
 

Thread Starter

Los Frijoles

Joined May 16, 2009
10
Hmm...that is a good point and it would explain the problems. Then what the heck speed am I running at??

I know I am running with the PLL rather than the crystal because of a little test I ran. I have a bliky light that switches state when a 16-bit int overflows. I turned off the PLL (changed CONFIG1H to 0x0C) so it was running right off my 16Mhz crystal and it flashed significantly slower than when I had CONFIG1H set to 0x0E (HS, PLL enabled). I can't get out my oscilloscope to monitor the exact frequency (it is buried beneath boxes), but that proved to me that something was happening with the speed increasing. Also, the datasheet for the 18F4550 has frequency/voltage graphs going up to 48Mhz (12MIPS). I would think that since USB requires a 48Mhz signal to run that the chip would be able to handle higher clock speeds.

EDIT: Just tried those values. No luck.
 
Last edited:

DonQ

Joined May 6, 2009
321
I just looked at the datasheet briefly, but let me say what it seems to mean to me.

The 96MHz PLL is expecting a fixed 4MHz input (2.2.4 Paragraph 2), meaning that if you are using a 16MHz crystal, you should be dividing by 4 in the PLLDIV. Is that what you are doing?

Then the CPU clock can come from a variety of places, either set with the CPUDIV, either from the crystal freq, or the PLL, or a secondary crystal or an internal clock... Lots of options. Lots more settings than just the ones shown in Albertos post. If one of them is wrong, there is no telling what frequency clock your USART is actually working with. Then there are lots of USART settings that also need to be right. But it definately sounds like it is running at the wrong speed.

At this point, things like "it flashed significantly slower" isn't going to be good enough. I would suggest dividing the clock down far enough, with something that you are sure you know the division ratio, so that you can time it and see exactly what freq you actually have available. This is so much easier if you can put a scope or freq meter on an output.

Once you are relatively sure of the clock, then work with the USART. When I have problems, I always just make a test loop to put out a "U" followed by a delay longer than any baudrate I might accidently have by mistake. Any delay you use might also be running off a clock very different than what you think so start with a really long delay. You can shorten it later. Sending a "U", with makes the USART output 0101010101. This should put a series of U-s on the screen but baud errors will certainly give you something else. Also, this pattern is easy to see and measure on a scope.
 

Thread Starter

Los Frijoles

Joined May 16, 2009
10
Well I just got out my oscilloscope to debug this (its a LeCroy 9400A, so its not light) and taking a look at what was actually going out was quite a revelation to me. Here is basically what I saw:

If I saw the following hump pattern on the scope: long, short, short, short
I would see the following from the microcontroller: short, short, short, long
Now it is obvious why there was a frame error: the microcontroller was expecting something different at the end.

EDIT: Ok, now I really don't know what to think. Here is a 'u' (comp bottom, pic top):

Maybe the PIC is flipping everything upside down?
END EDIT

This explains why the U's were showing up properly, but it does not quite explain why text was received properly. Has anyone seen this before? Is it my USB cable?
 
Last edited:

hgmjr

Joined Jan 28, 2005
9,027
Are you using a TTL to RS-232 converter on the output of the PIC so that it produces true RS-232 signal levels going to the PC?

hgmjr
 

hgmjr

Joined Jan 28, 2005
9,027
Does the PIC allow you to configure its UART to invert the data that it outputs through the serial port?

hgmjr
 

hgmjr

Joined Jan 28, 2005
9,027
If you are using a function call from a library of routines to handle your serial transmissions, you may need to make sure that it is not perfroming the inversion of the data inside the function.

hgmjr
 

DonQ

Joined May 6, 2009
321
Can't quite follow your "humps", but do you realize that the MAX-232 inverts the signal between the PIC and the serial line?

This might explain "short, short, long, long" or whatever.

The start bit on the PIC will be a high pulse, on the serial line it will switch from positive voltage (generally about 8-9 volts) to a negative voltage.

What you need to look for is the length of time of the pulses.

------------
Oops, you added a picture while I was writing.

Send a capitol "U" instead of a "u". 0101010101 instead of 0101000101, including start and stop bits.

Don't worry about manually inverting. The PIC and the MAX-232 do what you need to make the signal correct. Just realize that high is true on the PIC, low is true on the serial wire, and the low-order bits are transmitted first (between a start and at least one stop bit).
 

Thread Starter

Los Frijoles

Joined May 16, 2009
10
Yes. I actually tried having it invert the data it received instead. This had no effect and I am not sure why (it should have done something). When I inverted the transmitted data, the problem worsened since the computer wouldn't even display "HELLO!" anymore.

The problem seems to be in the PIC reading the byte correctly rather than the PIC sending it correctly as stated above. However, it is obviously not a baud problem, but appears to be a protocol problem. Should I just give up and write a software UART? It would be slower, but would avoid trying to fix a PCB.
 

hgmjr

Joined Jan 28, 2005
9,027
If you are using a library function call then you should be able to tell the function whether it is to invert the data before transmission or not.

hgmjr
 

Thread Starter

Los Frijoles

Joined May 16, 2009
10
hjmjr: I never thought of that. It is possible that the library is actually inverting everything before sending it. However, this library is only supposed to interface to the EUSART peripheral on the PIC which also allows for synchronous transmissions, so I am not sure why the library would invert before sending. But, when I send a string such as "HELLO???", it is displayed properly on the computer end, pointing again to the fact that the PIC is reading things incorrectly.

The library is the built in uart library for the MCC18 compiler. I have the commercial version, but it is a bit old since I have neglected to update it. They could have made a software error...should I just control the peripheral manually without the library? It is one of the simpler ones to use.

@DonQ: Each pulse in the capital U coming out of the PIC and the PC was exactly 800uS which translates to 1200 baud which is what I was expecting (SPBRG(H) = 9999 @ 48Mhz). I used the lowercase u for the picture because the uppercase U told me the baud was correct but didn't explain why my characters were garbled when they were echoed back. I noticed that if I shift over all the pulses coming out of the PIC over 800uS (one bit), they make a perfect inverse of what is coming into the PIC.

Oh, btw I can't measure the output coming right out of the PIC...only the output coming out and into the MAX232 from the serial port. This is because of my board design which doesn't happen to have a via on the RX and TX lines coming out of the PIC and the entire thing is surface mount. *facepalm*
 

DonQ

Joined May 6, 2009
321
If you are using a library function call then you should be able to tell the function whether it is to invert the data before transmission or not.
You know... I have never seen a "printf" or a "putch" or any other normal function for sending ASCII characters over a serial line, that had an option of inverting the characters. That is simply not the way RS232 works.

Any regular function for sending a char to the USART port will do exactly what you need to do without worrying about if it is inverted.

You can also just do an "outport" of the character directly to the USART, as long as you either check for the "Transmit Shift Register Empty" flag or just delay long enough that you can be sure it is empty. Even doing it this way, it will not need to be inverted in software. If you put, place, force, or in any other way, send a character to the USART, you do not need to invert it in any way.

If it seems to be the wrong polarity, you are not looking at it correctly.

I can't see your picture well enough to tell much, but these are obviously two entirely different characters. But the signals are so compressed, you can't read the baud rate.

Set the horizontal so that just a few bits of what is coming out of the PIC will show on the screen. Then measure the time per bit as precisely as you can. If the PC, for example is set at 9600 baud, but your PIC is actually running at 9934 baud, it won't work. So you have to see that it is set correctly by measuring it.
 

DonQ

Joined May 6, 2009
321
But, when I send a string such as "HELLO???", it is displayed properly on the computer end
This, and a couple of other things you said help alot. The bauds are set close enough, now you have to get the start/stop/data bits in the right place

If you are using library routines for synchronous transmissions, there may be lots of options that you don't need for asynchronous communications. For various non-RS232 communications you do things like leave off the start and stop bits, add extra bits to signify command/data, and things like that. Asynchronous is different than synchronous. Your PC is doing asynchronous, so should the PIC.

If you working with synchronous communications on the PIC end and asynchronous on the PC end... well, just don't do that.

Try bypassing any lib routines. Just poll the Receiver Register Full, or whatever the bit is that says a character is received. Fetch the value of the Receive buffer and put it straight back into the Transmit buffer. This should echo anything you send from the PC.
 

DonQ

Joined May 6, 2009
321
And now.... the rest of the story.

(Normally not needed when level converter, such as MAX232).
(Their grammar, not mine.)

On the chip end, the serial hardware on the PCB consists of a MAX232 hooked up to an old serial port...
And... the "mark" state in the 'scope traces in the first post show that the polarity on both serial lines is correct.



So still... Don't try to invert your signal.
 

hgmjr

Joined Jan 28, 2005
9,027
I agree with DonQ. You need to track down the point in your program that sets up the UART and change it so that it does not call for an inversion of the data.

hgmjr
 
Top