Search code examples
embeddedmicrocontrolleruartpic18

Write UART on PIC18


I need help with the uart communication I am trying to implement on my Proteus simulation. I use a PIC18f4520 and I want to display on the virtual terminal the values that have been calculated by the microcontroller.

Here a snap of my design on Proteus

Right now, this is how my UART code looks like :

#define _XTAL_FREQ  20000000
#define _BAUDRATE   9600

void Configuration_ISR(void) {
    IPR1bits.TMR1IP = 1;        // TMR1 Overflow Interrupt Priority - High
    PIE1bits.TMR1IE = 1;        // TMR1 Overflow Interrupt Enable
    PIR1bits.TMR1IF = 0;        // TMR1 Overflow Interrupt Flag
                            //   0 = TMR1 register did not overflow
                            //   1 = TMR1 register overflowed (must be cleared in software)
    RCONbits.IPEN   = 1;        // Interrupt Priority High level
    INTCONbits.PEIE = 1;        // Enables all low-priority peripheral interrupts
    //INTCONbits.GIE  = 1;          // Enables all high-priority interrupts
}

void Configuration_UART(void) {
    TRISCbits.TRISC6 = 0;
    TRISCbits.TRISC7 = 1;

    SPBRG = ((_XTAL_FREQ/16)/_BAUDRATE)-1;

    //RCSTA REG
    RCSTAbits.SPEN = 1;     // enable serial port pins    
    RCSTAbits.RX9 = 0;

    //TXSTA REG
    TXSTAbits.BRGH = 1;     // fast baudrate
    TXSTAbits.SYNC = 0;     // asynchronous
    TXSTAbits.TX9 = 0;      // 8-bit transmission
    TXSTAbits.TXEN = 1;     // enble transmitter
}

void WriteByte_UART(unsigned char ch) {
    while(!PIR1bits.TXIF);  // Wait for TXIF flag Set which indicates
                            // TXREG register is empty
    TXREG = ch;             // Transmitt data to UART
}

void WriteString_UART(char *data) { 
       while(*data){ 
          WriteByte_UART(*data++); 
       }
}

unsigned char ReceiveByte_UART(void) {
    if(RCSTAbits.OERR) {
        RCSTAbits.CREN = 0;
        RCSTAbits.CREN = 1;
    }
    while(!PIR1bits.RCIF); //Wait for a byte
    return RCREG;
}

And in the main loop :

while(1) {
    WriteByte_UART('a'); // This works. I can see the As in the terminal
    WriteString_UART("Hello World !"); //Nothing displayed :(
}//end while(1)

I have tried different solution for WriteString_UART but none has worked so far.

I don't want to use printf cause it impacts other operations I'm doing with the PIC by adding delay. So I really want to make it work with WriteString_UART. In the end I would like to have someting like "Error rate is : [a value]%" on the terminal.

Thanks for your help, and please tell me if something isn't clear.


Solution

  • In your WriteByte_UART() function, try polling the TRMT bit. In particular, change:

    while(!PIR1bits.TXIF);
    

    to

    while(!TXSTA1bits.TRMT);
    

    I don't know if this is your particular issue, but there exists a race-condition due to the fact that TXIF is not immediately cleared upon loading TXREG. Another option would be to try:

    ...
    Nop();
    while(!PIR1bits.TXIF);
    ...
    

    EDIT BASED ON COMMENTS

    The issue is due to the fact that the PIC18 utilizes two different pointer types based on data memory and program memory. Try changing your declaration to void WriteString_UART(const rom char * data) and see what happens. You will need to change your WriteByte_UART() declaration as well, to void WriteByte_UART(const unsigned char ch).