• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC18F45k80 UART Registers

Djsarkar

Member
Hi

I have PIC18F45K80. I am using MPLABX 5.40 and XC8 2.30. I was reading the datasheet. I looked table that show required register for UART communication

1) my doubt, Does it means only timer0 will be used and other timer will not be used for UART serial communication ?

Uart inte.jpg
 

Pommie

Well-Known Member
Most Helpful Member
It says Timer1 will be used if you use asynchronous.

Edit, I don't recall any timers being used by the UARTs. I think the above is a typo.

Mike.
 
Last edited:

Djsarkar

Member
It says Timer1 will be used if you use asynchronous.

Edit, I don't recall any timers being used by the UARTs. I think the above is a typo.

Mike.
given in datasheet If using interrupts, ensure that the GIE and PEIE bits (INTCON<7:6>) are set. Only Timer0 given in INTCON register and PIR1 doesn't show bit for timer 0

I am confused How to configure INTCON and PIR1 register for UART ASYNCHRONOUS TRANSMISSION ?
 

Nigel Goodwin

Super Moderator
Most Helpful Member
given in datasheet If using interrupts, ensure that the GIE and PEIE bits (INTCON<7:6>) are set. Only Timer0 given in INTCON register and PIR1 doesn't show bit for timer 0

I am confused How to configure INTCON and PIR1 register for UART ASYNCHRONOUS TRANSMISSION ?
Use the MCC to configure it - it generates the correct code for you.

I also agree that the UART doesn't use a timer, at least not asynchronous - I've never used synchronous.
 

Djsarkar

Member
Use the MCC to configure it - it generates the correct code for you.

I also agree that the UART doesn't use a timer, at least not asynchronous - I've never used synchronous.
I am following link https://microchipdeveloper.com/mcu1101:project-12

I have reached up to step 10 but I don't get I don't get tmr1.c file

MCC UART.jpg


perhaps it may be eusart1.c file

C:
#include "eusart1.h"

/**
  Section: Macro Declarations
*/

#define EUSART1_TX_BUFFER_SIZE 8
#define EUSART1_RX_BUFFER_SIZE 8

/**
  Section: Global Variables
*/
volatile uint8_t eusart1TxHead = 0;
volatile uint8_t eusart1TxTail = 0;
volatile uint8_t eusart1TxBuffer[EUSART1_TX_BUFFER_SIZE];
volatile uint8_t eusart1TxBufferRemaining;

volatile uint8_t eusart1RxHead = 0;
volatile uint8_t eusart1RxTail = 0;
volatile uint8_t eusart1RxBuffer[EUSART1_RX_BUFFER_SIZE];
volatile eusart1_status_t eusart1RxStatusBuffer[EUSART1_RX_BUFFER_SIZE];
volatile uint8_t eusart1RxCount;
volatile eusart1_status_t eusart1RxLastError;

/**
  Section: EUSART1 APIs
*/
void (*EUSART1_TxDefaultInterruptHandler)(void);
void (*EUSART1_RxDefaultInterruptHandler)(void);

void (*EUSART1_FramingErrorHandler)(void);
void (*EUSART1_OverrunErrorHandler)(void);
void (*EUSART1_ErrorHandler)(void);

void EUSART1_DefaultFramingErrorHandler(void);
void EUSART1_DefaultOverrunErrorHandler(void);
void EUSART1_DefaultErrorHandler(void);

