简体   繁体   中英

UART only transmitting first and last character of string (PIC16F877A simulation through proteus)

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); } } } }

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM