/***************************************************************************//**
 *   @file   UARTsComm.c
 *   @brief  Gestion des périphériques de communication série UART
 *   @author Kévin MARCHAND(Kevin.marchand@intelligence-electronique.com)
********************************************************************************
 * Copyright 2014(c) PLCD, Inc.
 *
 * Fonctions d'initialisation et de lecture/écriture des périphériques
 * de communication série UART.
 * Définition des UART :
 *  - <b>UART1</b> : RS232 standard +12V -12V
 *  - <b>UART2</b> : RS232 niveau TTL 3,3V
 *  - <b>UART3</b> : RS485 n°1
 *  - <b>UART4</b> : RS485 n°2
 *
********************************************************************************
 *   SVN Revision: 1
*******************************************************************************/

/******************************************************************************/
/***************************** Include Files **********************************/
/******************************************************************************/
#include <string.h>
#include "UARTsComm.h"
#include "HardwareProfile.h"
#include "uart.h"
#include "Include/TCPIPStack/Delay.h"
#include "Process.h"
#include "MODBUSTCPServer.h"

/******************************************************************************/
/************************* Define Declarations ********************************/
/******************************************************************************/
//#define MAKE_UBRG_VALUE(b) ((GetPeripheralClock()+8ul*b)/16/b-1)
#define MAKE_UBRG_VALUE(b) (((GetPeripheralClock()/b)/16)-1)
/******************************************************************************/
/************************ Variables Declarations ******************************/
/******************************************************************************/
//! Contient la valeur du registre de controle du générateur de fréquence pour le baud rate
unsigned int U1Baudvalue, U2Baudvalue, U3Baudvalue, U4Baudvalue;
//! Contient les informations du registre de configuration de l'UART 1
unsigned int U1MODEvalue;
//! Contient les informations du registre d'état et de control de l'UART 1
unsigned int U1STAvalue;
//! Contient les informations du registre de configuration de l'UART 2
unsigned int U2MODEvalue;
//! Contient les informations du registre d'état et de control de l'UART 2
unsigned int U2STAvalue;
//! Contient les informations du registre de configuration de l'UART 3
unsigned int U3MODEvalue;
//! Contient les informations du registre d'état et de control de l'UART 3
unsigned int U3STAvalue;
//! Contient les informations du registre de configuration de l'UART 4
unsigned int U4MODEvalue;
//! Contient les informations du registre d'état et de control de l'UART 4
unsigned int U4STAvalue;                

TrameUART TrameU1;
TrameUART TrameU2;
TrameUART TrameU3;
TrameUART TrameU4;

