Communicating With PIC Over Serial - Page 1
Forum section: electronics / projects

author: Lance
author_rank: Frequent Contributor
timestamp: March 19, 2013, 03:25:31 am
content: Hi everyone. I have a project using a PIC16F1823 micro, and I'm trying to get it to talk over serial. The USB to serial converter I'm using is a Prolific brand chip.I've been getting some odd data back through PuTTy. This is what I got back:Code:ÌcsBÌcsccÎÎBïcãÄCÌCïÌcsBÌBskCgÌcsBÌBskCgÌcsBÆgsÞgÎsssssssssssïBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbCBbCbCBbbbBbCbFrom this code:Code:for(i=0;i<33;i++){printf("%u",i);}I'm using the hitec C compiler operating in lite mode for this. I here is my putch function:Code:void putch(char txchar){while(!TXIF);TXREG=txchar;}From what I understand this is correct, however this is the first time I've written a putch function. The scope currently available to me doesn't have serial decode, so I'm not sure if this is an error with my machine, or on the microcontroller. Has anyone encountered an issue like this before?

author: c4757p
author_rank: Super Contributor
timestamp: March 19, 2013, 03:34:03 am
content: Check the baud rates.

author: Lance
author_rank: Frequent Contributor
timestamp: March 19, 2013, 04:19:16 am
content: I did have an error in the baud rate. I've recalculated the values.I'm now running at 9600 Baud off of the 8 bit clock at a system oscillator speed of 32MHz. Transmission is asynchronous. I calculated the value for the control bits to be 52 based off the formula in the datasheet. So the lower register is 52, and the upper register is 0. I am now getting this out of the port:Code:Â¢ª²ºÂ¢ª²ºÂ¢ª²º

author: c4757p
author_rank: Super Contributor
timestamp: March 19, 2013, 04:27:56 am
content: Can you attach the rest of your code, or at least everything relevant to the USART?

author: c4757p
author_rank: Super Contributor
timestamp: March 19, 2013, 04:42:02 am
content: By the way, I'm getting a 1.7% error on the baud rate based on that config number. Add in some oscillator error and it may just be too much. Using 51 instead of 52 brings it to 0.1% error.

author: Lance
author_rank: Frequent Contributor
timestamp: March 19, 2013, 05:18:20 am
content: Oh...so here is a capture from the scope. The blue trace is the microcontroller output. The yellow is what is being sent to the computer by the driver circuit. Note the voltage scale difference.

author: c4757p
author_rank: Super Contributor
timestamp: March 19, 2013, 05:29:30 am
content: 1) Try to capture an entire transmission, start bit to end.2) Your initialize() function is really hard to follow. Try to use defines for individual flags, not whole registers. Bitwise-OR them in the function body. And lose the retarded #define ONE, define TRUE crap.3) Commenting out killallhumans.h doesn't keep it out, code can be injected before main() by the linker. Check your makefile carefully - our lives may be in danger. Come to think of it - you should probably hand assemble the code and program it in using DIP switches - any part of your compile toolchain may be compromised with the tools of the PIC apocalypse.4) It is 1:30 AM here and I am going to bed. Hopefully someone else can help you dissect this, or I will do more in the morning.5) Check the hardware too. How exactly is this connected?

author: Lance
author_rank: Frequent Contributor
timestamp: March 19, 2013, 06:01:36 am
content: Odd thing just happened. I set putty to use no flow control and I then started getting 0-8 out in the terminal. I went and tried to send a different string, and got more garbage out of it. Then my computer threw a BSOD.I'll show you the connection stuff in the morning.EDIT: So it turns out that if I put in a delay between the prints the thing suddenly starts working. I don't quite know why. I have a feeling it may be something to do with the converter. I'll look at the datasheet and see what I can find.

author: c4757p
author_rank: Super Contributor
timestamp: March 19, 2013, 01:50:57 pm
content: A BSOD? Seems weird that the computer can't handle a corrupt data stream...The code looks reasonable to me, unless someone else knows better, so I would suspect the connection or settings on the computer.

author: Harvs
author_rank: Super Contributor
timestamp: March 19, 2013, 02:12:49 pm
content: I regularly find that using a usb to serial converter, if the uC is dumping a lot of data but nothing is receiving it (I. E. Putty isn't open) it can crash windows. I guess it's a bug in the driver or something so the bsod sounds pretty normal to me.

author: c4757p
author_rank: Super Contributor
timestamp: March 19, 2013, 03:13:51 pm
content: Did he say USB? That waveform looks like true RS-232, doesn't it? Or am I having a brain fart?Edit: I am having a brain fart. He said USB. Er... check your hardware. Not sure why that waveform is 10Vpp. Can we please have a schematic? Just draw one on paper if you don't have one in CAD, but it'd be nice to see a clear diagram of connections. And mark exactly where in the schematic you have stuck the scope probes.

author: AlfBaz
author_rank: Super Contributor
timestamp: March 19, 2013, 03:39:20 pm
content: Quote from: Lance on March 19, 2013, 06:01:36 amJust a shot in the dark here since you are using a different compiler and It was the 18f's with c18 that I used.Have a look at the setbuf() func and set it to 0. printf() buffers the stream until it fills up or you flush it, if memory serves me.

author: Lance
author_rank: Frequent Contributor
timestamp: March 19, 2013, 07:51:07 pm
content: I just quickly drew the schematic up on my whiteboard. This circuit is also used on a little kit robot that I own.So I also decided to slow down the transmission to help me capture the waveform. Stuff started to work.Code:for(j=0;j<1000;j++);printf("ROFLCOPTER");Code:OPUQêROFLCOPTERROFLCOPTERROFLCOPTERROFLCOPTERROFLCOPUIÿROFLCOPTERROFLCOPTERROFLCOPTERROFLCOPTERROFLCOPTERROFLCOPTERROFLCOPTERROFLCOPTERROFLCOPTERROFLCOPTERI've also attached a full capture of one ROFLCOPTER.

author: c4757p
author_rank: Super Contributor
timestamp: March 19, 2013, 08:20:18 pm
content: Er... that schematic is bizarre. Why do you have a signal going into a 22 uF capacitor?? I'm not quite sure what's going on there, but I'm tempted to blame that.What exact USB-serial device are you using? Is it a TTL-level output, or RS232? If it's TTL you just connect the outputs directly to the microcontroller. If you can give me a part number so I can look it up, maybe I can help you out with connecting it to the microcontroller.Quote from: Lance on March 19, 2013, 07:51:07 pmFor a very loose definition of "work". Sounds like something doesn't like that 22 uF capacitor. That'll put a severe cap on the speed, and for no reason that I can see.

author: Lance
author_rank: Frequent Contributor
timestamp: March 19, 2013, 08:44:23 pm
content: Quote from: c4757p on March 19, 2013, 08:20:18 pmAs in suddenly I started to get valid data back.I was initially using a prolific device embedded in a USB to serial converter cable (I didn't buy it, that's all that was around here). Then I switched over to an FTDI 232RL and I'm running it at TTL level. Even with a straight connection to the device however, I still need to have a delay there in order for the computer to not interpret the incoming data as garbage.I'm thinking the issue might be with the way the PIC is transmitting the data. Unfortunately the scope I have here isn't super fantastic. I'll do the best I can with it.

author: David_AVD
author_rank: Super Contributor
timestamp: March 19, 2013, 09:39:55 pm
content: That is a bizarre circuit. You need to spell out what the heck is going on there before looking at the code more.

author: Lance
author_rank: Frequent Contributor
timestamp: March 19, 2013, 10:36:18 pm
content: Quote from: David_AVD on March 19, 2013, 09:39:55 pmI sporked this level shifting circuit from a robot kit that I have. I don't fully know how it works...I tore that circuit out, and I'm using the FTDI 232RL device now. It's connected directly to the microcontroller. I'm still however running into the issue of the data coming out as garbage on the other end unless I use that delay...Looking at the form on the scope, I think that the time between transmissions is so small that the receiver is reading on the wrong spot. The gap is of the same size as the bits.

author: c4757p
author_rank: Super Contributor
timestamp: March 19, 2013, 11:03:25 pm
content: Quote from: Lance on March 19, 2013, 10:36:18 pmNeither do I. Any chance you sporked it wrong? I'm particularly confused by the unholy matrimony of the Tx and Rx signals across that 4k7 resistor, and the WTF capacitor...Thislooks much better - try it. Only change I would make is to move D1's cathode from the Tx line (I don't like that it takes its parasitic draw from the signal line - may distort at higher speeds) to the DTR line (pin 4 on a DB9). You'll need to ensure that DTR is set low (this is a noninverted line, unlike Tx and Rx) in the PC software. And you should read the explanation - it is quite detailed.Update: Just saw that you're using an FTDI device now. Um... I don't know. I'm really stumped by the need for that delay. Your code looks fine. Hopefully someone else can help with that.

author: c4757p
author_rank: Super Contributor
timestamp: March 19, 2013, 11:10:33 pm
content: Quote from: Lance on March 19, 2013, 10:36:18 pmAs long as your start and stop bits are all there, there should not need to be any idle time at all.Have you actually dissected the stream on a bit-by-bit level? Capture a byte or two of transmission on your scope screen and checkeverything.Measurethe baud rate to make sure it is right. Then, use the vernier control to set up the waveform so that the time scale lines up exactly with the baud rate, sync to the start bit, and manually decode the stream, reading at every tick mark. If this "human UART" can get a signal, I see no reason why the computer can't.

author: David_AVD
author_rank: Super Contributor
timestamp: March 19, 2013, 11:13:57 pm
content: Quote from: Lance on March 19, 2013, 10:36:18 pmIs the FT232 converter an RS232 level or TTL level unit? Does it have a D9 connector?

author: Lance
author_rank: Frequent Contributor
timestamp: March 19, 2013, 11:19:16 pm
content: Quote from: c4757p on March 19, 2013, 11:03:25 pmIt's on page 15 of this assembly guide.https://solarbotics.com/download.php?file=1590Quote from: c4757p on March 19, 2013, 11:10:33 pmDecoding this stream manually will be tedious. My scope doesn't have any automatic features for that, but I'll try.Quote from: David_AVD on March 19, 2013, 11:13:57 pmIt runs at TTL level.

author: c4757p
author_rank: Super Contributor
timestamp: March 19, 2013, 11:25:03 pm
content: Quote from: Lance on March 19, 2013, 11:19:16 pmYep, you sporked it wrong. Look closer at the connections. (If it makes you feel better, that is ashitschematic and I would probably spork it wrong too.)Quote from: Lance on March 19, 2013, 11:19:16 pmMore tedious than the hunting around you've already been doing? It's just 8 or 16 bits or so! Sometimes debugging iswork. And you shouldn't use an automatic decode for that, it's probably better than the UART in the FTDI chip and might make sense of the signal even if nothing else does. You need to do it yourself and hold it to a tight standard. That's why I suggested making use of the vernier control so you know you're reading the signal right when a real UART would.

author: Lance
author_rank: Frequent Contributor
timestamp: March 20, 2013, 02:03:32 am
content: Quote from: c4757p on March 19, 2013, 11:25:03 pmYup...fixed it. I'll try rebuilding it later.Just for a sanity check on my math here:9600 symbols/second * 8 bits/symbol = 76800 bits/second --> 13E-6 seconds/bit.I've tried several times to get this to work, however I can't manually decode the data I'm looking for.I recorded all the bits form the start of one transmission to the beginning of the other. I then searched through it to find specific characters that I looked up in the ascii table. Nothing.

author: MikeK
author_rank: Super Contributor
timestamp: March 20, 2013, 02:35:06 am
content: If it was just 8 bits per character you'd never decode it. Each character has start and stop bits.

author: Lance
author_rank: Frequent Contributor
timestamp: March 20, 2013, 03:19:21 am
content: Quote from: MikeK on March 20, 2013, 02:35:06 amRight, I'll give it another shot.EDIT: I got it! I decoded a couple a shorter strings to get some practice. I'll try manually decoding the initial string to see what's going on.The baud rate appears to be correct.EDIT: It turns outSo I found the issue. I shortened the delay, and started working my way through the following strings:"A""R""RO""ROF"When I reached "ROF" I started getting corrupted data.For RO I get the following, I've seperated the start and end bits.0 01010010 1 0 11110010 1For ROF I getCode:JÕÊback from the terminal. Currently working on decoding the whole string.EDIT 2:So for 9600 Baud each bit is 104us, so a three character burst has 30 bits (including stop/start flags) which comes to 3.12ms.I captured the following data over that span0 01010011 0 0 01010010 0 1 01010111 1Looks like something is getting messed up along the way.

author: c4757p
author_rank: Super Contributor
timestamp: March 20, 2013, 05:06:11 am
content: 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.

author: c4757p
author_rank: Super Contributor
timestamp: March 20, 2013, 05:09:04 am
content: Quote from: Lance on March 20, 2013, 03:19:21 amEither 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.

author: ecat
author_rank: Frequent Contributor
timestamp: March 20, 2013, 06:11:24 am
content: Quote from: Lance on March 20, 2013, 02:03:32 amTypically 9600 baud:9600 bits per second, 1 start bit + 8 data bits + 1 stop bit = 10 bits per character = 960 characters per second.

author: AlfBaz
author_rank: Super Contributor
timestamp: March 20, 2013, 07:17:28 am
content: 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

author: David_AVD
author_rank: Super Contributor
timestamp: March 20, 2013, 07:46:27 am
content: 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?

author: Lance
author_rank: Frequent Contributor
timestamp: March 20, 2013, 08:07:29 am
content: Quote from: ecat on March 20, 2013, 06:11:24 amI figured something was wrong there...Quote from: AlfBaz on March 20, 2013, 07:17:28 amThe way I wrote putch will block it:Code: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.

author: ecat
author_rank: Frequent Contributor
timestamp: March 20, 2013, 09:00:12 am
content: Quote from: Lance on March 20, 2013, 08:07:29 amOh yes it canTXREG 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.

author: PA0PBZ
author_rank: Super Contributor
timestamp: March 20, 2013, 10:34:06 am
content: 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.

author: AlfBaz
author_rank: Super Contributor
timestamp: March 20, 2013, 12:29:13 pm
content: Ok lance I found this in the hi-tech faq's, so I am wrong, there is no stdout bufQuote

author: Lance
author_rank: Frequent Contributor
timestamp: March 20, 2013, 12:31:11 pm
content: Quote from: ecat on March 20, 2013, 09:00:12 amInteresting, I'll look into this some more.Quote from: PA0PBZ on March 20, 2013, 10:34:06 amAll the bits appear to be the correct width.Quote from: AlfBaz on March 20, 2013, 12:29:13 pmYup, although the function prototype actually exists in stdio.h. The function just doesn't do anything if it's in there somewhere.

author: Unknown
author_rank: Unknown
timestamp: March 20, 2013, 12:47:40 pm
content: Have you tried a small delay like..Code:void putch(char txchar){while(!TXIF);TXREG=txchar;small_delay(); <<<<<<<}

author: c4757p
author_rank: Super Contributor
timestamp: March 20, 2013, 01:10:00 pm
content: Quote from: jucole on March 20, 2013, 12:47:40 pmIt'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.

author: AlfBaz
author_rank: Super Contributor
timestamp: March 20, 2013, 01:29:04 pm
content: Besides there's probably enough delay to output umpteen characters considering each character has to go through printf()

author: Unknown
author_rank: Unknown
timestamp: March 20, 2013, 02:20:04 pm
content: This might be helpful.http://www.microchip.com/forums/m608851.aspx

author: Lance
author_rank: Frequent Contributor
timestamp: March 20, 2013, 09:24:33 pm
content: Quote from: c4757p on March 20, 2013, 01:10:00 pmActually 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.

author: c4757p
author_rank: Super Contributor
timestamp: March 20, 2013, 09:33:48 pm
content: 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.

author: Lance
author_rank: Frequent Contributor
timestamp: March 20, 2013, 09:57:15 pm
content: Quote from: c4757p on March 20, 2013, 09:33:48 pmThat'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.

author: c4757p
author_rank: Super Contributor
timestamp: March 20, 2013, 10:14:47 pm
content: printf may be more efficient as it is likely bufferless. Look at the code to be sure though.

author: Unknown
author_rank: Unknown
timestamp: March 20, 2013, 11:02:05 pm
content: Quote from: Lance on March 20, 2013, 09:24:33 pmAlways 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! ;-)