Monthly Archives: May 2014

PIC talks UART

 

PIC talks UART

16F887 UART Breadboard Hello World

Overview

This article is about connecting two PICs via their UART. If you need to know about UARTs just Google that up, if you want to see them up close … read on!

Serial communication is something that has been around for quite some time and it is still very present today in many shapes and forms. When working with embedded systems knowing how to use the UART is of the utmost importance. The UART can be used for micros to talk to each other, for a micro to I/O to a terminal running on a PC, to interface to devices like a GPS module or a Zigbee or an infrared module.

For this article we will be using two PIC16F887 40 pin PDIP and compile the code with MikroC and Microchip XC8. We will be using two Mikroelektronika’s EasyPICs boards for the preparation of the material but we will also provide instructions on how to achieve the same results on a breadboard.

The two EasyPICs board connected via UART

The two EasyPICs board connected via UART


 The communication

At the wires level the two PICs will interface using PINs 25 and 26. These are the PINs reserved as TX and RX.

16F887-pinout-UART

PIC16F887 pinout

They are respectively RC6 and RC7 of port C in the block diagram below.

16F887-block-UART

PIC16F887 block diagram

16F887-Datasheet-USART-PINs

RC6/7 modes and functions

The signal generated should look like the one below. Bear in mind that our PICs will use simplex asynchronous communication. Wikipedia’s Universal asynchronous receiver/transmitter has additional information.

signal-UART

UART signal

The line is kept high until the transmission starts bringing the line to low and logic 0, then 8 or 9 bits are transmitted. The packet is terminated with a stop bit which is always 1. In this way the signal is brought back to high. Further details on the inner workings of the UART module can be found in the Serial Communication Modules of Mikroelektronika e-book and in Microchip PIC Mid-Range USART.


 The circuit

Our circuit will be as follows, we are connecting the PICs so that the TX on PIC1 is connected on the RX on PIC2 and vice versa the TX on PIC2 to the RX on PIC1. This configuration is also known as NULL-Modem.

Circuit setup

Just to make things easier in order to replicate the circuit on a breadboard, we have provided a BOM and a description of the breadboard set-up in another article … 40-pin (6F887) DIY Protoboard

Once the breadboards are ready and connected, they should look like this

UART-breadboard-connected1

Breadboards connected


UART-breadboard-connected2

Breadboards connected from another angle. The LCD hooks up neatly on top of the microcontroller

The Code

The aim of the program on PIC1 is to send a “Hello, world!” message to PIC2 so that the program running on it can display the message on its LCD.

The TX side will first of all set the baud rate, in this case to 9600 bps, then enter an endless loop in which it will write “Hello, world!” and “From 0xEE.net” to its UART at 1 seconds intervals. Between each message a character 10, representing a linefeed, is also sent as a terminator.

UART1_Init(9600);               // Initialize UART module at 9600 bps
  Delay_ms(100);                  // Wait for UART module to stabilize

  while (1) {                     // Endless loop
        UART1_Write_Text("Hello, world!");   // 0x48 0x65 0x6C 0x6C 0x6F 0x2C 0x20 0x77 0x6F 0x72 0x6C 0x64 0x21
        UART1_Write(10);                     // 0x0A
        delay_ms(1000);                      // Wait a bit
        UART1_Write_Text("From 0xEE.net");   // 0x46 0x72 0x6F 0x6D 0x20 0x30 0x78 0x45 0x45 0x2E 0x6E 0x65 0x74
        UART1_Write(10);                     // 0x0A
        delay_ms(1000);                      // Wait a bit
  }

The RX side will setup the baud rate to match the one from the TX PIC and then simply stay in an endless loop waiting for data to be ready. If some data is received. Each byte representing a character gets stored in an array of characters until a \n or linefeeld is received at which point the array is considered complete and ready to be displayed on the LCD via the next line.

UART1_Init(9600);               // Initialize UART module at 9600 bps
  Delay_ms(100);                  // Wait for UART module to stabilize

  while (1) {                                     // Endless loop
    if (UART1_Data_Ready()) {                     // If data is received,
       UART1_Read_Text(received,"\n",255);        // Store in received everything before a linefeed
      Lcd_Out(1,1,received);                      // Display received on the LCD
    }
  }

