uartpicmplab

how to clear RCREG in pic uart


is it possible to clear RCREG on uart in PIC?

hi

I am studying Uart data transmitter and receiver.

is it possible to clear or erase RCREG value?

first of all, I use pic16f690, mplab ide v8.84(not x ide) and Hitech-C.

And I'm using a basic example of uart data transmitter and receiver.

but I find problem.

After reading the received data, I often checked that there was some data left in REREG. So I checked that the code stopped until the rest of the RCREG was read.

This usually happens when a packet longer than I want is received (for example, when I have to receive a packet longer than 22 bytes)

As far as I know, when uart data is received, the data is stored in a register called RCREG, and RCIF is set. And I know that if RCREG is CLEAR because I read the data, RCIF becomes CLEAR.

the below code is part of the code I wrote

__CONFIG(FOSC_INTRCIO & WDTE_OFF & PWRTE_OFF & MCLRE_ON& BOREN_OFF & CP_ON & CPD_ON);
#define _XTAL_FREQ 8000000  // 8MHz crystal Frequency
#define Fcyc _XTAL_FREQ / 4 // 2MHz
#define Tcyc 1 / Fcyc       // 500ns = 0.5ms

#define BAUD_RATE 9600
#define BRG_VALUE (_XTAL_FREQ/(16*BAUD_RATE)) -1 // (8MHZ/(16*9600))-1 = 51.083333->51

unsigned int count = 0;
unsigned int flag = 0;
unsigned int overflow_bit = 0;
unsigned int header = 0;
unsigned int tail  = 20;

unsigned char received_data[21] = {0};

.
.
.
void init_ports(void){
    OSCCON = 0b01110000; //8MHz
    CM1CON0 = 0x00;
    CM2CON0 = 0x00;
    ADCON0 = 0x00;
    ANSEL = 0x00;
    ANSELH = 0x00;
    
    TRISA = 0b00000000;
    TRISB = 0b00100000; //  TRISB5 : RX | TRISB7 : TX
    TRISC = 0b00000011; // 1 : input / 0 : output
}

void init_uart(void){   
    SPBRG = 51; TX9 = 0;    TXEN = 1;   SYNC = 0;   BRGH = 1; 
    SPEN = 1;   RX9 = 0;    CREN = 1;       
    RCIF = 0;   RCIE = 0;   TXIF = 0;   TXIE = 0;
}


void init_timer2(void){
    GIE = 1;                        
    PEIE = 1;                       
    TMR2IE = 1;                     
    TMR2IF = 0;                     
    T2CON = 0b00001000;             // 1:2 postscaler, TIMER2 OFF, 1:1 prescaler 
    TMR2 = 0;
    PR2 = 99;       // Tcyc X pre X post X PR2 = 500ns X 2 X 1 X 100(0~99) = 100us 
    TMR2ON = 1; 
}



unsigned char uart_getch(void)
{
    while(!RCIF);
    RCIF = 0;
    return RCREG;
}

void uart_putch(unsigned char data)
{
    TXREG = data; //
    while(!TRMT);
}

.
.
.