/***************************************************************************//**
 * @brief Initialise les périphériques de communication série UART.
 * Configuration par defaut : 115200 N 8 (no parity 8 bits)
 *
 * @param none.
 *
 * @return none.
*******************************************************************************/
void UARTs_Init(void)
{
    /******************** UART 1 ********************/
    CloseUART1();
    TrameU1.buffIdx = 0;
    TrameU1.Status = 0;
    memset(TrameU1.Buff, 0x00, sizeof(TrameU1.Buff));
    /* Configure UART 1 receive and transmit interrupt 1 (lowest priority) 7 (highest priority)*/
    ConfigIntUART1(UART_RX_INT_EN & UART_RX_INT_PR4 & UART_TX_INT_DIS & UART_TX_INT_PR5);
    /* Configure UART1 module to transmit 8 bit data with one stopbit */
    U1MODEvalue = UART_EN & UART_IDLE_CON & UART_IrDA_DISABLE & UART_MODE_SIMPLEX &
            UART_UEN_00 & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD &
            UART_UXRX_IDLE_ONE & UART_BRGH_SIXTEEN & UART_NO_PAR_8BIT & UART_1STOPBIT;
    U1STAvalue = UART_INT_TX_BUF_EMPTY & UART_IrDA_POL_INV_ZERO & UART_SYNC_BREAK_DISABLED &  UART_TX_ENABLE & UART_INT_RX_CHAR &
            UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;
    U1Baudvalue = MAKE_UBRG_VALUE(BR115200);
    OpenUART1(U1MODEvalue, U1STAvalue, U1Baudvalue);

    /******************** UART 2 ********************/
    CloseUART2();
    TrameU2.buffIdx = 0;
    TrameU2.Status = 0;
    memset(TrameU2.Buff, 0x00, sizeof(TrameU2.Buff));
    /* Configure UART 2 receive and transmit interrupt */
    ConfigIntUART2(UART_RX_INT_EN & UART_RX_INT_PR4 & UART_TX_INT_DIS & UART_TX_INT_PR5);
    /* Configure UART2 module to transmit 8 bit data with one stopbit */
    U2MODEvalue = UART_EN & UART_IDLE_CON & UART_IrDA_DISABLE & UART_MODE_SIMPLEX &
            UART_UEN_00 & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD &
            UART_UXRX_IDLE_ONE & UART_BRGH_SIXTEEN & UART_NO_PAR_8BIT & UART_1STOPBIT;
    U2STAvalue = UART_INT_TX_BUF_EMPTY & UART_IrDA_POL_INV_ZERO & UART_SYNC_BREAK_DISABLED &  UART_TX_ENABLE & UART_INT_RX_CHAR &
            UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;
    U2Baudvalue = MAKE_UBRG_VALUE(BR57600);
    OpenUART2(U2MODEvalue, U2STAvalue, U2Baudvalue);

    /******************** UART 3 ********************/
    CloseUART3();
    TrameU3.buffIdx = 0;
    TrameU3.Status = 0;
    memset(TrameU3.Buff, 0x00, sizeof(TrameU3.Buff));
    /* Configure UART 3 receive and transmit interrupt */
    ConfigIntUART3(UART_RX_INT_EN & UART_RX_INT_PR4 & UART_TX_INT_DIS & UART_TX_INT_PR5);
    /* Configure UART3 module to transmit 8 bit data with one stopbit */
    U3MODEvalue = UART_EN & UART_IDLE_CON & UART_IrDA_DISABLE & UART_MODE_SIMPLEX &
            UART_UEN_00 & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD &
            UART_UXRX_IDLE_ONE & UART_BRGH_SIXTEEN & UART_NO_PAR_8BIT & UART_1STOPBIT;
    U3STAvalue = UART_INT_TX_BUF_EMPTY & UART_IrDA_POL_INV_ZERO & UART_SYNC_BREAK_DISABLED &  UART_TX_ENABLE & UART_INT_RX_CHAR &
            UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;
    U3Baudvalue = MAKE_UBRG_VALUE(BR57600);
    OpenUART3(U3MODEvalue, U3STAvalue, U3Baudvalue);

    /******************** UART 4 ********************/
    CloseUART4();
    TrameU4.buffIdx = 0;
    TrameU4.Status = 0;
    memset(TrameU4.Buff, 0x00, sizeof(TrameU4.Buff));
    /* Configure UART 4 receive and transmit interrupt */
    ConfigIntUART4(UART_RX_INT_EN & UART_RX_INT_PR4 & UART_TX_INT_DIS & UART_TX_INT_PR5);
    /* Configure UART4 module to transmit 8 bit data with one stopbit */
    U4MODEvalue = UART_EN & UART_IDLE_CON & UART_IrDA_DISABLE & UART_MODE_SIMPLEX &
            UART_UEN_00 & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD &
            UART_UXRX_IDLE_ONE & UART_BRGH_SIXTEEN & UART_NO_PAR_8BIT & UART_1STOPBIT;
    U4STAvalue = UART_INT_TX_BUF_EMPTY & UART_IrDA_POL_INV_ZERO & UART_SYNC_BREAK_DISABLED &  UART_TX_ENABLE & UART_INT_RX_CHAR &
            UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;
    U4Baudvalue = MAKE_UBRG_VALUE(BR57600);
    OpenUART4(U4MODEvalue, U4STAvalue, U4Baudvalue);
}


