PIC Serial Tx and Rx

The last step of preparation for some serious PIC programming is to learn how to use the serial interface of the PIC for reading (Rx) and writing (Tx). So I decided to enhance the 3-Digit 7-segment display to read the input value over the serial connection. To test it I wrote a simple serial transmitter that sends the numbers from 1 to 255 first counting upwards (1 to 255) and then downwards (255 to 1) over and over again. The 3-digit display shows these numbers that it reads from its serial port.

The transmitter

First some definitions for the direction of counting

#define UP 1
#define DOWN 2

Then the  timer 0 counter

int timer0count;

The ISR simply increments the timer 0 counter every time Timer0 rolls over

void interrupt ISR()
{
  if (INTCONbits.TMR0IF) {
    timer0count++;
    INTCONbits.TMR0IF = 0;
    TMR0 = 0;
  }
}

This is the main() function
void main()
{
  unsigned int value = 1;
  char direction = UP;

  OSCCON = 0xF0; // set internal osc to 32Mhz
  OPTION_REG = 0x08; // Prescaler not assigned to timer 0

  TRISA0 = 0;

The next line sets the TX function on pin A0. This is important because the default is to use A4 for Tx.

  // TX function on pin A0
  TXCKSEL = 1;

Baud rate configuration. The data sheet contains tables with the settings for common values.

  // configure EUSART BAUD rate: Fosc / 64(n+1)
  BRG16 = 0;
  BRGH = 0;

The following lines configure the EUSART (extended universal serial asynchronous receiver transmitter) for Tx

  // configure the EUSART receiver
  TXEN = 1;
  SYNC = 0;
  SPEN = 1;

Clearing the analog output bit for pin A0 that we will use for Tx

  // The analog bit must be cleared for RX to function
  ANSELAbits.ANSA0 = 0;

  timer0count = 0;

Enabling the interrupts – needed for Timer 0

  INTCON = 0xC0 | 0xE0;
  INTCONbits.GIE = 1;

  while(1) {

We wait for 2000 overruns for transmitting a number. This comes out around 16 times a second.
    if (timer0count < 2000)
      continue;

    timer0count = 0;

The TRMT bit indicates whether we can write a character to the transmit register. We can write if it is set.
    if (TRMT == 0)
      continue;

Transmitting a character is done by writing it to TXREG

    TXREG = value;

Then we increase of decrease the value.
    if (direction == UP)
      value += 1;
    else
      value -= 1;
    if (value == 254)
      direction = DOWN;
    if (value == 1)
      direction = UP;
  }
}

The receiver

We will not copy the 3-digit controller again, but only point out the differences.

First the updated ISR with the new section highlighted in bold. The new section reads a character from RCREG when the RCIF flag is raised.

void interrupt ISR()
{
  if (INTCONbits.TMR0IF) {
    timer0count++;
    INTCONbits.TMR0IF = 0;
    TMR0 = 0;
  }
  if (PIR1bits.RCIF == 1) {
    if (FERR == 0)
      adcvalue = RCREG;
    if (OERR == 1) {
      overrun = 1;
    }
  }
}

Next is a new function to indicate that there is an overrun error. An overrun error occurs when a character is received before all the characters have been read from the 2 character input buffer. I decided to indicate this condition by lighting one segment on each digit. This is done by the following function:

void show_overrun_error()
{
  LATC0 = 1;
  LATC1 = 0;
  LATC2 = 0;
  LATC3 = 0;
  LATC4 = 0;
  LATC5 = 0;
  LATA4 = 0;
}

There are some changes in the main function. First we enable the EUSART receive interrupt and enable the EUSART:

// enabling EUSART rx interrupt
PIE1bits.RCIE = 1;
INTCONbits.PEIE = 1;
INTCONbits.GIE = 1;

// configure EUSART BAUD rate: Fosc / 64(n+1)
BRG16 = 0;
BRGH = 0;

// configure the EUSART receiver
CREN = 1;
SYNC = 0;
SPEN = 1;

// The analog bit must be cleared for RX to function
ANSELAbits.ANSA1 = 0;

The last change is in the switch statement that shows the digit. Here we check for an overrun and display the overrun error or the digit:

if (overrun == 1)
  show_overrun_error();
else
  show_number(digits[digit1index]);

Demo

This is how it work. The 3-digit controller is not perfect yet and the digit (especially to left most one) are flickering. But it does show the numbers correctly and will be very helpful in debugging my applications.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s