0
votes

I am a beginner with PIC microcontrollers and trying to learn through tutorials and simultaneously implement a project for which I need to program a PIC microcontroller. I have tried 3 different programs for UART transmission found on various tutorials and I am still having the same issue.

When I try to transmit a string, say "abcd", I only get adadadad.... on repeat. What might be the issue? I have checked the baud rates and it is correct. I have tried introducing delay but it doesnot help. Would greatly appreciate any suggestions. The UART transmission function is part of a frequency counter program that counts the frequency when it receives an interrupt and displays it on LCD. The value displayed on LCD is also to be transmitted via UART, but first I am trying to make it work for a random string "abcd". I am using proteus for simulations. Currently using the following functions for transmitting data string:

void UART_send_char(char bt)
{
    while(!TXIF);  // hold the program till TX buffer is free
    TXREG = bt; //Load the transmitter buffer with the received value
}
void UART_send_string(char* st_pt)
        {
        while(*st_pt) //if there is a char
        UART_send_char(*st_pt++); //process it as a byte data
        }

Following is my main function:

void main() {
char op[12];                 // Display string for ascii converted long.
char opdb[12];               // double buffer to stop flicker.
unsigned long  freq = 0;     // display frequency value to use.
unsigned short blinkc=0;     // blink counter
int i,n,num;
unsigned char letter;
unsigned char test[]="abcd";

   init_ports();
   init_interrupts();

   Lcd_Init ();
   Lcd_Cmd ( _LCD_CLEAR );
   Lcd_Cmd ( _LCD_CURSOR_OFF );

   start_timer_count();

   for(;;) {

      if (update_LCD) {

         INTCON.GIE = 0;         // Disable All interrupts.
         INTCON.PEIE = 0;        // Disable All Extended interrupts.

         freq = (st_TMR1L+(st_TMR1H<<8)+(st_TMR1_ovfl<<16));//*1000;
         ltoa(freq, op, 10);

         n=ltoa(freq, opdb, 10);        // Build string in non display buffer
         memcpy(op,opdb,n);             // Copy digits
         memset(&op[n],' ',12-n);       // Blank the rest.

         LCD_Out(1,1,"FREQ:");
         LCD_Out(1,7,op);
     
        
         UART_send_string("abcd"); //<-----------TRANSMISSION FUNCTION CALLED HERE
         
         update_LCD=0;
         
         TMR1_counter=0;
         TMR0_counter=0;

         start_timer_count();
      }

      if (toggle_LED) {  // Also check for signal presence at TMR1.
         blinkc=~blinkc;
         if (blinkc==0) { setBit(PORTD,0); } else { resBit(PORTD,0); }
         toggle_LED=0;

           if (freq==0) {
              for ( i=0;i<12;i++) { op[i]=' ';}
              LCD_Out(1,7,op);
          }
      }
   }
}
1
Which PIC are you using on which board? Which serial interface library are you using? Also please show a minimal, complete, verifiable and reproducible example. We need to see all the code. Remove anything that is not really required such the LCD. Make you example minimal: just send "hello\r\n" and also tell us what you use to receive data (Maybe it is the receiver that is bugged).fpiette
What IDE and compiler do you use? Where do you initialize the serial port? Since this is an embedded application it is pretty hard for us to detect errors by only looking a piece of code. You must help us to detect the issue by providing useful information about your project and development environment. This way it could be easier to help you. also you must ensure that the receiver hardware is working as expected as @fpiette stated. Go ahead and help us to help you.Kozmotronik
Trouble is in unposted receiving code.chux - Reinstate Monica

1 Answers

0
votes

This is a complete, builds with MPLABX and XC8, application to show the PIC16F877A asynchronous UART working with the Microchip simulation tool:

/*
 * File:     main.c
 * Author:   dan1138
 * Target:   PIC16F877A
 * Compiler: XC8 v2.32
 * IDE:      MPLABX v5.50
 *
 * Created on July 21, 2021, 1:29 PM
 *
 *                         PIC16F877A
 *                 +----------:_:----------+
 *       VPP ->  1 : MCLR/VPP      PGD/RB7 : 40 <> PGD
 *           <>  2 : RA0/AN0       PGC/RB6 : 39 <> PGC
 *           <>  3 : RA1/AN1           RB5 : 38 <>
 *           <>  4 : RA2/AN2           RB4 : 37 <>
 *           <>  5 : RA3/AN3           RB3 : 36 <> 
 *           <>  6 : RA4               RB2 : 35 <> 
 *           <>  7 : RA5/AN4           RB1 : 34 <> 
 *           <>  8 : RE0/AN5           RB0 : 33 <> 
 *           <>  9 : RE1/AN6           VDD : 32 <- 5v0
 *           <> 10 : RE2/AN7           VSS : 31 <- GND
 *       5v0 -> 11 : VDD               RD7 : 30 -> 
 *       GND -> 12 : VSS               RD6 : 29 -> 
 * 20.000MHz -> 13 : OSC1              RD5 : 28 -> 
 * 20.000MHz <- 14 : OSC2              RD4 : 27 -> 
 *           <> 15 : RC0/SOSCO   RX/DT/RC7 : 26 <> 
 *           <> 16 : RC1/SOSCI   TX/CK/RC6 : 25 <> 
 *           <> 17 : RC2/CCP1          RC5 : 24 <>
 *           <> 18 : RC3/SCL       SDA/RC4 : 23 <> 
 *           <> 19 : RD0               RD3 : 22 <> 
 *           <> 20 : RD1               RD2 : 21 <> 
 *                 +-----------------------:
 *                          DIP-40
 * 
 * Description:
 * 
 *  Unit test for the UART transmit output implementation.
 *  
 *  Test runs using the MPLABX v5.50 simulator.
 * 
 *  Read the Microchip documentation about how to setup the simulator to show UART output.
 *
 */

