1) What happens at the oscilloscope when it corrupts?
2) Is the corruption the same at different baud rates?
3) Is the corruption the same for different characters? Is there a pattern to it?
4) Delay the entire transmission, not between characters. Is the corruption still the same?
5) Transmit a string that is two characters long, but insert a delay equal to the transmission time of a third character between 1 and 2. Does it corrupt?
6) Try it without printf().
7) When you copy the corrupted strings into the forum, do them in hex or binary. I don't trust the forum software to keep the exact characters faithfully, even the weird ones, and it would be nice to be able to look at the actual binary values being received.
8 ) Try a different PIC.
0 01010011 0 0 01010010 0 1 01010111 1
Looks like something is getting messed up along the way.
Either you copied that wrong or the start and stop bits are messed up. Should be 0/1 0/1 0/1, not 0/0 0/0 1/1. If that really is what you are getting, the problem is not in software because that chip has no options related to start and stop bits. It should always transmit them properly.
Just for a sanity check on my math here:
9600 symbols/second * 8 bits/symbol = 76800 bits/second --> 13E-6 seconds/bit.
Typically 9600 baud:
9600 bits per second, 1 start bit + 8 data bits + 1 stop bit = 10 bits per character = 960 characters per second.
I said this before, and I don't know if you looked at it (its still just a shot in the dark)
The standard printf() does not have to output its contents immediately, ie it doesn't have to go to you putch() function every time you call it because it has a buffer.
You set the buffer size to zero with setbuf(stdout, 0); once this is done, every call to printf() will call your putch() function.
As for the baud rate, seeing you have oscilloscope can you output a clock on a pin somewhere and measure it, or a multiple of it (eg via a clocked hardware timer). I have seen error rates increase to a point where the data becomes corrupted but not to the point where it happens in 3 characters, that's why I'm thinking it may be stdout buffer corruption or a dodgy oscilator
Good point about the oscillator. I think the OP is using the 32MHz internal oscillator. Does that PIC have an OSCTUNE register that needs setting?
Typically 9600 baud:
9600 bits per second, 1 start bit + 8 data bits + 1 stop bit = 10 bits per character = 960 characters per second.
I figured something was wrong there...
I said this before, and I don't know if you looked at it (its still just a shot in the dark)
The standard printf() does not have to output its contents immediately, ie it doesn't have to go to you putch() function every time you call it because it has a buffer.
You set the buffer size to zero with setbuf(stdout, 0); once this is done, every call to printf() will call your putch() function.
As for the baud rate, seeing you have oscilloscope can you output a clock on a pin somewhere and measure it, or a multiple of it (eg via a clocked hardware timer). I have seen error rates increase to a point where the data becomes corrupted but not to the point where it happens in 3 characters, that's why I'm thinking it may be stdout buffer corruption or a dodgy oscilator
The way I wrote putch will block it:
void putch(char txchar)
{
while(!TXIF);
TXREG=txchar;
}
It can't load anything else into the transmitter until what is there has been sent. Also, stdout isn't a thing on this micro. I don't know what to direct that command at.
EDIT:
I have OSCTUNE set to use the default setting. I verified it with the scope when I first got the device running.
It can't load anything else into the transmitter until what is there has been sent.
Oh yes it can