/***************************************************************************//**
 * @brief Verifie la validité d'un Baudrate (voir UARTBaudrates).
 * @param baudrate - Baudrate à valider
 * @return BOOL - Indique si le baudrate est valide.
*******************************************************************************/
BOOL BaudrateIsValid(unsigned long baudrate)
{
switch(baudrate)
{
	case BR9600: return TRUE;
	case BR19200: return TRUE;
	case BR28800: return TRUE;
    case BR57600: return TRUE;
    case BR115200: return TRUE;
    case BR256000: return TRUE;
	default:return FALSE;
}
}

/***************************************************************************//**
 * @brief Change le Baudrate de l'UART1 si newBaudrate est valide et différent.
 * @param newBaudrate - Nouveau Baudrate (voir UARTsComm.h).
 * @return BOOL - Indique si le changement à réussi.
*******************************************************************************/
BOOL UART1_SetBaudrate(unsigned long newBaudrate)
{
if (BaudrateIsValid(newBaudrate) && MAKE_UBRG_VALUE(newBaudrate) != U1Baudvalue)
{
    U1Baudvalue = MAKE_UBRG_VALUE(newBaudrate);
    OpenUART1(U1MODEvalue, U1STAvalue, U1Baudvalue);
    return TRUE;
}
return FALSE;
}

/***************************************************************************//**
 * @brief Change le Baudrate de l'UART2 si newBaudrate est valide et différent.
 * @param newBaudrate - Nouveau Baudrate (voir UARTsComm.h).
 * @return BOOL - Indique si le changement à réussi.
*******************************************************************************/
BOOL UART2_SetBaudrate(unsigned long newBaudrate)
{
if (BaudrateIsValid(newBaudrate) && MAKE_UBRG_VALUE(newBaudrate) != U2Baudvalue)
{
    U2Baudvalue = MAKE_UBRG_VALUE(newBaudrate);
    OpenUART2(U2MODEvalue, U2STAvalue, U2Baudvalue);
    return TRUE;
}
return FALSE;
}

/***************************************************************************//**
 * @brief Change le Baudrate de l'UART3 si newBaudrate est valide et différent.
 * @param newBaudrate - Nouveau Baudrate (voir UARTsComm.h).
 * @return BOOL - Indique si le changement à réussi.
*******************************************************************************/
BOOL UART3_SetBaudrate(unsigned long newBaudrate)
{
if (BaudrateIsValid(newBaudrate) && MAKE_UBRG_VALUE(newBaudrate) != U3Baudvalue)
{
    U3Baudvalue = MAKE_UBRG_VALUE(newBaudrate);
    OpenUART3(U3MODEvalue, U3STAvalue, U3Baudvalue);
    return TRUE;
}
return FALSE;
}

/***************************************************************************//**
 * @brief Change le Baudrate de l'UART4 si newBaudrate est valide et différent.
 * @param newBaudrate - Nouveau Baudrate (voir UARTsComm.h).
 * @return BOOL - Indique si le changement à réussi.
*******************************************************************************/
BOOL UART4_SetBaudrate(unsigned long newBaudrate)
{
if (BaudrateIsValid(newBaudrate) && MAKE_UBRG_VALUE(newBaudrate) != U4Baudvalue)
{
    U4Baudvalue = MAKE_UBRG_VALUE(newBaudrate);
    OpenUART4(U4MODEvalue, U4STAvalue, U4Baudvalue);
    return TRUE;
}
return FALSE;
}

/***************************************************************************//**
 * @brief Change UART1 Stop bit (1 ou 2).
 * @param newStopBit - Nouveau StopBit (1 ou 2).
 * @return BOOL - Indique si le changement à réussi.
*******************************************************************************/
BOOL UART1_SetStopBit(unsigned int newStopBit)
{
unsigned int tmpMode = U1MODEvalue;

tmpMode |= ~UART_1STOPBIT;                                                      // Réinit bit du registre
switch(newStopBit)
{
    case 1: tmpMode = tmpMode & UART_1STOPBIT; break;
    case 2:  tmpMode = tmpMode & UART_2STOPBITS; break;
	default:return FALSE;
}
U1MODEvalue = tmpMode;
OpenUART1(U1MODEvalue, U1STAvalue, U1Baudvalue);
return TRUE;
}