#pragma config FOSC = HS        /* Oscillator Selection bits (HS oscillator) */
#pragma config WDTE = OFF       /* Watchdog Timer Enable bit (WDT disabled) */
#pragma config PWRTE = OFF      /* Power-up Timer Enable bit (PWRT disabled) */
#pragma config BOREN = OFF      /* Brown-out Reset Enable bit (BOR disabled) */
#pragma config LVP = OFF        /* Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming) */
#pragma config CPD = OFF        /* Data EEPROM Memory Code Protection bit (Data EEPROM code protection off) */
#pragma config WRT = OFF        /* Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control) */
#pragma config CP = OFF         /* Flash Program Memory Code Protection bit (Code protection off) */
/*
 * Include defines for target specific Special Function Registers
 */
#include <xc.h>
/*
 * Tell XC8 compiler what frequency this code sets for system oscillator
 */
#define _XTAL_FREQ 20000000UL
/*
 * function to convert unsigned long to ASCII string
 */
void ultoa(void * str, unsigned long data, unsigned char radix)
{
    char buffer[32];
    char * outstr = 0;
    unsigned char index;
    unsigned char temp;
    
    outstr = (char *)str;
    if(outstr)
    {
        if((radix > 1) && (radix <= 16))
        {
            index = 0;
            do 
            {
                temp = data % radix;
                data = data / radix;
                temp = temp + '0';
                if (temp > '9') temp = temp + ('A'-'9')-1;
                buffer[index++] = temp;
            } while (data);
            do
            {
                *outstr++ = buffer[--index];                
            } while(index);
            *outstr = 0;
        }
    }
}
/*
 * Initialize UART
 */
void UART_Init(void)
{
    /* Disable UART interrupts */
    PIE1bits.TXIE = 0;
    PIE1bits.RCIE = 0;

    /* Turn off USART module */
    RCSTA = 0; 
    TXSTA = 0;
    SPBRG = (_XTAL_FREQ/(16UL *  9600UL) - 1);
    TXSTAbits.BRGH = 1;
    RCSTAbits.CREN = 1; /* Enable continuous receive  */
    TXSTAbits.TXEN = 1; /* Enables Transmission */
    RCSTAbits.SPEN = 1; /* Enables Serial Port */
    /*
     * Flush UART receive buffer
     */
    RCREG;
    RCREG;
    RCREG;
}
/*
 * Send a character to serial interface
 */
void UART_Write(unsigned char data) {
  while(!TRMT); /* Wait for buffer to be empty */
  TXREG = data;
}
/*
 * Send a string of characters to serial interface
 */
void UART_WriteString(char *pBuffer) {
    if (pBuffer)
    {
        while(*pBuffer)
        {
            UART_Write(*pBuffer++);
        }
    }
}
/*
 * Test if character is available from serial interface
 */
unsigned char UART_Data_Ready( void )
{
  return (RCIF!=0?1:0);
}
/*
 * Read a character from serial interface
 * Returns a zero if successful.
 * Returns non-zero on framing error or overrun error.
 */
unsigned char UART_Read(void *data)
{ 
    unsigned char Result;
    char * buffer = (char *)data;
    
    Result = 0;
    
    if (PIR1bits.RCIF) 
    {
        unsigned char rxerr = 0;
        
        if (RCSTAbits.OERR) {
            rxerr = 1;
            RCSTAbits.CREN = 0; /* reset receiver */
            RCSTAbits.CREN = 1;
            RCREG;
            RCREG;
            RCREG;
        }
        
        if (RCSTAbits.FERR) {
            rxerr = 1;
            RCREG; /* Discard character with framing error */
        } 
        
        if (!rxerr) { /* No error detected during reception */
            if(buffer) *buffer = RCREG;
            Result = 1;
        }
    }
    return Result;
}
/*
 * Initialize this PIC
 */
void PIC_Init( void )
{
    /* Disable all interrupt sources */
    INTCON = 0;
    PIE1   = 0;
    PIE2   = 0;

    /*
     * Pull-ups off, INT edge low to high, WDT prescale 1:1
     * TMR0 clock edge low to high, TMR0 clock = _XTAL_FREQ/4, TMR0 prescale 1:16
     * TIMER0 will assert the overflow flag every 256*16 (4096)
     * instruction cycles, with a 20MHz oscillator this is 0.8192 milliseconds.
     */
    OPTION_REG = 0b11000011;
    
    /* Make all GPIO pins digital */
    CMCON  = 0x07;
    ADCON1 = 0x06;
}
/*
 * Main application
 */
void main(void) 
{
    char output[40];
    unsigned long Count;
    
    /*
     * Initialize application
     */
    PIC_Init();
    UART_Init();
    UART_WriteString("PIC16F877A UART test build on " __DATE__ " at " __TIME__ "\r\n");
    Count = 0;
    /*
     * Application process loop
     */
    for(;;)
    {
        ultoa(output,Count,10);
        UART_WriteString("Count: ");
        UART_WriteString(output);
        UART_WriteString("\r\n");
        Count++;
    }
    /* 
     * Keep XC8 from whining about functions not being called
     */
    UART_Data_Ready();
    UART_Read(0);
}

I would expect this to work with your Proteus environment too.

It's on you to port this code to your project.