Setting up and Using the UART for the PIC
In a previous post I explained many of the registers and bits used in the UART. This time we’re going to put those pieces together to make a functional UART.
First thing you need to set is the baud rate. The baud rate is dependent on the clock speed. It’s important to know what you want your baud rate to be before you start setting everything up. If you’re just testing it out between two PICs, it isn’t as important. However, if you’re trying to communicate with a peripheral, read the data sheet and make sure you know what speed it communicates at. An example is that the XBee only communicates at 9600 baud, so you need to work with that.
Let’s assume that we want that 9600 baud. We’ll want to look at the data sheet of the PIC we’re using, where we’ll find a couple pages of tables. These tables help us decide what settings we need to use at different clock frequencies. It also shows the error of the communication speed, or the deviation of actual rate versus desired rate. You’ll note that some clock frequencies yield better error rates than others. On the 16F690, I’ll actually vary the clock signal according what gives me the best rate (this, of course, affects time sensitive operations and power consumption, but in some projects, those don’t concern me). On the 18F877A, where I have a set frequency of 4 MHz in one of my current projects, I set BRGH even though I only want 9600 baud. This is because I get a much, much better error rate with BRGH set and SPBRG = 25 instead of clearing BRGH and putting SPBRG = 6.
Those are just some considerations while setting up your UART. The actual code I use to transmit with a PIC16F690 setup for 9600 baud using an 8MHz clock is as follows:
SPBRGH = 0; // Most significant byte, not available on 16F877A.
SPBRG = 12; // Least significant byte
BRG16 = 0; // No 16 bit communication, also not available on 16F877A
BRGH = 0; // 8 MHz isn't that fast, so we don't need to set this.
SYNC = 0; // Asynchronous
SPEN = 1; // Serial Port Enabled
TXEN = 1; // Transmit enabled
TXREG = a; // Transmitting the requested character.
and the receive code:
SYNC = 0;
SPEN = 1;
BRG16 = 0; // 8-bit communication
BRGH = 0; // Setting up the transmit speed
SPBRGH = 0;
SPBRG = 12;
CREN = 1;
while (RCIF == 0) // Wait loop while waiting to receive data
CLRWDT();
a = RCREG; // Read from the receive register
For transmission, you’ll most likely want some sort of indication that the UART is done transmitting, because if you try and transmit again before it is done, you will get an error. I would suggest using the TRMT bit to verify that a transmission has completed. The TRMT bit is set when it is empty, i.e. when it’s done transmitting.
I split it up into a “setup” type function and a “use” type function and have a little bit more tacked on in there, but those bare bones should work for you. You should also note that much of the order of those instructions aren’t that important, but others are. Once you get an intuitive feeling of what is going on, it’ll be easy to discern which one is which.
Let me know if anything doesn’t make sense or you have a specific question that I haven’t answered or you’re having any difficulties.
Comment from Joshua
Time June 12, 2009 at 8:52 pm
Important addition to this post: If, for some reason, the transmission from your PIC works but you can’t receive, make sure that you’re not sharing your receive pin with something else, specifically an ADC pin. I switched from the 16F877a to the 16F690 and couldn’t even get RCIF to set. After much scrambling about and finally Googling, I found that I hadn’t cleared ANS11 to disable the analogue circuitry.
Hope this tip saves you some time.