void EUSART1_Initialize(void)
{
    // disable interrupts before changing states
    PIE1bits.RC1IE = 0;
    EUSART1_SetRxInterruptHandler(EUSART1_Receive_ISR);
    PIE1bits.TX1IE = 0;
    EUSART1_SetTxInterruptHandler(EUSART1_Transmit_ISR);
    // Set the EUSART1 module to the options selected in the user interface.

    // ABDOVF no_overflow; TXCKP async_noninverted_sync_fallingedge; BRG16 16bit_generator; WUE disabled; ABDEN disabled; RXDTP not_inverted;
    BAUDCON1 = 0x08;

    // SPEN enabled; RX9 8-bit; RX9D 0; CREN enabled; ADDEN disabled; SREN disabled;
    RCSTA1 = 0x90;

    // TX9 8-bit; TX9D 0; SENDB sync_break_complete; TXEN enabled; SYNC asynchronous; BRGH hi_speed; CSRC slave_mode;
    TXSTA1 = 0x24;

    //
    SPBRG1 = 0xCF;

    //
    SPBRGH1 = 0x00;


    EUSART1_SetFramingErrorHandler(EUSART1_DefaultFramingErrorHandler);
    EUSART1_SetOverrunErrorHandler(EUSART1_DefaultOverrunErrorHandler);
    EUSART1_SetErrorHandler(EUSART1_DefaultErrorHandler);

    eusart1RxLastError.status = 0;

    // initializing the driver state
    eusart1TxHead = 0;
    eusart1TxTail = 0;
    eusart1TxBufferRemaining = sizeof(eusart1TxBuffer);

    eusart1RxHead = 0;
    eusart1RxTail = 0;
    eusart1RxCount = 0;

    // enable receive interrupt
    PIE1bits.RC1IE = 1;
}

bool EUSART1_is_tx_ready(void)
{
    return (eusart1TxBufferRemaining ? true : false);
}

bool EUSART1_is_rx_ready(void)
{
    return (eusart1RxCount ? true : false);
}

bool EUSART1_is_tx_done(void)
{
    return TXSTA1bits.TRMT;
}

eusart1_status_t EUSART1_get_last_status(void){
    return eusart1RxLastError;
}

uint8_t EUSART1_Read(void)
{
    uint8_t readValue  = 0;
    
    while(0 == eusart1RxCount)
    {
    }

    eusart1RxLastError = eusart1RxStatusBuffer[eusart1RxTail];

    readValue = eusart1RxBuffer[eusart1RxTail++];
    if(sizeof(eusart1RxBuffer) <= eusart1RxTail)
    {
        eusart1RxTail = 0;
    }
    PIE1bits.RC1IE = 0;
    eusart1RxCount--;
    PIE1bits.RC1IE = 1;

    return readValue;
}

void EUSART1_Write(uint8_t txData)
{
    while(0 == eusart1TxBufferRemaining)
    {
    }

    if(0 == PIE1bits.TX1IE)
    {
        TXREG1 = txData;
    }
    else
    {
        PIE1bits.TX1IE = 0;
        eusart1TxBuffer[eusart1TxHead++] = txData;
        if(sizeof(eusart1TxBuffer) <= eusart1TxHead)
        {
            eusart1TxHead = 0;
        }
        eusart1TxBufferRemaining--;
    }
    PIE1bits.TX1IE = 1;
}


void EUSART1_Transmit_ISR(void)
{

    // add your EUSART1 interrupt custom code
    if(sizeof(eusart1TxBuffer) > eusart1TxBufferRemaining)
    {
        TXREG1 = eusart1TxBuffer[eusart1TxTail++];
        if(sizeof(eusart1TxBuffer) <= eusart1TxTail)
        {
            eusart1TxTail = 0;
        }
        eusart1TxBufferRemaining++;
    }
    else
    {
        PIE1bits.TX1IE = 0;
    }
}

void EUSART1_Receive_ISR(void)
{
    
    eusart1RxStatusBuffer[eusart1RxHead].status = 0;

    if(RCSTA1bits.FERR){
        eusart1RxStatusBuffer[eusart1RxHead].ferr = 1;
        EUSART1_FramingErrorHandler();
    }

    if(RCSTA1bits.OERR){
        eusart1RxStatusBuffer[eusart1RxHead].oerr = 1;
        EUSART1_OverrunErrorHandler();
    }
    
    if(eusart1RxStatusBuffer[eusart1RxHead].status){
        EUSART1_ErrorHandler();
    } else {
        EUSART1_RxDataHandler();
    }
    
    // or set custom function using EUSART1_SetRxInterruptHandler()
}