In the XC8 version of the program as shown in the snippet below the bulk of the work for receiving is done in the interrupt service.

void interrupt ISR() {

    if (PIR1bits.RCIF)          // see if interrupt caused by incoming data
    {
        char temp;
        temp = RCREG;     // read the incoming data
        PIR1bits.RCIF = 0;      // clear interrupt flag

        if(temp=='\n')      //if EOL
        {
            index = 0;
            new_rx = 1;             //"ding"
        }
        else if(temp!=1)           //in middle of string
        {
            rxtxt[index] = temp;         //load it up
            index++;                    //increment index
            if(index > 19)              //that's more than enough data
                {
                index = 0;              //reset index
                new_rx = 1;             //"ding"
                }
        }

        //
    }

}
Here you can fin the full TX code and the RX code for MikroC and the TX code and RX code for Microchip XC8.

 The Results

We thought it would be a good idea to give a bottom up approach to analysing what happens during the communication. Much like the ISO/OSI model will look at the different layers from the wires and the voltages up through to the message that gets displayed on the LCD.

Oscilloscope

The oscilloscope is a useful tool to look at voltage levels in the time domain. The scope displays the level from the input from the left to the right. Shown in the screen-shot is the ASCII letters “Hello”. We used a single sequence trigger to capture this sequence of the message. If you use a free-running rising-edge trigger it is difficult to determine what part of the message you are looking at. Note that there are very low levels of noise on the line. If there is noise on your UART communication lines you would find it with an oscilloscope as the oscilloscope is displaying actual voltage levels. In this case each major division horizontal  grid marking represents 2.0V with the middle horizontal marking set up as the 0V reference;  The vertical grid lines indicate time.

Hello at 9600 Baud

“Hello” at 9600 Baud

Logic analyser

One step above the voltage levels measured by the oscilloscope we can position the logic analyser which will interpret the changes of the voltage as logic levels. Depending on the type of signals and the electronics involved, the values will be interpreted as high and low or logic 1 and 0.

Bitscope-Oscilloscope2

“Hello, world!” as logic states

Protocol decoding

In order to better understand the results from the protocol decoders of both the logic analyser and the bus pirate, we can refer to the following ASCII table. The values displayed by both tools are both in hexadecimal.

ASCII TABLE

ASCII Table

Logic analyser decoding

A part from looking a bit more squeezed, the picture below is the same as the one obtained using the logic analyser,

Hello, world as timing

“Hello, world!” as timing

it is only by inspecting it with a packet decoder that the next level of abstraction will be unveiled.

Bitscope-Logic2

“Hello, world!” as UART Packets at 9600 kb/s

By using the hex column of ASCII table above we can already make sense of the packets by matching the numbers with the characters. It is with no surprise that the sequence above reads “Hello, world!” plus a line feed character at the end.

If you are so bold/mad as to look at the logic levels from the wave above, you will notice that the sequence for the “H” character has to be read from left to right to make sense. The “H” character is 0x48 in hexadecimal which in binary translates to 0b01001000. This should be made more evident by looking at the following picture which breaks down the packet sent into its 10 bits.

Bitscope-Logic4

UART packet dissection

Note the duration of each byte sent. At 9.600 kb/s we are sending 9600 b/s. The adjustment made by the baud rate generator produced an effective baud rate of 9.615 kb/s.

9.615 kb/s = 9615 b/s = 9.615 b/ms = 0.009615 b/us
The packet is composed of 10 bits and it takes 1.039 ms to send according to the logic analyser. This means that 1 bit takes 0.1039 ms or 103.9 us. The rate calculated from this yields 0.009624 b/us or 9.624 kb/s which is, rather obviously, very close to the baud rate set by the micro. Hurray!

Bitscope-Logic3

“H” character transmit duration. The duration should read 1.039 ms and not 980 us

Bus Pirate

