Reputation: 21
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