void EUSART1_RxDataHandler(void){
    // use this default receive interrupt handler code
    eusart1RxBuffer[eusart1RxHead++] = RCREG1;
    if(sizeof(eusart1RxBuffer) <= eusart1RxHead)
    {
        eusart1RxHead = 0;
    }
    eusart1RxCount++;
}

void EUSART1_DefaultFramingErrorHandler(void){}

void EUSART1_DefaultOverrunErrorHandler(void){
    // EUSART1 error - restart

    RCSTA1bits.CREN = 0;
    RCSTA1bits.CREN = 1;

}

void EUSART1_DefaultErrorHandler(void){
    EUSART1_RxDataHandler();
}

void EUSART1_SetFramingErrorHandler(void (* interruptHandler)(void)){
    EUSART1_FramingErrorHandler = interruptHandler;
}

void EUSART1_SetOverrunErrorHandler(void (* interruptHandler)(void)){
    EUSART1_OverrunErrorHandler = interruptHandler;
}

void EUSART1_SetErrorHandler(void (* interruptHandler)(void)){
    EUSART1_ErrorHandler = interruptHandler;
}

void EUSART1_SetTxInterruptHandler(void (* interruptHandler)(void)){
    EUSART1_TxDefaultInterruptHandler = interruptHandler;
}

void EUSART1_SetRxInterruptHandler(void (* interruptHandler)(void)){
    EUSART1_RxDefaultInterruptHandler = interruptHandler;
}
/**
  End of File
*/
 

Nigel Goodwin

Super Moderator
Most Helpful Member
Last edited:

Djsarkar

Member
Why do you expect to?, you're not using a timer, and you're not configuring it.

As Pommie said, the timer1 mentioned in the webpage appears to be a typo (presumably they cut and paste from a previous tutorial, and messed up).
I have generated code but I do not understand how to modified require file because link show the different files while I have different files step 11
 

Nigel Goodwin

Super Moderator
Most Helpful Member
I have generated code but I do not understand how to modified require file because link show the different files while I have different files step 11
What files? - as we've already explained, you won't have the tmr1.c file because it's a typo - the other files are manually created, and it explains how.
 

Djsarkar

Member
What files? - as we've already explained, you won't have the tmr1.c file because it's a typo - the other files are manually created, and it explains how.
I have generated code by using MCC code configurator Next I don't have any idea How to modify original file to achieve uart communication
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
I have generated code by using MCC code configurator Next I don't have any idea How to modify original file to achieve uart communication
Why would you need to?? I do not use code cofigurator as it produces too much of a generic code..

All that's ever needed... is around 4 lines of code for the init a tiny wrapper function for send and receive...

BUT!! I always use interrupt reception, so my code probably wont help..
 

Djsarkar

Member
Here is my program when I run code I am getting garbage value on hyper terminal.

Hyper terminal settings

baud rate 9600
Data bit 8
parity none
stop bit 1