TXREG holds the next character to be transferred to the Transmit Shift Register (TSR) and TXIF is set whenever TXREG is empty. The TSR contains the character that is currently being transmitted.
So, the character in TSR is transmitting, the TXREG is empty and TXIF is set. You put a character in TXREG and it waits there for TSR to empty at which point TSR is loaded with the new character, TXREG becomes empty, TXIF is set again and you load TXREG with another character while the previous character is transmitting. The data flow is continuous and is proceeding almost as quickly as the hardware can allow.
In short. TXIF does not tell you that the transmission has finished, only that TXREG is empty.
To check for transmission complete you should test the TRMT bit of the TXSTA register. If TXIF is set and TRMT is set, only then is the transmission complete.
It is possible that your interface circuit needs a small recovery time between characters (some characters? Pairs of characters? I don't know, I just do SW

). The delay you are using allows for this, just testing TXIF does not.
If you start to see errors after a few characters it's most certainly a wrong baud rate. Then after a pause the stuff resyncs and you have a few correct characters again. Please measure the length of a start bit on your scope, 9600 baud is 9600 bits/sec so 9600 Hz or 104 uSec.
Ok lance I found this in the hi-tech faq's, so I am wrong, there is no stdout buf
The printf() function performs two main tasks: formatting of text, and printing this
formatted text to stdout. The exact location of stdout is determined by a second
function called putch(), which is called by printf() to output each character.
[\quote]
It can't load anything else into the transmitter until what is there has been sent.
Oh yes it can 
TXREG holds the next character to be transferred to the Transmit Shift Register (TSR) and TXIF is set whenever TXREG is empty. The TSR contains the character that is currently being transmitted.
So, the character in TSR is transmitting, the TXREG is empty and TXIF is set. You put a character in TXREG and it waits there for TSR to empty at which point TSR is loaded with the new character, TXREG becomes empty, TXIF is set again and you load TXREG with another character while the previous character is transmitting. The data flow is continuous and is proceeding almost as quickly as the hardware can allow.
In short. TXIF does not tell you that the transmission has finished, only that TXREG is empty.
To check for transmission complete you should test the TRMT bit of the TXSTA register. If TXIF is set and TRMT is set, only then is the transmission complete.
It is possible that your interface circuit needs a small recovery time between characters (some characters? Pairs of characters? I don't know, I just do SW
). The delay you are using allows for this, just testing TXIF does not.
Interesting, I'll look into this some more.
If you start to see errors after a few characters it's most certainly a wrong baud rate. Then after a pause the stuff resyncs and you have a few correct characters again. Please measure the length of a start bit on your scope, 9600 baud is 9600 bits/sec so 9600 Hz or 104 uSec.
All the bits appear to be the correct width.
Ok lance I found this in the hi-tech faq's, so I am wrong, there is no stdout buf
Yup, although the function prototype actually exists in stdio.h. The function just doesn't do anything if it's in there somewhere.
Have you tried a small delay like..
void putch(char txchar)
{
while(!TXIF);
TXREG=txchar;
small_delay(); <<<<<<<
}
Have you tried a small delay like..
It's obviously a hobby project, not something done for work on a deadline. Much better to spend the learning time figuring out what is wrong with it than bodging a fix. There is usually no need for any delay. A decent UART transmitting to a decent UART over a short cable can go full speed directly stop bit to start bit.
Besides there's probably enough delay to output umpteen characters considering each character has to go through printf()
Have you tried a small delay like..
It's obviously a hobby project, not something done for work on a deadline. Much better to spend the learning time figuring out what is wrong with it than bodging a fix. There is usually no need for any delay. A decent UART transmitting to a decent UART over a short cable can go full speed directly stop bit to start bit.
Actually I do have a deadline for this. It's a school project. Not to say that I don't want to learn the actual cause, however I'll have to use the bodge until I have the time to figure out what's going on. I am really curious to know what is happening.
Ah. Yeah, we've all had to give up doing something the "right" way in the name of a deadline. It happens. I encourage you to keep investigating this past the end of the project, though.
Ah. Yeah, we've all had to give up doing something the "right" way in the name of a deadline. It happens. I encourage you to keep investigating this past the end of the project, though.
That's the plan. I'm going to switch over however from printf to sprintf and manage the output myself if I have the time once I get the rest of this thing working. I'm trying to aim for maximum efficiency.
printf may be more efficient as it is likely bufferless. Look at the code to be sure though.
however I'll have to use the bodge until I have the time to figure out what's going on. I am really curious to know what is happening.
Always remember a bodge is something someone else does to get something working without knowing why it works; But if you do it; it's known as a work-a-round! ;-)