UART Register Configuration

Thread Starter

Fanfire174

Joined Mar 13, 2018
240
Good response!

Based on my test using the simulator, the code should work if the PIC is running.
Try the sim test in #18? If that works, the problem is likely hardware or your UART setup. Have you tried the terminal test procedure outlined in #14 I.e are you sure the terminal works?
I did it
elcome show in uart1 output window

In simulator you set 5mz but I have 20 MHz crystal on the board

I think something wrong with Uart setup
 

JohnInTX

Joined Jun 26, 2012
4,787
The 5 MHz is the instruction frequency which is 1/4 of the oscillator freq. which should be 20MHz. But you are right, the sim uses that number For the Stopwatch function. It won’t identify a baud rate error.
 

JohnInTX

Joined Jun 26, 2012
4,787
Looks right.

Did you try the ‘wrap’ test above? That is pull the PIC from the socket and jumper the TX and RX pins and see if characters are echoed on the terminal? That will ensure that the link is OK. From here, it looks like it should work.
 

JohnInTX

Joined Jun 26, 2012
4,787
While we're at it, you should add OERR detection and correction to the receive routine. If you don't and you get an overrun (receive a character before processing the previous one) the UART will stop raising RCIF and your program will hang.

C:
char receive()
{
  if(OERR == 1){  // reset UART on overflow error
  CREN = 0;
  CREN = 1;   
  }
   
  while(RCIF==0);  // Wait till the data is received
  return(RCREG);  // Return the received data to calling function
}
 

Thread Starter

Fanfire174

Joined Mar 13, 2018
240
While we're at it, you should add OERR detection and correction to the receive routine. If you don't and you get an overrun (receive a character before processing the previous one) the UART will stop raising RCIF and your program will hang.
Good evening JohnInTX

I can confirm there is no problem with hardware

I had one example code and I used hex file of that project and now I can receive a signal that proves there is no problem in hardware

code

C:
#include<htc.h>                //Header File
#define _XTAL_FREQ 20000000    //Device Crystal Frequency
__CONFIG(0x1F7A);             //Configuration Bits refer Datasheet

#define BAUDRATE 9600        //Set BaudRate
void main()
{
TRISC6=0;                    //Configure RC6/TX Pin as Output
RC6=0;
unsigned char a;
unsigned char msg[]=" ELECTRONICS ";    //To Send the Data Serial                                //////////////////////////////////////////////////////////////
TXSTA=0x24;                    //Set Transmit Enable Bit and High Speed Baudrate in Asynchronous Mode            ////////    SPBRG = [((_XTAL_FREQ/16)/BAUDRATE)-1]    //////////
SPBRG=0x81;                    //Load the Value of Baud Rate Generator Register                                ////////    SPBRG = [((20000000/16)/9600)-1]        //////////
TXEN=1;                        //Set Transmit Enable Bit                                                        ////////    SPBRG = 129 = 0x81                        //////////
SPEN=1;                        //Set Serial Port Enable Bit                                                    //////////////////////////////////////////////////////////////
while(1)
    {
        for(a=0;a<26;a++)
        {
        while(TXIF==0);                //RC6 Connect to Rx Pin of Serial Port//
        TXREG=msg[a];
        RC7=TXREG;
        }
    }
}
I have attached zif file of project

so it seems something wrong in uart set up, what could be wrong in my program?

still trying to correct my code
 

Attachments

Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
@Fanfire174
OK, we'll assume the hardware works - at least for the PIC transmitting to the PC.
Try this. It's a cleaned up version of your original code with a better 'send string' routine. If nothing else, you can see how that is done.
It also adds overrun recovery to the receive code - that is necessary in a PIC.
However, what you had should at least have typed out the welcome message.
Since this is the first time you've tried to receive a character, be SURE that the normal voltage on the RX pin of the PIC is a logic '1' when idle. If it is, hit a few keys on the PC and the meter should change a little indicating that the serial signal is there.
Let's see.

C:
// UART TEST CODE
// PIC16F877A

#include <xc.h>

#define _XTAL_FREQ 20000000

// BEGIN CONFIG
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
//END CONFIG

