Hamza khalid
Hamza khalid

Reputation: 21

Pic18f47k40 EUSART setup

I am trying to implement Modbus RTU in a device that has a PIC18f47k40 MCU with baudrate of 19200.

I started by setting up eusart1 for sending and receiving. This is the code in main.c that is supposed to print an array:

    DIR_RS486_SetHigh();  // Set RS485 direction to transmit
    const char message[] = "Hello world";
    DelayUs(100);      // Short delay to allow direction to stabilize
    DIR_RS486_SetHigh();
    for (uint8_t i = 0u; i < sizeof(message)-1; i++)  // Loop to send each character
        {
        WDIFeed();
        EUSART1_Write(message[i]);  // Send each character
        }  
    DIR_RS486_SetLow();
    DelayUs(100);

This is the EUSART.c code:

/**
  EUSART1 Generated Driver File

  @Company
    Microchip Technology Inc.

  @File Name
    eusart1.c

  @Summary
    This is the generated driver implementation file for the EUSART1 driver using PIC10 / PIC12 / PIC16 / PIC18 MCUs

  @Description
    This source file provides APIs for EUSART1.
    Generation Information :
        Product Revision  :  PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.65.2
        Device            :  PIC18F47K40
        Driver Version    :  2.01
    The generated drivers are tested against the following:
        Compiler          :  XC8 1.45
        MPLAB             :  MPLAB X 4.15
*/

/*
    (c) 2018 Microchip Technology Inc. and its subsidiaries. 
    
    Subject to your compliance with these terms, you may use Microchip software and any 
    derivatives exclusively with Microchip products. It is your responsibility to comply with third party 
    license terms applicable to your use of third party software (including open source software) that 
    may accompany Microchip software.
    
    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER 
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY 
    IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS 
    FOR A PARTICULAR PURPOSE.
    
    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, 
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND 
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP 
    HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO 
    THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL 
    CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT 
    OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS 
    SOFTWARE.
*/

/**
  Section: Included Files
*/
#include "eusart1.h"
/**
  Section: Macro Declarations
*/

#define EUSART1_TX_BUFFER_SIZE 128
#define EUSART1_RX_BUFFER_SIZE 128

/**
  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 uint8_t eusart1RxCount;

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

    // ABDOVF no_overflow; SCKP Non-Inverted; BRG16 16bit_generator; WUE disabled; ABDEN disabled; 
    BAUD1CON = 0x08;

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

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

    // SP1BRGL 103; 
    SP1BRGL = 0x67;

    // SP1BRGH 0; 
    SP1BRGH = 0x00;


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

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

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

//uint8_t EUSART1_is_tx_ready(void)
//{
//    return eusart1TxBufferRemaining;
//}

//uint8_t EUSART1_is_rx_ready(void)
//{
//    return eusart1RxCount;
//}
//
//bool EUSART1_is_tx_done(void)
//{
//    return TX1STAbits.TRMT;
//}

//uint8_t EUSART1_Read(void)
//{
//    uint8_t readValue  = 0;
//    
//    while(0 == eusart1RxCount)
//    {
//    }
//
//    readValue = eusart1RxBuffer[eusart1RxTail++];
//    if(sizeof(eusart1RxBuffer) <= eusart1RxTail)
//    {
//        eusart1RxTail = 0;
//    }
//    PIE3bits.RC1IE = 0;
//    eusart1RxCount--;
//    PIE3bits.RC1IE = 1;
//
//    return readValue;
//}
// EUSART1_Write sends one byte to the EUSART transmit buffer
void EUSART1_Write(uint8_t txData)
{
    while (!PIR3bits.TX1IF);  // Wait until the transmit buffer is empty
    TX1REG = txData;          // Load the byte into the transmit register
}

//void EUSART1_Write(uint8_t txData)
//{
//     uint16_t timeout = 1000;  // Set a timeout limit
//    while(0 == eusart1TxBufferRemaining)
//    {
//        if (--timeout == 0)
//        {
//            // Handle timeout error, perhaps reset the buffer or return an error code
//            return;  // Exit the function to avoid getting stuck
//        }
//    }
//    if(0 == PIE3bits.TX1IE)
//    {
//        TX1REG = txData;
//    }
//    else
//    {   
//        PIE3bits.TX1IE = 0;
//        eusart1TxBuffer[eusart1TxHead++] = txData;
//        if(sizeof(eusart1TxBuffer) <= eusart1TxHead)
//        {
//            eusart1TxHead = 0;
//        }
//        eusart1TxBufferRemaining--;
//    }
//    PIE3bits.TX1IE = 1;
//}

char getch(void)
{
    return EUSART1_Read();
}

void putch(char txData)
{
    EUSART1_Write(txData);
}

void EUSART1_Transmit_ISR(void)
{

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

void EUSART1_Receive_ISR(void)
{
    
    if(1 == RC1STAbits.OERR)
    {
        // EUSART1 error - restart

        RC1STAbits.CREN = 0;
        RC1STAbits.CREN = 1;
    }

    // buffer overruns are ignored
    eusart1RxBuffer[eusart1RxHead++] = RC1REG;
    if(sizeof(eusart1RxBuffer) <= eusart1RxHead)
    {
        eusart1RxHead = 0;
    }
    eusart1RxCount++;
}

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

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

Most of the function definitions are commented out since I was not using these functions, I was getting an error.

This is the interrupt handler code (sometime my device gets stuck here):

void __interrupt() INTERRUPT_InterruptManagerHigh (void)
{
//   // interrupt handler
//    if(PIE3bits.BCL2IE == 1 && PIR3bits.BCL2IF == 1)
//    {
//        i2c2_driver_busCollisionISR();
//    }
//    else if(PIE3bits.SSP2IE == 1 && PIR3bits.SSP2IF == 1)
//    {
//        i2c2_driver_i2cISR();
//    }
//    else
//    {
//        //Unhandled Interrupt
//    }
    // interrupt handler
    if(PIE3bits.TX1IE == 1 && PIR3bits.TX1IF == 1)
    {
        EUSART1_TxDefaultInterruptHandler();
    }
    else if(PIE3bits.RC1IE == 1 && PIR3bits.RC1IF == 1)
    {
        EUSART1_RxDefaultInterruptHandler();
    }
    else
    {
        //Unhandled Interrupt
    }
}

I tried different functions to print hello world to the serial terminal but sometimes hello world was printed but device was getting watchdog. After uncommenting interrupt handler code the device stopped getting stuck but the serial terminal showed garbage getting printed.

Upvotes: 2

Views: 65

Answers (0)

Related Questions