Much like with the previous tool, when using the bus pirate in UART mode we can decode the message sent by either reading each byte sent

BusPirate-Decode-Input

Bus Pirate input decode

 

Note that the sequence captured on the left is inverted as “From 0xEE.net” comes before “Hello, world!”

while (1) {                     // Endless loop
        UART1_Write_Text("Hello, world!");   // 0x48 0x65 0x6C 0x6C 0x6F 0x2C 0x20 0x77 0x6F 0x72 0x6C 0x64 0x21
        UART1_Write(10);                     // 0x0A
        delay_ms(1000);                      // Wait a bit
        UART1_Write_Text("From 0xEE.net");   // 0x46 0x72 0x6F 0x6D 0x20 0x30 0x78 0x45 0x45 0x2E 0x6E 0x65 0x74
        UART1_Write(10);                     // 0x0A
        delay_ms(1000);                      // Wait a bit
  }

 

 

 

 

 

 

 

 

 

or by reading the raw UART input

BusPirate-Raw-Input

Bus Pirate raw input

Note the linefeed that we have inserted at the end of each message.

Follow the link should you want to know more about sniffing UART packets with the Bus Pirate.

LCD output

Finally our message gets displayed on the LCD connected to PIC2 gets displayed!

"Hello, world!" on the LCD

“Hello, world!” on the LCD


Final thoughts

At the end of this article you should be able to have two PICs talking to each other via their UART whether you are using MikroC or Microchip XC8. With some basic understanding of the protocol we can now move onto connecting to other devices or using different media to achieve the same communication. We will add a number of spin-off of this article as soon as we manage to put them together. Stay tuned!

We hope you add fun and in doing so also learned something new. Please get in touch through the forums, we’ll do our best to answer your questions, cherish your advices and, why not, learn something more.


40-pin ( PIC 16F887 ) DIY Protoboard

Francesco has a love obsession with his 16F887 and as we’re developing tutorials it was clear I needed to be ready to work with this product. My solution was a very basic development I put together from stuff lying around the bench.

An overhead shot of the breadboard. Note that the resistor is on PIN 1 pulling the /MCLR pin up out of reset. the /MCLR pin is also connected to the ICSP connector for programming purposes.

An overhead shot of the breadboard. Note that the resistor is on PIN 1 pulling the /MCLR pin up out of reset. the /MCLR pin is also connected to the ICSP connector for programming purposes.

Tired of DIY circuits with obscure parts? Me too.. this is a simple one and everything will be readily available. I used an Adafruit Perma-Proto Breadboard. This PCB is laid out just like a breadboard but you solder it. Their perma boards are handy for projects like this were you have something simple enough for the breadboard but want to keep it permanent. Radio shack has smaller ones for smaller circuits. I used the Minty version of the Perma board because I had a bunch on hand but their 1/2 size board should work fine for you. I also recommend a 40 pin DIP socket so you can use this for other microcontrollers, and perhaps a 0.1uF bypass capacitor. I scored some snap-away 90 deg 2.54mm headers from eBay for the ICSP (6 position). They are $2 with shipping or source them from a local supplier if available. I use my PICKit3 to program; if you’re using something else you may want to customize your own ICSP connection. I recommend putting headers on your board which I did not, but this will make connecting item to it easier in most cases.

Just in case I haven’t sold you on this, there is a bonus! This board works with many of the 8-bit line of microcontrollers available in 40 pin DIP sockets, not all of them but many. Examples: 18F452, 18F4520, 18F45K20, 16F1519, 16LF1907, etc.

Step 1. Gather your parts (list at bottom of the article).

This is the bare minimum of parts required for the breadboarding of the 16F887. The socket could be left out but that's a poor idea.

This is the bare minimum of parts required for the breadboarding of the 16F887. The socket could be left out but that’s a poor idea.

Step 2. Wire parts to the protoboard:

Connections you need to ensure you make:

Pin 11 & 32 : Wire these to the positive (Vdd) rails (I also recommend connecting your rails together as I did.

Pin 21 & 31 : Wire these to the negative/common/ground (Vss) rails. (also connecting them together.

Pin 1 : Solder a resistor from Pin 1 to the positive rail. I recommend 4.7K to 10K. This is needed to pull your pick out of reset. You can optionally add a push button reset switch wired normally open from Pin 1 to Ground/Common.

Going to program this on a different board and don’t need a crystal? well you’re done..  I do like to ICSP if I can free up the ports easy enough so:

If you’re looking towards the pins as if you were the programming tool being plugged in, we will call the left pin Pin A, then to the right B, C, D, E and F.

Pin A will go to Pin 1 on the PIC (/MCLR).

Pin B  wire to Vdd rail (+5V)

Pin C wire to Ground/Vss

Pin D is the ICSPDAT pin and will go to the Pin 40 on the microcontroller.

Pin E is the ICSPCLK and will be wired to Pin 39 on the microcontroller.

Pin F is not connected to anything.

I use the internal oscillator most of the time but if you’re feeling a burning hurt to use an external oscillator check out Page 64 in the Microchip specification guide for the PIC 16F887 ( DS41291F ). I’ll give you a sneak pic of it embedded…

xtal

Step 3: That’s it, add headers and customize for your circuit! I recommend adding a ground loop attachment for a meter/scope probes/logic analyzer minigrabbers, etc.. see the photo below for an example:

I recommend putting in a sturdy ground loop for minigrabber yest leads to grab on to. You can power your board this was or just use it as a ground point with a meter of oscilloscope. I also use machined socket DIPs for cheap wire sockets on the boards. Shown is a DIP I've been cutting up to put in plugin jumpers on the board.

I recommend putting in a sturdy ground loop for minigrabber yest leads to grab on to. You can power your board this was or just use it as a ground point with a meter of oscilloscope. I also use machined socket DIPs for cheap wire sockets on the boards. Shown is a DIP I’ve been cutting up to put in plugin jumpers on the board.

In my first board I added an LED with current limiting resistor (270 ohm) so that I could have a “heart beat” LED on my test circuit. This is a quick indicator that your oscillator is working and you have power.

My first protoboard with some "extras" .. I put a 47uF capacitor across the rails and a 0.1uF bypass capacitor across the rails as well. Finally I added and LED w/ a current limiting resistor on a header so I could add this to any pin I wanted.

My first protoboard with some “extras” .. I put a 47uF capacitor across the rails and a 0.1uF bypass capacitor across the rails as well. Finally I added and LED w/ a current limiting resistor on a header so I could add this to any pin I wanted.

Bill of Materials:

  • Adafruit Perma-Proto Breadboard https://www.adafruit.com/products/571
  • Microchip PIC 16F887 Digikey P/N PIC16F887-I/P-ND
  • 40 Pin DIP socket (eBay <$1) You may consider a “ZIF” socket if you know you’ll be swapping microcontrollers every so often.
  • 10kOhm resistor (Radio Shack, your scrap bin, eBay..  look for 1/8th or 1/4 watt)
  • Headers (eBay or a local shop, pick something that works for you.. I used a machined DIP socket cut up)
  • 90 deg 2.54mm header — Something like Jameco p/n: 103271 though I got mine from eBay.
  • Bits of wire and the tools to do the job including a soldering iron, etc.

 

 

Welcome!

Hello, Welcome to 0xEE.net. This site is a collaborate effort between of Francesco of the Garage Tech blog and Chas of the /PNW/ELECTRONICS blog.

We propose to deliver content in a flexible format for the beginner as well as provide an easy to access reference for those who are more experienced. We’ll write guides, project outlines, and tutorials involving PIC microcontrollers and electronics in general. We’ll be using the Microchip platform as well as the Mikroelectronika tools and development boards. Based on the project you may find an article using the Microchip MPLABX IDE with XC8 C compilier or the Mikro C PRO tools.

Our article tagging will include a difficulty rating which we will explain at a later date once it’s finalized. It’ll outline what level of experience should be considered a minimum level to accomplish the task without too much difficulty.

We encourage feedback, both positive and negative, to help us shape this project into a valuable resource for PIC developers and newcomers alike.