C:
#define _XTAL_FREQ 8000000
#include <xc.h>
// PIC18F45K80 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1L
#pragma config RETEN = OFF      // VREG Sleep Enable bit (Ultra low-power regulator is Disabled (Controlled by REGSLP bit))
#pragma config INTOSCSEL = HIGH // LF-INTOSC Low-power Enable bit (LF-INTOSC in High-power mode during Sleep)
#pragma config SOSCSEL = HIGH   // SOSC Power Selection and mode Configuration bits (High Power SOSC circuit selected)
#pragma config XINST = OFF       // Extended Instruction Set (Enabled)
// CONFIG1H
#pragma config FOSC = INTIO2    // Oscillator (Internal RC oscillator)
#pragma config PLLCFG = OFF     // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)
// CONFIG2L
#pragma config PWRTEN = OFF     // Power Up Timer (Disabled)
#pragma config BOREN = SBORDIS  // Brown Out Detect (Enabled in hardware, SBOREN disabled)
#pragma config BORV = 3         // Brown-out Reset Voltage bits (1.8V)
#pragma config BORPWR = ZPBORMV // BORMV Power level (ZPBORMV instead of BORMV is selected)
// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1048576  // Watchdog Postscaler (1:1048576)
// CONFIG3H
#pragma config CANMX = PORTB    // ECAN Mux bit (ECAN TX and RX pins are located on RB2 and RB3, respectively)
#pragma config MSSPMSK = MSK7   // MSSP address masking (7 Bit address masking mode)
#pragma config MCLRE = ON       // Master Clear Enable (MCLR Enabled, RE3 Disabled)
// CONFIG4L
#pragma config STVREN = ON      // Stack Overflow Reset (Enabled)
#pragma config BBSIZ = BB2K     // Boot Block Size (2K word Boot Block size)
// CONFIG5L
#pragma config CP0 = OFF        // Code Protect 00800-01FFF (Disabled)
#pragma config CP1 = OFF        // Code Protect 02000-03FFF (Disabled)
#pragma config CP2 = OFF        // Code Protect 04000-05FFF (Disabled)
#pragma config CP3 = OFF        // Code Protect 06000-07FFF (Disabled)
// CONFIG5H
#pragma config CPB = OFF        // Code Protect Boot (Disabled)
#pragma config CPD = OFF        // Data EE Read Protect (Disabled)
// CONFIG6L
#pragma config WRT0 = OFF       // Table Write Protect 00800-01FFF (Disabled)
#pragma config WRT1 = OFF       // Table Write Protect 02000-03FFF (Disabled)
#pragma config WRT2 = OFF       // Table Write Protect 04000-05FFF (Disabled)
#pragma config WRT3 = OFF       // Table Write Protect 06000-07FFF (Disabled)
// CONFIG6H
#pragma config WRTC = OFF       // Config. Write Protect (Disabled)
#pragma config WRTB = OFF       // Table Write Protect Boot (Disabled)
#pragma config WRTD = OFF       // Data EE Write Protect (Disabled)
// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protect 00800-01FFF (Disabled)
#pragma config EBTR1 = OFF      // Table Read Protect 02000-03FFF (Disabled)
#pragma config EBTR2 = OFF      // Table Read Protect 04000-05FFF (Disabled)
#pragma config EBTR3 = OFF      // Table Read Protect 06000-07FFF (Disabled)
// CONFIG7H
#pragma config EBTRB = OFF      // Table Read Protect Boot (Disabled)
void Port_Initialized (void)
{
    LATA = LATB = LATC = LATD = LATE =  0;
    TRISA = 0b0000000;// all are output, Unused
    TRISB = 0b0000000;// all are output, Unused
    TRISC = 0b1000000; // TX Pin set as output, RX Pin set as input
    TRISD = 0b0000000;//all are output, Unused
    TRISE = 0b0000000;// All are output, Unused

    ANCON0 = 0; // digital port
    ANCON1 = 0; // digital port
    CM1CON = 0; // Comparator off
    CM2CON = 0; // Comparator off
    ADCON0 = 0; // A/D conversion Disabled
}
   
void send(char message)
{
    while(TXIF==0);  // Wait till the transmitter register becomes empty
    TXREG = message;  
}
void string(char *p)
{
   while(*p != '\0') {
     send(*p);
     __delay_ms(1);
     p++;
   }
}
void Uart_Initialized(void)
{
    //TXSTAx TRANSMIT STATUS AND CONTROL REGISTER
   
   TXSTAbits.CSRC = 0; //: Don?t care.
   TXSTAbits.TX9 = 0; //Selects 8-bit transmissionbit
   TXSTAbits.TXEN = 1; // Transmit Enable
   TXSTAbits.SYNC  = 0;   // Asynchronous mode
   TXSTAbits.SENDB = 0;
   TXSTAbits.BRGH =  1;   //  High speed mode
 
   TXSTAbits.TX9D = 0;
   //RCSTAx: RECEIVE STATUS AND CONTROL REGISTER
   RCSTAbits.SPEN  = 1 ;   //Serial port enabled
   RCSTAbits.RX9 = 0; //Selects 8-bit reception
   RCSTAbits.SREN  = 1 ;//Don?t care.
   RCSTAbits.CREN  = 1 ;// Enables receiver
   RCSTAbits.ADDEN = 0; //
   RCSTAbits.FERR  = 0 ;// No framing error
   RCSTAbits.OERR  = 1 ;   // Overrun error
   RCSTAbits.RX9D   = 0 ;   //Selects 8-bit reception  
 
   SPBRG = 51;
 
}