/***************************************************************************//**
 * @brief Change UART2 Stop bit (1 ou 2).
 * @param newStopBit - Nouveau StopBit (1 ou 2).
 * @return BOOL - Indique si le changement à réussi.
*******************************************************************************/
BOOL UART2_SetStopBit(unsigned int newStopBit)
{
unsigned int tmpMode = U2MODEvalue;

tmpMode |= ~UART_1STOPBIT;                                                      // Réinit bit du registre
switch(newStopBit)
{
	case 1: tmpMode = tmpMode & UART_1STOPBIT; break;
	case 2:  tmpMode = tmpMode & UART_2STOPBITS; break;
	default:return FALSE;
}
U2MODEvalue = tmpMode;
OpenUART2(U2MODEvalue, U2STAvalue, U2Baudvalue);
return TRUE;
}

/***************************************************************************//**
 * @brief Change la paritée et le nombre de bits de données de UART1.
 * @param newParity - Nouvelle config (voir BIT_PARITY dans UARTsComm.h).
 * @return BOOL - Indique si le changement à réussi.
*******************************************************************************/
BOOL UART1_SetParityNBits(BIT_PARITY newParity)
{
unsigned int tmpMode = U1MODEvalue;

tmpMode |= ~UART_NO_PAR_8BIT;                                                   // Réinit bit du registre
switch(newParity)
{
	case NO_PAR_8BIT: tmpMode = tmpMode & UART_NO_PAR_8BIT; break;
	case EVEN_PAR_8BIT:  tmpMode = tmpMode & UART_EVEN_PAR_8BIT; break;
    case ODD_PAR_8BIT: tmpMode = tmpMode & UART_ODD_PAR_8BIT; break;
	case NO_PAR_9BIT:  tmpMode = tmpMode & UART_NO_PAR_9BIT; break;
	default:return FALSE;
}
U1MODEvalue = tmpMode;
OpenUART1(U1MODEvalue, U1STAvalue, U1Baudvalue);
return TRUE;
}

/***************************************************************************//**
 * @brief Change la paritée et le nombre de bits de données de UART2.
 * @param newParity - Nouvelle config (voir BIT_PARITY dans UARTsComm.h).
 * @return BOOL - Indique si le changement à réussi.
*******************************************************************************/
BOOL UART2_SetParityNBits(BIT_PARITY newParity)
{
unsigned int tmpMode = U2MODEvalue;

tmpMode |= ~UART_NO_PAR_8BIT;                                                   // Réinit bit du registre
switch(newParity)
{
	case NO_PAR_8BIT: tmpMode = tmpMode & UART_NO_PAR_8BIT; break;
	case EVEN_PAR_8BIT:  tmpMode = tmpMode & UART_EVEN_PAR_8BIT; break;
    case ODD_PAR_8BIT: tmpMode = tmpMode & UART_ODD_PAR_8BIT; break;
	case NO_PAR_9BIT:  tmpMode = tmpMode & UART_NO_PAR_9BIT; break;
	default:return FALSE;
} 
U2MODEvalue = tmpMode;
OpenUART2(U2MODEvalue, U2STAvalue, U2Baudvalue);
return TRUE;
}