void UART_Init(void)
{
  TRISC = 0b10111111;  // you don't have to do this but it doesn't hurt
  TXSTA = 0b00100100;  // TX enabled, BRGH=1
  RCSTA = 0b10010000;  // Serial Port, Continuous Receive enabled
  SPBRG = 0x81;  // baud rate 9600

# if 0  // left for reference only - it's best to do these in bytes instead of bits
  TRISC6 = 0; // TX Pin set as output
  TRISC7 = 1; // RX Pin set as input

  SPBRG = 129;
  BRGH  = 1;
  SYNC  = 0;  // Asynchronous
  SPEN  = 1;  // Enable serial port pins

  TXEN  = 1;  // enable transmission
  CREN  = 1;  // enable reception

  TX9  = 0;  // 8-bit reception selected
  RX9  = 0;  // 8-bit reception mode selected
#endif
}

//------------------ SEND AND RECEIVE  ------------------------------

void send(char message)
{
  while(TXIF==0);  // Wait till the transmitter register becomes empty
  TXREG=message;  // load the char to be transmitted into transmit reg
}

char receive()
{
  if(OERR == 1){  // reset UART on overflow error
  CREN = 0;
  CREN = 1;
  }

  while(RCIF==0);  // Wait till the data is received
  return(RCREG);  // Return the received data to calling function
}

//--------------------- SEND STRING  ---------------------------
// Sends null-terminated ASCII string
void send_string(char *p)
{
  char c;
  while((c = *p) != '\0'){
  send(c);
  p++;
  }
}

//----------------------- SEND CRLF  ------------------------------
// Sends carriage return and line feed
void CRLF(void)
{
  send_string("\r\n");
}

//--------------------- MAIN  -----------------------------------
void main(void)
{

  char Data[] = "Welcome\n\r";
  char Data1[] = "TO YOU!";
  char message;


  UART_Init();
  CRLF();
  send_string(Data);
  send_string(Data1);

  while(1){
  message = receive(); // Receive a char from serial port
  send(message);  // Transmit the received char
  }// while
} // main
 

Attachments

Last edited:

Thread Starter

Fanfire174

Joined Mar 13, 2018
240
@Fanfire174
OK, we'll assume the hardware works - at least for the PIC transmitting to the PC.
I would test code later because I am outside I don't have a board available

I want to add one feature in your code When PC send one string to a microcontroller. LED connected to microcontroller should be turn ON

I made some changes in your code but it gives error

C:
// UART TEST CODE
// PIC16F877A
#include <xc.h>
#define _XTAL_FREQ 20000000
// BEGIN CONFIG
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
//END CONFIG
void UART_Init(void)
{
  TRISC = 0b10111111;  // you don't have to do this but it doesn't hurt
  TXSTA = 0b00100100;  // TX enabled, BRGH=1
  RCSTA = 0b10010000;  // Serial Port, Continuous Receive enabled
  SPBRG = 0x81;  // baud rate 9600
# if 0  // left for reference only - it's best to do these in bytes instead of bits
  TRISC6 = 0; // TX Pin set as output
  TRISC7 = 1; // RX Pin set as input
  SPBRG = 129;
  BRGH  = 1;
  SYNC  = 0;  // Asynchronous
  SPEN  = 1;  // Enable serial port pins
  TXEN  = 1;  // enable transmission
  CREN  = 1;  // enable reception
  TX9  = 0;  // 8-bit reception selected
  RX9  = 0;  // 8-bit reception mode selected
#endif
}
//------------------ SEND AND RECEIVE  ------------------------------
void send(char message)
{
  while(TXIF==0);  // Wait till the transmitter register becomes empty
  TXREG=message;  // load the char to be transmitted into transmit reg
}
char receive()
{
  if(OERR == 1){  // reset UART on overflow error
  CREN = 0;
  CREN = 1;
  }
  while(RCIF==0);  // Wait till the data is received
  return(RCREG);  // Return the received data to calling function
}
//--------------------- SEND STRING  ---------------------------
// Sends null-terminated ASCII string
void send_string(char *p)
{
  char c;
  while((c = *p) != '\0'){
  send(c);
  p++;
  }
}
//----------------------- SEND CRLF  ------------------------------
// Sends carriage return and line feed
void CRLF(void)
{
  send_string("\r\n");
}
//--------------------- MAIN  -----------------------------------
void main(void)
{
  char Data[] = "Welcome\n\r";
  char Data1[] = "TO YOU!";
  char message;
   TRISB2 = 0;    //  RB2 pin connected to LED
  UART_Init();
  CRLF();
  send_string(Data);
  send_string(Data1);
  while(1){
   message = receive(); // Receive a char from serial port

  if (message ==  "1")
    {
        RB2 = 1;  // LED on
    }
  else
    {
        RB2 = 0;  // LED off
    }

  send(message);  // Transmit the received char
  }// while
}
uart.c:98: error: (208) operands of "==" not same type

