HOW-TO: Learn PIC serial UART with your Bus Pirate

The Bus Pirate is a handy debugging tool, but it’s also a 16 bit PIC 24FJ64GA002 development board. You don’t need a programmer to play, just upload the firmware over USB using the Bus Pirate’s nearly-impossible-to-brick bootloader. It’s easy to go back to the original Bus Pirate firmware at any time.

This demo is step two, you can find step one in our wiki, or check out the previous post. It shows how to setup the PIC to communicate with the FT232RL serial-to-USB IC over , and establish communication with your computer over the com terminal. The code below is broken up and explained section by section.

Overview

This tutorial shows how to use the serial UART peripheral on the Bus Pirate v3’s PIC 24FJ64GA002. All PIC24 and PIC33 chips with UARTs should work about the same. The UART is connected to an FTDI USB to serial converter chip, so we can test the UART demo from a serial terminal on a PC.

After this tutorial you should be able to send and receive serial data from the Bus Pirate hardware.

Hardware

Bus Pirate’s PIC chip and the FTDI chip are connected as shown in the table. These PIC pins have a cool feature called Peripheral Pin Select. We can use PPS to assign hardware, like the UART, to any pin we want. This makes board design and routing much easier. It’s also the basis for the versatility of the main Bus Pirate firmware.

Firmware

Configuration

#include _CONFIG2(FNOSC_FRCPLL & OSCIOFNC_ON &POSCMOD_NONE & I2C1SEL_PRI) // Internal FRC OSC = 8 MHz
_CONFIG1(JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx1) //turn off junk we don't need

#pragma code

int main(void){

CLKDIVbits.RCDIV0=0; //clock divider to 0
AD1PCFG = 0xFFFF; //Default all pins to digital
OSCCONbits.SOSCEN=0;

The configuration is the same as with our other demos. The first few lines are dedicated to setting up the CONFIG registrar, selecting the right values for the oscillator, and making all our pins digital.

UART Initialization

The serial UART on the PIC is initialized to fit our hardware by assigning the UART module to the corresponding reprogrammable (RP) pins.

RPINR18bits.U1RXR = 5; //map to RP5

For input pins, like the RX UART pin, the register associated with the UART1 RX peripheral needs to be loaded with the RP pin number(RP5).

RPOR2bits.RP4R = 3; //3 is the UART1 TX output function number in table 10-3

For Output pins, the RP pin register is loaded with the output peripheral (UART1RX). See table 10-3 of the PIC24FJ64GA002 datasheet for all the peripheral options.

UART baud rate setup

The Bus Pirate uses an 8 MHz internal clock multiplied by a 4x PLL to produce a 32 MHz CPU clock. The PIC does one instruction every two clock ticks, or 16 MIPS.

To set the UART to our desired baud rate (115200bps) we use equation 17-2 from the datasheet.

Fcy = Fosc/2
Fcy = 32 MHz/2 = 16 MHz

First find Fcy, which is the number of instructions the PIC processes per second.

U1BRG = [Fcy/(4*Baud Rate)] - 1

For a baud rate of 115200 and an Fcy of 16 MHz we get 33.722, about 34. That’s not exactly 115200 bps, but 114285 bps – an acceptable 0.79% error.

U1BRG = 34;

Write 34 to the U1BRG (UART 1 baud rate generator) register for a speed of 115200bps.

Some more configuration

U1MODE=0; //clear all U1MODE register
U1MODEbits.BRGH = 1; //highest baudrate select
U1STA = 0; //clear all U1STA register
U1MODEbits.UARTEN = 1; // Enable UART1
U1STAbits.UTXEN = 1; //Enable transmit
IFS0bits.U1RXIF = 0; //Clear UART1 Received interrupt flag

These are some general settings that enable the UART. We won’t dwell on these here.

Continuous loop

//Main Loop
    while(1){
         //wait for byte from USB to serial converter
         while(U1STAbits.URXDA == 0); 
         c=U1RXREG;//get byte

         //wait for empty spot in transmit buffer
         while(U1STAbits.UTXBF == 1); 
         //echo received character back to USB to serial converter
         U1TXREG = c; 
    }

This code is executed in a continuous loop. The Bus pirate waits for one character to be sent to it via terminal, and once received the same character is echoed back to the terminal.

Get incoming data

while(U1STAbits.URXDA == 0);

When a byte is received the URXDA bit changes to 1. Until then, we just hang out here.

c=U1RXREG;//get byte

Incoming bytes are stored in U1RXREG. We grab it into variable c.

Send data to the computer

while(U1STAbits.UTXBF == 1);

If there is still a byte being transmitted to the computer we have to wait for it to complete before we can send more. If we don’t wait, the currently transmitting byte is lost. When a transmission slot if available the UTXBF bit changes to 0, until then we just hang out.

U1TXREG = c;

Finally we put the byte we stored in variable c into the UART transmit buffer to send back to the computer.

Test it out

With code in hand, let’s compile it and program the Bus Pirate. Upload your code using the bootloader, or a PIC programmer.

Reset the Bus Pirate by replugging the USB cable. Open a terminal program such as the one you normally use with the Bus Pirate, we use Tera Term. Set it to the Bus Pirate serial port and configure the speed settings we configured in the firmware (Baud Rate: 115200, Data Size: 8 bits, Parity: None).

Type in a letter in the serial terminal. The Bus Pirate receives the character and echos it back to the terminal. Congratulations you’ve just established a link with your Bus Pirate UART over the USB to serial converter!

*You can download the entire MPLAB project in our SVN file repository
*Lost? Check out our introduction demo that simply blinks the Bus Pirate MODE LED
More Pirate as a PIC24F64GA002 development board tutorials

C30 Code

#include <p24fxxxx.h>
_CONFIG2(FNOSC_FRCPLL & OSCIOFNC_ON &POSCMOD_NONE & I2C1SEL_PRI)        // Internal FRC OSC = 8MHz
_CONFIG1(JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx1) //turn off junk we don't need

#pragma code

int main(void){

  CLKDIVbits.RCDIV0=0; //clock divider to 0
  AD1PCFG = 0xFFFF;    //Default all pins to digital
  OSCCONbits.SOSCEN=0;   

  //Initialize UART1
  RPINR18bits.U1RXR = 5; // UART1 RX assign to RP5
  RPOR2bits.RP4R = 3; //UART1 TX assign to RP4

  U1BRG = 34;
  U1MODE = 0;
  U1MODEbits.BRGH = 1;
  U1STA = 0;
  U1MODEbits.UARTEN = 1;
  U1STAbits.UTXEN = 1;
  IFS0bits.U1RXIF = 0;

  //Main Loop
    while(1){
         //wait for byte from USB to serial converter
         while(U1STAbits.URXDA == 0); 
         c=U1RXREG;//get byte

         //wait for empty spot in transmit buffer
         while(U1STAbits.UTXBF == 1); 
         //echo received character back to USB to serial converter
         U1TXREG = c; 
    }
}

This entry was posted in Bus Pirate, dev boards, how-to, tutorials and tagged , , .

Leave a Comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Notify me of followup comments via e-mail. You can also subscribe without commenting.