/***************************************************************************//**
 * @brief Réception UART1, appelé par l'interruption RX.
 * Cette fonction assure le contrôle de la structure de la trame.
 * @param none.
 * @return none.
*******************************************************************************/
void ReceiveUART1(void)
{
unsigned int        longueurTrameTheo;
unsigned int        longueurTrame;

if (PAR.CommType[COM_RS232] == 2)                                               // Communication Intelligence Electronique
{
    if (TrameU1.buffIdx <= 2)
        return;

    if (TrameU1.Buff[TrameU1.buffIdx-1] == END_OF_FRAME)
    {
        if (TrameU1.Buff[0] == START_OF_FRAME)
        {
            memcpy(&TrameU1.Data[0],&TrameU1.Buff[1],TrameU1.buffIdx-1);
            TrameU1.Length = TrameU1.buffIdx-1;
            TrameU1.Status = 1;
            TrameU1.buffIdx = 0;
            memset(TrameU1.Buff, 0x00, sizeof(TrameU1.Buff));
        }
        else                                                                    // Erreur de trame, init buffer
        {
            TrameU1.buffIdx = 0;
            memset(TrameU1.Buff, 0x00, sizeof(TrameU1.Buff));
        }
    }
}

if ((PAR.CommType[COM_RS232] == COMM_AFFICHEUR_BASIA4)                          // Communication en Modbus
        || (PAR.CommType[COM_RS232] == COMM_PC))                                // Communication en Modbus
{
    if ((TrameU1.Buff[0] == PAR.CommNumEsclave[COM_RS232]) && TrameU1.buffIdx > 7)
    {
        longueurTrameTheo = TrameU1.Buff[6];
        longueurTrame = TrameU1.buffIdx;

        if ((TrameU1.Buff[1] == 0x10) && (longueurTrame > longueurTrameTheo+8))
        {
            memcpy(&TrameU1.Data[0],&TrameU1.Buff[0],TrameU1.buffIdx);
            TrameU1.Length = TrameU1.buffIdx-1;
            TrameU1.Status = 1;
            TrameU1.buffIdx = 0;
            memset(TrameU1.Buff, 0x00, sizeof(TrameU1.Buff));
        }

        if ((TrameU1.Buff[1] == 0x03) && (longueurTrame == 8))
        {
            memcpy(&TrameU1.Data[0],&TrameU1.Buff[0],TrameU1.buffIdx);
            TrameU1.Length = TrameU1.buffIdx-1;
            TrameU1.Status = 1;
            TrameU1.buffIdx = 0;
            memset(TrameU1.Buff, 0x00, sizeof(TrameU1.Buff));
        }
    }
}
}


/***************************************************************************//**
 * @brief Réception UART2, appelé par l'interruption RX.
 * Cette fonction assure le contrôle de la structure de la trame.
 * @param none.
 * @return none.
*******************************************************************************/
void ReceiveUART2(void)
{
unsigned int        longueurTrameTheo;
unsigned char       longueurTrameTheoChar;
unsigned int        longueurTrame;
unsigned char       longueurTrameChar;

if (PAR.CommType[COM_UART2] == 2)                                               // Communication Intelligence Electronique
{
    if (TrameU2.buffIdx <= 2)
        return;

    if (TrameU2.Buff[TrameU2.buffIdx-1] == END_OF_FRAME)
    {
        if (TrameU2.Buff[0] == START_OF_FRAME)
        {
            memcpy(&TrameU2.Data[0],&TrameU2.Buff[1],TrameU2.buffIdx-1);
            TrameU2.Length = TrameU2.buffIdx-1;
            TrameU2.Status = 1;
            TrameU2.buffIdx = 0;
            memset(TrameU2.Buff, 0x00, sizeof(TrameU2.Buff));
        }
        else                                                                    // Erreur de trame, init buffer
        {
            TrameU2.buffIdx = 0;
            memset(TrameU2.Buff, 0x00, sizeof(TrameU2.Buff));
        }
    }
}

PAR.CommType[COM_UART2] = COMM_PC;                                              // Communication avec PC PLCD en Modbus
PAR.CommNumEsclave[COM_UART2] = 1;
if (PAR.CommType[COM_UART2] == COMM_PC)                                         // Communication avec PC PLCD en Modbus
{
    if ((TrameU2.Buff[0] == PAR.CommNumEsclave[COM_UART2]) && TrameU2.buffIdx > 7)
    {
        longueurTrameTheoChar = TrameU2.Buff[6];
        longueurTrameTheo = longueurTrameTheoChar;
        longueurTrameChar = TrameU2.buffIdx;
        longueurTrame = longueurTrameChar;

        if ((TrameU2.Buff[1] == 0x10) && (longueurTrame > longueurTrameTheo+8))
        {
            memcpy(&TrameU2.Data[0],&TrameU2.Buff[0],TrameU2.buffIdx);
            TrameU2.Length = TrameU2.buffIdx-1;
            TrameU2.Status = 1;
            TrameU2.buffIdx = 0;
            memset(TrameU2.Buff, 0x00, sizeof(TrameU2.Buff));
        }

        if ((TrameU2.Buff[1] == 0x03) && (longueurTrame == 8))
        {
            memcpy(&TrameU2.Data[0],&TrameU2.Buff[0],TrameU2.buffIdx);
            TrameU2.Length = TrameU2.buffIdx-1;
            TrameU2.Status = 1;
            TrameU2.buffIdx = 0;
            memset(TrameU2.Buff, 0x00, sizeof(TrameU2.Buff));
        }
    }
}
}