I think I can use hyper terminal to send data from PC to microcontroller I want to turn on LED when PC send data to microcontroller How to do this ?
 

JohnInTX

Joined Jun 26, 2012
4,787
@Fanfire174
Line 98??
In line 79 “1” is a character array. I think you mean ‘1’.

A couple of things:

Do not add things to the code until you get the original code working. That will complicate your task enormously. At this point, it is enough to add the LED to the project description. One thing that WOULD be useful is to install the LED and just turn it on by default in the IO init. That way you can at least verify that the PIC has started up out of reset:

PORTB = 0b00000100; // output a 1 to turn on the LED and make..
TRISB = 0b11111011 ; // ..RB2 an output

Do not initialize TRIS with single bit operations. Always use a full byte. There are good reasons for this which are beyond the scope of our discussion here. For now, it's enough to say that Microchip no longer recommends the practice. I know there are a lot of examples of the practice out there, even in textbooks and older datasheets but don't do it.

While we are on the subject of initialization, it is important to initialize ALL of the IO ports on the PIC, not just the ones you are currently using. You should determine starting values for ALL IO pins and write them to ALL the ports during init. The reason for this is after reset, all pins are digital or analog inputs. You do not want to have floating inputs in your system, ever. That leaves you open to a host of potential problems including breaking the chip itself. It's a common mistake that beginners make.

Are you using the PICkit to program the chip on the board using the ISCP pins? If so, it's time to fire up the MPLABX Debugger. You'll love it.

Which development board are you using? I want to pull a schematic. I might even have one laying around.

Finally, what compiler and version are you using? XC8 Ver 2.00 complains about that error but in a different way. It looks like Version 1.xx ? In that case are you getting a Warning about send_string in CRLF?

When you can, try the unmodified code I posted and see what happens.
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
I think your hardware has problems..
I ran the original code from #27 (after fixing the error) on a PICDEM 2 PLUS and it works fine.

There are 3 versions in the zip:
Rev 0: The original code as run on the PICDEM 2
Rev 1: Your LED control code modification and it also works fine.
Rev 2: Finally, I punched up the code using a switch statement to fully decode the commands as well as added some prompts to show off the string output stuff. Note the differences in the inits.

Here's the screen output from Rev 2:
Welcome
TO YOU!

Please type 1 or 0
> 1
LED is ON
> 0
LED is OFF
> 5
???
Please type 1 or 0
> 1
LED is ON
> 0
LED is OFF
> 1
LED is ON
> 0
LED is OFF
>
Have fun!
 

Attachments

Last edited:

Thread Starter

Fanfire174

Joined Mar 13, 2018
240
I think your hardware has problems..
I ran the original code from #27 (after fixing the error) on a PICDEM 2 PLUS and it works fine.
Good evening JohnInTX

You are correct. I think there was a manufacturing problem in that board I ran your code in another board same model and It's working without any problem

I have MPLAB IPE V4.15 version. I bought this board online https://www.amazon.in/Silicon-Techn...C16F877A/dp/B06XQMPLDH?tag=googinhydr18418-21 because it is low cost 7.83 USD

I have tested your code with hyper terminal if I type 1 LED become "on" and if type 0 LED become "off"

Now I am trying to add difficult things like counting of the people should be display on hyper terminal

one Pir sensor is connected to the microcontroller so when people pass from sensor. sensor becomes high then increment the value of a counter