void main(void){
.
.
.
    while(1){
        if(RCIF){
        int i;
        for(i=0; i<21; i++){
            count = 0;
            while(!RCIF){
                if(count >= 10){
                    break;
                }
                count ++;
                __delay_ms(1);                  
            }
            if(count >= 10){ break;}
            if(overflow_bit == 0){received_data[i] = uart_getch();}
            else{overflow_data[i] = uart_getch();}
            flag++; header = i; if(flag >21){overflow_bit = 1;}     
        }
        }
                if(header == tail){
            for(int i = 0; i<21; i++{
                RB4=1; uart_putch(received_data[i]); RB4=0;
            }
        }              
    }
}


There is no problem with receiving data less than or equal to 21 bytes in length, but if there is a data reception greater than 21 bytes in length, there is a problem.

So once I receive data longer than 21 bytes, I want to proceed with data reception up to 21 bytes, then stop receiving data, and then CLEAR the RCREG register.


Solution

  • There are a lot of issues with the code posted in this question.

    The vast majority of them involve things that a developer will learn after using Microchip controllers and development tools for few years.

    The OP of the question is just starting out and will eventually discover most of these thing on his own.

    As a push in the right direction here is my best guess at what the OP was trying to create:

    /*
     * File:     main.c
     * Author:   dan1138
     * Target:   PIC16F690
     * MPLAB:    8.92
     * Compiler: HT-Tech picc v9.83
     * 
     * Answer to StackOverflow:
     *  https://stackoverflow.com/questions/76403671/how-to-clear-rcreg-in-pic-uart
     *  
     * 
     * Description:
     *  This application will receive characters from the UART and store them in a buffer.
     *  When 20 character arrive the buffer is sent to the UART transmitter.
     *  When a delay of 10 milliseconds or longer occurs all buffered characters (from 1 to 19) are sent to the UART transmitter.
     *  A carriage return <CR> and line feed <LF> is sent after any buffer is sent.
     *  The ASCII character 0x00 <NUL> is ignored on receive.
     * 
     *                      PIC16F690
     *              +----------:_:----------+
     *    5v0 ->  1 : VDD               VSS : 20 <- GND
     *        <>  2 : RA5       PGD/AN0/RA0 : 19 <> PGD
     *        <>  3 : RA4/AN3   PGC/AN1/RA1 : 18 <> PGC
     *    VPP ->  4 : RA3/VPP       AN2/RA2 : 17 <> 
     *        <>  5 : RC5/P1A       AN4/RC0 : 16 <> 
     *        <>  6 : RC4/P1B       AN5/RC1 : 15 <> 
     *        <>  7 : RC3/P1C       P1D/RC2 : 14 <> 
     *        <>  8 : RC6               RB4 : 13 <>
     *        <>  9 : RC7           RXD/RB5 : 12 <> RXD
     *    TXD <> 10 : RB7/TXD           RB6 : 11 <>
     *              +-----------------------:
     *                       DIP-20
     *  
     *
     * Created on June 5, 2023, 9:34 PM
     */
    
    #define _XTAL_FREQ (8000000UL)  // 8MHz crystal Frequency
    #define Fcyc (_XTAL_FREQ/4UL) // 2MHz
    
    #define BAUD_RATE (9600UL)
    #define BRG_VALUE (_XTAL_FREQ/(16UL*BAUD_RATE)) -1 // (8MHZ/(16*9600))-1 = 51.083333->51
    
    #define MAX_BUFFER (20)
    #define CR (0x0D)
    #define LF (0x0A)
    
    #include "htc.h"
    
    __CONFIG(FOSC_INTRCIO & WDTE_OFF & PWRTE_OFF & MCLRE_ON & CP_OFF & CPD_OFF & BOREN_OFF & IESO_ON & FCMEN_ON);
    
    void init_ports(void){
        OSCCON = 0b01110000; //8MHz
        CM1CON0 = 0x00;
        CM2CON0 = 0x00;
        ADCON0 = 0x00;
        ANSEL = 0x00;
        ANSELH = 0x00;
        
        TRISA = 0b00000000;
        TRISB = 0b00100000; //  TRISB5 : RX | TRISB7 : TX
        TRISC = 0b00000011; // 1 : input / 0 : output
    }
    
    void init_uart(void)
    {
    #if (BRG_VALUE > 255UL)
        BRG16 = 1;
        SPBRGH = (BRG_VALUE>>8);
    #endif
        SPBRG = (BRG_VALUE & 0xFF);
        TX9 = 0;    
        TXEN = 1;   
        SYNC = 0;   
        BRGH = 1; 
        SPEN = 1;   
        RX9 = 0;    
        CREN = 1;       
        RCIF = 0;   
        RCIE = 0;   
        TXIF = 0;   
        TXIE = 0;
    }
    
    void putc (unsigned char c)
    {
        while(!TXIF);
        TXREG = c;
    }
        
    unsigned char kbhit (void)
    {
        unsigned char c;
    
        if(OERR)
        {
            c = RCREG;  /* read twice to clear FIFO */
            c = RCREG;
            CREN = 0;   /* clear overrun error */
            CREN = 1;
        }
    
        if (RCIF) c = 1;
        else      c = 0;
    
        return c;
    }
        
    unsigned char getch(void)
    {
        unsigned char c;
        
        while (!RCIF)
        {
            if(OERR)
            {
                c = RCREG;  /* read twice to clear FIFO */
                c = RCREG;
                CREN = 0;   /* clear overrun error */
                CREN = 1;
            }
        }
        
        if (FERR)
        {
            /* maybe set a flag for a character with framming error */
        }
        c = RCREG;          /* get a character from UART */
        
        return c;
    }
    
    void UART_SendBuffer(unsigned char *pBuffer)
    {
        unsigned char c;
        
        if((pBuffer != 0) && (*pBuffer != 0))
        {
            for(;;)
            {
                c = *pBuffer++;
                if(c)
                {
                    putc(c);
                }
                else
                {
                    break;
                }
            }
            putc(CR);
            putc(LF);
        }
    }
    
    unsigned char received_data[MAX_BUFFER+1];
    
    void main(void) 
    {
        unsigned char Index;
        unsigned char Timeout;
        unsigned char c;
        
        init_ports();
        init_uart();
        
        Index = 0;
        received_data[Index] = 0;
        Timeout = 20;
        
        UART_SendBuffer((unsigned char *)"PIC16F690 UART test");
        
        for(;;)
        {
            if(Timeout != 0)
            {
                if(kbhit() == 0)
                {
                    __delay_us(500);
                    Timeout--;
                }
                else
                {
                    c = getch();
                    if(c != 0)
                    {
                        received_data[Index++] = c;
                        received_data[Index] = 0;
                        Timeout = 20;
                        if(Index >= MAX_BUFFER)
                        {
                            UART_SendBuffer(received_data);
                            Index = 0;
                            received_data[Index] = 0;
                        }
                    }    
                }
            }
            else
            {
                Timeout = 20;
                UART_SendBuffer(received_data);
                Index = 0;
                received_data[Index] = 0;
            }
        }
    }
    

    The lack of verbose comments in the code is intentional. The OP will need to invest time to understand why this code works better than the original.