/***************************************************************************//**
 * @brief Réception UART3, appelé par l'interruption RX.
 * Cette fonction assure le contrôle de la structure de la trame.
 * @param none.
 * @return none.
*******************************************************************************/
void ReceiveUART3(void)
{
unsigned int        longueurTrameTheo;
unsigned int        longueurTrame;

if (PAR.CommType[COM_RS485_1] == 2)                                             // Communication Intelligence Electronique
{
    if (TrameU3.buffIdx <= 2)
        return;

    if (TrameU3.Buff[TrameU3.buffIdx-1] == END_OF_FRAME)
    {
        if (TrameU3.Buff[0] == START_OF_FRAME)
        {
            memcpy(&TrameU3.Data[0],&TrameU3.Buff[1],TrameU3.buffIdx-1);
            TrameU3.Length = TrameU3.buffIdx-1;
            TrameU3.Status = 1;
            TrameU3.buffIdx = 0;
            memset(TrameU3.Buff, 0x00, sizeof(TrameU3.Buff));
        }
        else                                                                    // Erreur de trame, init buffer
        {
            TrameU3.buffIdx = 0;
            memset(TrameU3.Buff, 0x00, sizeof(TrameU3.Buff));
        }
    }
}

if ((PAR.CommType[COM_RS485_1] == COMM_AFFICHEUR_BASIA4)                        // Communication en Modbus
        || (PAR.CommType[COM_RS485_1] == COMM_PC))                              // Communication en Modbus
{
    if ((TrameU3.Buff[0] == PAR.CommNumEsclave[COM_RS485_1]) && TrameU3.buffIdx > 7)
    {
        longueurTrameTheo = TrameU3.Buff[6];
        longueurTrame = TrameU3.buffIdx;

        if ((TrameU3.Buff[1] == 0x10) && (longueurTrame > longueurTrameTheo+8))
        {
            memcpy(&TrameU3.Data[0],&TrameU3.Buff[0],TrameU3.buffIdx);
            TrameU3.Length = TrameU3.buffIdx-1;
            TrameU3.Status = 1;
            TrameU3.buffIdx = 0;
            memset(TrameU3.Buff, 0x00, sizeof(TrameU3.Buff));
        }

        if ((TrameU3.Buff[1] == 0x03) && (longueurTrame == 8))
        {
            memcpy(&TrameU3.Data[0],&TrameU3.Buff[0],TrameU3.buffIdx);
            TrameU3.Length = TrameU3.buffIdx-1;
            TrameU3.Status = 1;
            TrameU3.buffIdx = 0;
            memset(TrameU3.Buff, 0x00, sizeof(TrameU3.Buff));
        }
    }
}
}