simple logic

C:
#define PIR RB0

void main (void)
{

    TRISB=0b00000001;  // sensor is connected to RB0
  
    Counter = 0;  //initial values is zero
 
    while (1)
    {
        if(PIR == 1)
        {
           count ++;
        }
    }
}
I want to get the counter value in the hyper terminal. How to send value of counter to serial port. I want to get continuously count value of counter in hyper terminal
 

JohnInTX

Joined Jun 26, 2012
4,787
Consider the parts of the project first:
A PIR detector that outputs a 1 when seeing something and a 0 otherwise.
A counter that increments when the PIR sees a NEW something
A way to convert the counter value to ASCII text and send it to the UART.

Note how the PIR sensing has to work:
You wait to sense something i.e. wait while PIR==0
When you sense something (PIR=1)
increment the counter
convert the count to ASCII and write it to the UART.
WAIT until the PIR stops sensing that person i.e. while PIR==1
Loop and do it again.

The easiest way to convert a number to ASCII is to use the 'printf' function. printf allows you to format the output, mix text with numbers etc. It is very powerful and the most often used way to output to a terminal.

IMPORTANT:
printf works by generating the characters and writing them out to a standard output device through a function called 'putch' that is provided by the operating system. But we don't have an operating system. printf won't work because we have no OS that provides the 'putch' function. But XC8 allows you to write a putch function and if you do, it will automatically make it available to printf and you can use all of the fancy stuff that printf provides. So how do you write putch? You already did! Just rename your 'send' routine to putch and recompile. Don't forget to add the includes to your main file.
#include <stdio.h>
#include <conio.h>

Now you can use something like
int count=0;

... do the PIR stuff then:

count++;
printf("\rThe count is: %d",count);
and it will send the text and the new count to the UART as nice as you please. Note that by using just the carriage return \r at the beginning of the line, the message will appear on the same line along with the new count. Nice.

So look up printf and putch in the compiler manual and have at it. FWIW, here's the output from mine. You can also use the other string and character out functions like 'puts' too.

------PIR DETECTOR------


Count: 60
Have fun!
 
Last edited:

Thread Starter

Fanfire174

Joined Mar 13, 2018
240
Consider the parts of the project first:
A PIR detector that outputs a 1 when seeing something and a 0 otherwise.
A counter that increments when the PIR sees a NEW something
I did see a code in the previous post that shows exactly what is in your statement

I made it this program. I am struggling to send an integer value to send serial port

C:
#include <xc.h>
#include <stdio.h>
#include <conio.h>

#define _XTAL_FREQ 20000000

#define PIR RB0

// BEGIN CONFIG
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
//END CONFIG

void UART_Init(void)
{
    TRISC = 0b10111111;    // you don't have to do this but it doesn't hurt
    TXSTA = 0b00100100;    // TX enabled, BRGH=1
    RCSTA = 0b10010000;    // Serial Port, Continuous Receive enabled
    SPBRG = 0x81;          // baud rate 9600
  
# if 0  // left for reference only - it's best to do these in bytes instead of bits
    TRISC6 = 0; // TX Pin set as output
    TRISC7 = 1; // RX Pin set as input
  
    SPBRG = 129;
    BRGH  = 1;
    SYNC  = 0;    // Asynchronous
    SPEN  = 1;    // Enable serial port pins

    TXEN  = 1;    // enable transmission
    CREN  = 1;    // enable reception

    TX9   = 0;    // 8-bit reception selected
    RX9   = 0;    // 8-bit reception mode selected
#endif
}

//------------------ SEND AND RECEIVE  ------------------------------

void putch(char message)
{
    while(TXIF==0);  // Wait till the transmitter register becomes empty
    TXREG=message;   // load the char to be transmitted into transmit reg
}

char receive()
{
    if(OERR == 1){      // reset UART on overflow error
        CREN = 0;
        CREN = 1;   
    }
  
    while(RCIF==0);    // Wait till the data is received
    return(RCREG);     // Return the received data to calling function
}

//--------------------- SEND STRING  ---------------------------
// Sends null-terminated ASCII string
void send_string(char *p)
{
    char c;
    while((c = *p) != '\0'){
        putch(c);
        p++;
    }  
}