void main(void)
{
   char message[]= {"Hello world"};
   Port_Initialized ();
   Uart_Initialized ();
   string(message);
 
    while (1)
    {
       
       
    }
}
garbaze value.jpg
 

Djsarkar

Member
I can't see where you set OSCCON.

Mike.
PIC is configured to use an internal RC oscillator

C:
#pragma config FOSC = INTIO2    // Oscillator (Internal RC oscillator)
#pragma config PLLCFG = OFF     // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)
Do i still need to configure OSCCON register ?
 

Pommie

Well-Known Member
Most Helpful Member
Do i still need to configure OSCCON register ?
On the older pics the default was 32kHz but I just checked the datasheet for the one you're using and it defaults to 8MHz.

To be sure you're running at 8MHz, try blinking an LED at 1Hz.

Mike.
Edit, you're also not waiting for the oscillator to become stable.
 

Diver300

Well-Known Member
Most Helpful Member
What do you mean by stability of an oscillator?
It can take a couple of milliseconds for a crystal oscillator to start up and become stable. There is a start-up timer in some PICs that can be enabled to prevent code from running for the first few milliseconds after start-up. Alternatively that can be done in code.

However, it won't make any difference here. If the first character were getting corrupted, then maybe look at start-up.

My suggestion would be to send one message per second as a test. You can time that against a stopwatch to check if the code is running at the speed that you expect. You also avoid any confusion of signals due to start-up or one instance of the message starting as soon as the last one has finished.

On that last point, if you are transmitting continuously (HelloWorldHelloWorldHelloWorldHelloWorld etc) the start and end of a message isn't easy to see, and we understand words and capital letters. Put it into hexadecimal and it's 48 65 6c 6c 6f 57 6f 72 6c 64. In binary with the start and stop bits it's

0 00010010 1 0 10100110 1 0 00110110 1 0 00110110 1 0 11110110 1 0 11101010 1 0 11110110 1 0 01001110 1 0 01110110 1 0 00100110 1

but without the spaces, which is what the voltage on the pin does, the start and stop bits just look like bits:-

0000100101010100110100011011010001101101011110110101110101010111101101001001110100111011010001001101

if that is just sent once, then the conditions before may not allow the receiver to see the start bit. If it is sent continually:-

0000100101010100110100011011010001101101011110110101110101010111101101001001110100111011010001001101000010010101010011010001101101000110110101111011010111010101011110110100100111010011101101000100110100001001010101001101000110110100011011010111101101011101010101111011010010011101001110110100010011010000100101010100110100011011010001101101011110110101110101010111101101001001110100111011010001001101000010010101010011010001101101000110110101111011010111010101011110110100100111010011101101000100110100001001010101001101000110110100011011010111101101011101010101111011010010011101001110110100010011010000100101010100110100011011010001101101011110110101110101010111101101001001110100111011010001001101

then it may be impossible for a receiver to work out where each character starts and stops.

If you send it with big periods of idle in between, the start becomes obvious:-
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100001001010101001101000110110100011011010111101101011101010101111011010010011101001110110100010011011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

because the data wire is high when idle, so it is like transmitting binary 1 continually.

The receiver can then start reading a character on the first transition from 1 to 0 and the data can be decoded.
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
Mike... That chip defaults to 8Mhz... BUT!! Serial transmission with the internal OSC needs tuning... The OSCTUNE register needs attention.. However!! You have selected high speed mode... Have you set the hyper terminal up to 9600 baud? Do as Mike say's (just in case) set the OSCCON to 8Mhz
 

Pommie

Well-Known Member
Most Helpful Member
I've never had a problem with RS232 and the internal oscillator. However, I always use two stop bits on the transmit end and one on receive end to prevent framing errors. Don't think that is the problem here and like Ian's suggestion of sending a string once per second to check timing.

Mike.
 

Latest threads

EE World Online Articles

Loading
Top