Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Polling based USART communication

Hayee

Member level 4
Member level 4
Joined
Mar 4, 2022
Messages
68
Helped
1
Reputation
2
Reaction score
3
Trophy points
8
Activity points
706
HI guys
I am doing USART communication between two microcontrollers, one is PIC18f46k22 and other is PIC16f883.
PIC18F46K22 is running on internal oscillator with system clock of 16Mhz. USART communication uses Asynchronous Mode with Baud Rate of 9600.
PIC16F883 is running on internal oscillator with system clock of 8Mhz. USART communication uses Asynchronous Mode with Baud Rate of 9600.
I am using MPLAB version 6.15 and Proteus for simulation purpose.

I made a simple program in which PIC18F46K22 first send a byte with a value of 1.
when PIC16F883 receive this value 1 then it will send two byte to PIC18F46k22, then according to the value receive PIC18F46K22 toggle the port pins.
Up till now the code is working fine but I am wondering when I add further stuff in my both microcontrollers then how do they behave like there should be some other routines in both microcontrollers, delays, execution time will be different. What I think they will loose data because when PIC18F46K22 send data maybe PIC16F883 will be in another loop/function and miss the data, vice-versa
What will be the possible solutions then.
I have attached both code here for your reference. Kindly take a look and tell me how I move further so that I can't loose any data.
Also guide me if I am missing something in my code which is necessary

code of PIC18F46K22
C:
#include "mcc_generated_files/mcc.h"

uint8_t dataArray[2];

void Serial_Write(uint8_t data)
{
        if(PIR1bits.TX1IF)  TXREG1 = data;    // Write the data byte to the USART.
}

void Serial_Read(void)
{
    // If Over run error occurs then clear OERR flag, disable then enable
    // the CREN flag.
    if(RCSTAbits.OERR){
        RCSTAbits.CREN = 0;
        RCSTAbits.OERR = 0;
        RCSTAbits.CREN = 1;
    }
    
    // receive the bytes here.
    for(int a = 0; a < 2; a++){
        if(PIR1bits.RCIF){
            dataArray[a] = RCREG;
        }
    }
}
void main(void)
{
    // Initialize the device like OSCILLATOR, PORTS, UART etc
    SYSTEM_Initialize();
    
    uint8_t pwmCounter = 0;
    
    ANSELB = 0x00;
    TRISBbits.TRISB0 = 0;
    TRISBbits.TRISB1 = 0;

    pwmCounter = 1;
    
    while (1)
    {
        // Add your application code
        Serial_Write(pwmCounter);
        __delay_ms(10);
        Serial_Read();
        if(dataArray[0] == 2){
            PORTBbits.RB0 = ~PORTBbits.RB0; dataArray[0] = 0;
        }
        
        if(dataArray[1] == 3){
            PORTBbits.RB1 = ~PORTBbits.RB1; dataArray[1] = 0;
        }
        
    }
}

code of PIC16F883
C:
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>

#define _XTAL_FREQ 8000000

uint8_t DataArray[2];

void Serial_Write(uint8_t* data)
{
        if(PIR1bits.TXIF){
            for (int a = 0; a < 2; a++){
                TXREG = data[a];
            }
        }
}

uint8_t Serial_Read(void)
{
    if(RCSTAbits.OERR){
        RCSTAbits.CREN = 0;
        RCSTAbits.OERR = 0;
        RCSTAbits.CREN = 1;
    }
    
    if(PIR1bits.RCIF){
        return RCREG;
    }

    return 255;
}

int main() {
    
    OSCCONbits.IRCF = 0b111; // Internal OCS with 16Mhz
    
    TRISCbits.TRISC0 = 0;
    TRISCbits.TRISC3 = 0;
    
    PORTB = 0;
    ANSELH = 0x00;

    TRISBbits.TRISB0 = 0;
    TRISBbits.TRISB2 = 0;
    TRISBbits.TRISB3 = 0;
    
    /*UART Settings*/
    BAUDCTL = 0x08;
    RCSTA = 0x90;
    TXSTA = 0x24;
    SPBRG = 0xCF;
    SPBRGH = 0x00;
            
    uint8_t counter = 0;
    
    while(1){
        DataArray[0] = 2;
        DataArray[1] = 3;
        
        counter = Serial_Read();
        if(counter == 1) Serial_Write(DataArray);
    }
}

Thanks
 
Hi,

UART = asynchron
USART = synchron

Receiver and transmitter need to work with the same(*) baud rate.
(*) Read about allowed baud rate tolerance.

What will be the possible solutions then.
9600 Buad .. means each character takes about 1ms to be transmitted. Plenty of time for processing.
We don´t know how long your tasks take, so we can not say whether this is a problem.

But for sure I would never do bidirectional UART / USART communication without interrupt in polling mode.

I mean the ISR can be very lean, just push the received byte into a software buffer.

Klaus
 
I agree fully with Klaus. Polling only works in situations where time isn't critical or you have the luxury of being able to lose data without harm being done. I might work with polling but you identified the risk of 'not being ready' when something arrives over the serial line and the risk growing as the code becomes more complex.

Changing to interrupt servicing is very easy and very reliable. This is what you do:
1. Create a variable (can even be a single bit) to signal that a character has been received
2. Write a simple interrupt routine (ISR) that reads the RCREG and stores it in a variable then sets the variable in 1.
3. Leave the ISR

In your setting up preamble, enable the USART receive interrupt bit and then the Global (GIE) bit. Now every time a character arrives it gets stored and your variable in step 1. gets set. You check that variable and read the stored character in your other code without time constraints. When you have read the character don't forget to clear your 'step 1' variable so it is ready for when the next character arrives.

If you want to be clever, inside the ISR, store incoming data in an array, keeping a pointer to the next location to use. That allows whole strings to arrive without worrying about timing and only set the variable 'step 1' when the complete string is in the array.

Caution: read the data sheet about saving certain registers at the start of your ISR code and restoring them again when it exits!

Brian.
 

LaTeX Commands Quick-Menu:

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top