//----------------------- SEND CRLF  ------------------------------
// Sends carriage return and line feed
void CRLF(void)
{
    send_string("\r\n");
}

//--------------------- MAIN  -----------------------------------
void main(void)
{
  int Counter = 0;  //initial values is zero
  char Data[] = "Welcome\n\r";

  char message;

  TRISB=0b00000001;  // sensor is connected to RB0
  UART_Init();
  CRLF();
  send_string(Data);
       
  while(1){
      if(PIR == 1)
        {
           Counter ++;
        }
        message = receive(); // Receive a char from serial port
        putch(message);    // Transmit the received char
  }// while
} // main
 

JohnInTX

Joined Jun 26, 2012
4,787
I made it this program. I am struggling to send an integer value to send serial port
I see two things you are missing.
First, your struggle to send an integer value to the serial port will be over when you use the 'printf' function.

Second, I outlined the step by step procedure to do the whole program above:
  • You wait to sense something i.e. wait while PIR==0
  • When you sense something (PIR=1)
    • Increment the counter
    • convert the count to ASCII and write it to the UART - use 'printf' for this.
    • WAIT until the PIR stops sensing that person i.e. while PIR==1
  • Loop and do it again.
Besides not using printf, your code is missing some of those other steps. To proceed, review the steps and code them as a C program. It will only take a few lines of C to do it. If you are fuzzy on printf, read up on it. Eventually you'll want to use it everywhere.
Keep this in mind: It is common to get stuck on a missing piece of the program, in your case converting the counter to something printable (hint: printf ;) ). When that happens, just defer that part and continue with the rest. Leave a placeholder.

As a placeholder you might use something like:
send_string("I will print the count here when I figure out printf");

Write the rest of the program. When the PIR is working and that line is printing where you want the count to be, you can visit printf, write it and try it out. You'll have the working stuff to help you with the new stuff.

Give that a try. Write the PIR loop and test it. Then try printf. I bet it will work. If you need help from there, post the code and tag me.

Good luck!
EDIT: Here are the pages from XC8 Compiler User's Guide that describe printf and putch.
 

Attachments

Last edited:
Hi Fanfire174, I just started to read your problem - if you are still having problems I could send you an example of my programs in Assembler as well as in C for PIC16F877 or newer 16F877A or for actual version 16F887. I did many projects with this family some years ago.
 

Thread Starter

Fanfire174

Joined Mar 13, 2018
240
If you need help from there, post the code and tag me.
.
@JohnInTX

I tried but I couldn't complete rest of program

C:
// UART EXERCISES
// PIC16F877 or 16F877A

#include <xc.h>
#include <stdio.h>
#include <conio.h>

#define _XTAL_FREQ 20000000

// BEGIN CONFIG
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
//END CONFIG

#define PIR RB0

void UART_Init(void)
{
      TXSTA = 0b00100100;  // TX enabled, BRGH=1
      RCSTA = 0b10010000;  // Serial Port, Continuous Receive enabled
      SPBRG = 0x81;        // baud rate 9600
}

//------------------ SEND AND RECEIVE  ------------------------------
void send(char message)
{
     while(TXIF==0);  // Wait till the transmitter register becomes empty
     TXREG=message;  // load the char to be transmitted into transmit reg
}

char receive()
{
  if(OERR == 1){  // reset UART on overflow error
  CREN = 0;
  CREN = 1;
  }

  while(RCIF==0);  // Wait till the data is received
  return(RCREG);  // Return the received data to calling function
}

void main (void)
{
    TRISB = 0b00000001;  // sensor is connected to RB0
    unsigned int counter = 0;  //initial values is zero

    UART_Init();

    while (1)
    {
        if(PIR == 1)
        {
           counter ++;
           printf("\rThe count is: %d",counter);
        }
    }
}
 

JohnInTX

Joined Jun 26, 2012
4,787
Seriously?

It's all there in post #34. Three bullet points. One C statement per point.

#32 tells you what to do to get ‘printf’ working on your Curiosity HPC board (the paragraph that says IMPORTANT)
 
Last edited:
Top