Monday , January 23 2017
Home / Embedded Systems / Arduino / Arduino Like Serial / UART Library for PIC 18 Microcontrollers
PIC with serial port

Arduino Like Serial / UART Library for PIC 18 Microcontrollers

In my last post describing the implementation of a circular buffer I mentioned that I was working on a serial UART library for PIC 18. Well it is now completed! Yesterday I tested all the functions of the library and its working like a charm!

In this post I will explain some key aspects of the code and how to download and use it in your code.

What is UART?

Universal Asynchronous Receiver and Transmitter is a serial communication protocol. It is an ‘asynchronous’ communication protocol… meaning it does not have a clock line (read about the use of clock line in digital communication protocols) to sync the data transfer.

For it to be defined as a protocol we have to have some ground rules so that the transmitter and receiver can understand what each other are trying to say. So that’s when we have the baud rate (can be referred to as bit rate or rarely as bandwidth) Start and Stop bits.

I will not go into the details of the serial communication protocol in general… it’s a post for another day! But if you really can’t resist the urge our friends at MaxEmbedded have done a wonderful job in explaining the basics do have look.

Like I mentioned in my previous post, I wanted the serial transmission and reception to be handled by interrupts and that’s exactly how I have done it. The best part is I have tried to make the functions look and behave mostly like the Arduino serial library.

Why use interrupts for reception and not for transmission?

Well it’s not as unfair as may seem… we have good reason to do it! When interrupt based serial communication is discussed, most of the time people write the reception in interrupt mode and transmission in polling mode.

The reason is that the incoming byte is time sensitive. That is if we are busy doing something else while a byte is at the received register, then the successive byte can overwrite the existing byte and the previous byte will be lost forever.

On the other hand, the transmission is bound by the program and you can control when the transmission has to happen and it’s up to the receiving deice to take care of how to receive it. So what we do is write the data to be transferred serially to the transmit register and wait for the data to be sent out and then move on to the next byte/task.

I have used interrupts in both transmit and receive functions just to demonstrate the its use in both the cases!

Serial Interrupt Mechanism

The serial reception interrupt is pretty straight forward. When there is a byte in the RXREG (reception register in PIC micros) the controller interrupts and jumps to the interrupt vector and grabs the byte and stores it in the RAM. Then the user program can then use this data at its discretion.

The transmission interrupt is not so trivial. Here, so long as the interrupt is enabled, the controller keep jumping into the ISR.

Weird? Not exactly… the controller interrupt each time the TXREG (transmit register) is empty that is after the data has been sent out. So all we have to do is, write the data to be sent to a buffer and then enable the transmission interrupt. Inside the ISR, we will have to add code to load the buffer on to the TXREG one after the other.

Once the last byte in the buffer is loaded, we will have to disable the interrupts inside the ISR this is really important. You will HAVE to disable the interrupt after loading the last data in the buffer is loaded. Your software should make damn sure of that. Failing to do so will result in successive interrupts which implies your program will not execute at all!

Where is the program?

The program run close to 400 lines so I will refrain from posting it here. You can find the code along with an example program at our GitHub Repository.

Download from GitHhub

I have commented the code very well so I don’t think there is any need for a description here. Besides, the most important part of the code, dealing with the circular buffer and their use has already been discussed. If you still have some thing to ask, leave a comment and I will get back to you as soon as possible.

I have also added some functions to perform string operations at the end of the file that is for the GPS module interface that I am working on right now! Feel free to have a look but if you don’t like it, you know where to find the back space!

About Siddharth

Siddharth is a Firmware Engineer, techie, and a movie-buff. His interests include, Programming, Embedded Systems, Linux, Robotics, CV, Carpentry and a lot more. At times, you could see some of his sunday projects converge on release quality. You get to know him on the following social channels.

Check Also


Getting Started with PIC Microcontrollers

Having worked with any one Microcontroller, moving from one of its family to another is …

  • Wijnand Nijs

    Hello Siddharth,

    I have a question about the type choise of head and tail in the fifo/buffer structure. Isn’t it a must to make them uint8_t because no atomic for double bytes is guaranteed? Forcing them to uint8_t gives less possibilities voor FIFO_SIZE (only 2, 4, 8, 16, 32 and 64).
    Regards Wijnand…

    • Hi Wijnand, What you are saying would be true in an 8 bit system. It’s generally accepted to leave head and tail to native integers. This gives us the huge advantage of code portability (int width is 16 in a 16 bit system and 32 in 32/64 bit systems).

      What is required and not done in the code I have checked in is a critical section. When head and tail are modified, the code has to enter and exit a critical section that has all interrupts disabled. This is a more robust and portable way to achieve atomicity. I will update the code with those strategies in the near future.

      Nice catch. Thanks.

Keep in touch with the current trends!
Did you like this article? Sign up and get our latest posts delivered to your inbox!
  We hate spam and never share your details.