/***************************************************************************//**
 * @brief Réception UART4, appelé par l'interruption RX.
 * Cette fonction assure le contrôle de la structure de la trame.
 * @param none.
 * @return none.
*******************************************************************************/
void ReceiveUART4(void)
{
unsigned int        longueurTrameTheo;
unsigned int        longueurTrame;

if (PAR.CommType[COM_RS485_2] == 2)                                             // Communication Intelligence Electronique
{
    if (TrameU4.buffIdx <= 2)
        return;

    if (TrameU4.Buff[TrameU4.buffIdx-1] == END_OF_FRAME)
    {
        if (TrameU4.Buff[0] == START_OF_FRAME)
        {
            memcpy(&TrameU4.Data[0],&TrameU4.Buff[1],TrameU4.buffIdx-1);
            TrameU4.Length = TrameU4.buffIdx-1;
            TrameU4.Status = 1;
            TrameU4.buffIdx = 0;
            memset(TrameU4.Buff, 0x00, sizeof(TrameU4.Buff));
        }
        else                                                                    // Erreur de trame, init buffer
        {
            TrameU4.buffIdx = 0;
            memset(TrameU4.Buff, 0x00, sizeof(TrameU4.Buff));
        }
    }
}

if ((PAR.CommType[COM_RS485_2] == COMM_AFFICHEUR_BASIA4)                        // Communication en Modbus
        || (PAR.CommType[COM_RS485_2] == COMM_PC))                              // Communication en Modbus
{
    if ((TrameU4.Buff[0] == PAR.CommNumEsclave[COM_RS485_2]) && TrameU4.buffIdx > 7)
    {
        longueurTrameTheo = TrameU4.Buff[6];
        longueurTrame = TrameU4.buffIdx;

        if ((TrameU4.Buff[1] == 0x10) && (longueurTrame > longueurTrameTheo+8))
        {
            memcpy(&TrameU4.Data[0],&TrameU4.Buff[0],TrameU4.buffIdx);
            TrameU4.Length = TrameU4.buffIdx-1;
            TrameU4.Status = 1;
            TrameU4.buffIdx = 0;
            memset(TrameU4.Buff, 0x00, sizeof(TrameU4.Buff));
        }

        if ((TrameU4.Buff[1] == 0x03) && (longueurTrame == 8))
        {
            memcpy(&TrameU4.Data[0],&TrameU4.Buff[0],TrameU4.buffIdx);
            TrameU4.Length = TrameU4.buffIdx-1;
            TrameU4.Status = 1;
            TrameU4.buffIdx = 0;
            memset(TrameU4.Buff, 0x00, sizeof(TrameU4.Buff));
        }
    }
}
}

/***************************************************************************//**
 * @brief Envoie la chaine de caractères à zéro terminal sur l'UART3 (RS485-1)
 * Cette fonction assure le changement de direction du bus RS485 N°1 envant l'envoi.
 * @param buff - chaine de caractères à zéro terminal à transmettre.
 * @return none.
*******************************************************************************/
void SendStrUART3(char *buff)
{
UART3TXEN_IO = 1;
Nop(); Nop(); Nop();
// Delay10us(1);
putsUART3((unsigned int *)buff);
while(BusyUART3());                                                             // Attente de la fin de la transmission
Nop(); Nop(); Nop();
//Delay10us(1);
UART3TXEN_IO = 0;
//Delay10us(1);
}

/***************************************************************************//**
 * @brief Envoie la chaine de caractères à zéro terminal sur l'UART4 (RS485-2)
 * Cette fonction assure le changement de direction du bus RS485 N°2 envant l'envoi.
 * @param buff - chaine de caractères à zéro terminal à transmettre.
 * @return none.
*******************************************************************************/
void SendStrUART4(char *buff)
{
UART4TXEN_IO = 1;
Delay10us(1);
putsUART4((unsigned int *)buff);
while(BusyUART4());                                                             // Attente de la fin de la transmission
Delay10us(1);
UART4TXEN_IO = 0;
Delay10us(1);
}
