Modbus RTU Communication Issue with PIC18F66K22 and XC8

109 views Asked by At

I'm currently working on a project using XC8, C, and a PIC18F66K22 as a master device for Modbus RTU communication (rs485). Despite a seemingly functional hardware setup with USART2 (TX=RG1, RX=RG2, R/T=RG3), I'm encountering issues with the code. The communication isn't working as intended, and when using a COM port toolkit for monitoring, it appears to be sending garbage data.

If anyone could provide assistance or guidance to troubleshoot this issue, I would greatly appreciate it. Thank you.

have been trying a lot.

the code:


    // PIC18F66K22 Configuration Bit Settings
    #pragma config RETEN=OFF, INTOSCSEL=HIGH, SOSCSEL=DIG, XINST=OFF, FOSC=INTIO2, PLLCFG=ON, FCMEN=OFF, IESO=OFF // Configuration word 1
    #pragma config PWRTEN=OFF, BOREN=ON, BORV=3, BORPWR=HIGH, WDTEN=SWDTDIS, WDTPS=1024 // Configuration word 2
    #pragma config RTCOSC=SOSCREF, CCP2MX=PORTC, MSSPMSK=MSK5, STVREN=ON, MCLRE=OFF // Configuration word 3
    #pragma config BBSIZ=BB1K // Configuration word 4
    #pragma config CP0=ON, CP1=ON, CP2=ON, CP3=ON, CPB=OFF, CPD=OFF // Configuration word 5
    #pragma config WRT0=OFF, WRT1=OFF, WRT2=OFF, WRT3=OFF, WRTC=ON, WRTB=OFF, WRTD=OFF // Configuration word 6
    #pragma config EBRT0=OFF, EBRT1=OFF, EBRT2=OFF, EBRT3=OFF, EBRTB=OFF // Configuration word 7
    
    #include <xc.h>   //default
    
    #define _XTAL_FREQ 64000000 // 64MHz
    //declare used funcsions:
    void InitializeSerialPort();
    void WriteModbusData(uint8_t* data, int length);
    void SendStatusRequest(uint8_t address, uint8_t* modbusData);
    uint16_t CalculateCRC(uint8_t* data, int length);
    
    void main(void)         //start main
    {
        
        InitializeSerialPort(); //set UART settings.
          __delay_ms(100); //delay for a bit
          
        while (1) //while true
        {
                uint8_t modbusData[8];   //create an array
                SendStatusRequest(0x01, modbusData);  //setting the array based on the MODBUS data sent in this case " 01 03 00 00 00 10 "
                WriteModbusData(modbusData, sizeof(modbusData));      //write the data (send).
             __delay_ms(100);  //delay after each message & repeat the process.  
        }
          
    }   //end main
    
    void InitializeSerialPort()
    {
       // Configure pins for serial communication
        TRISG2 = 1; // RX pin set as input 
        TRISG1 = 0; // TX pin set as output
        TRISG3 = 0; // R/T pin set as output
    
        // Set AN18 as digital I/O - data-sheet page 22
        ANSEL18 = 0; // RG2 needs to be done just for 18 because the ANSEL chanel is Analog Input and the rest (17 & 19) are outputs
    
        // Disable 9-bit mode
        TX92 = 0;   // Disable 9 bit sending.
        RX92 = 0;   // Disable 9 Bit reception.
    
        // Enable Asynchronous serial port
        SYNC2 = 0;  // Asynchronous mode.
        SPEN2 = 1;  // Enable serial port pins
    
        // Prepare for transmission & reception
        TXEN2 = 1;  // Enable transmission.
        CREN2 = 1;  // Enable reception
    
        // High-speed mode
        BRGH2 = 1;  //-----------------------)
        BAUDCON2 |= 0x08;   
    
        // Calculate and set SPBRG value for 9600 BPS baud rate according to the data-sheet page 332.
        const unsigned int spbrg_value = (_XTAL_FREQ / (64 * 9600)) - 1;
        
    //    BRG16: 16-Bit Baud Rate Register Enable bit
    //1 = 16-bit Baud Rate Generator – SPBRGHx and SPBRGx
    //0 = 8-bit Baud Rate Generator – SPBRGx only (Compatible mode), SPBRGHx value ignored PAGE 330
    // BRG16 = 1 (if needed, otherwise leave it as it is) 
    
         SPBRGH2 = spbrg_value & 0xFF;         // Low byte
        SPBRG2 =  (spbrg_value >> 8) & 0xFF; // High byte
        
    
    }
    void WriteModbusData(uint8_t* data, int length)
    {
        for (int i = 0; i < length; i++)
        {
            while (!TX2IF)  
            {}  //wait until transmit buffer is empty
            TXREG2 = data[i]; // Write data to transmit buffer
        }
    }
    
    void SendStatusRequest(uint8_t address, uint8_t* modbusData)
    {
        // Construct the Modbus status request message
        modbusData[0] = address; // Slave address
        modbusData[1] = 0x03; // Function code (Read Holding Registers)
        modbusData[2] = 0x00; // Starting register address (high byte)
        modbusData[3] = 0x00; // Starting register address (low byte)
        modbusData[4] = 0x00; // Quantity of registers (high byte)
        modbusData[5] = 0x0A; // Quantity of registers (low byte)  (10)
        uint16_t crc = CalculateCRC(modbusData, 6); //calculate CRC for the sent data
        modbusData[6] = (uint8_t)(crc & 0xFF); // CRC low byte
        modbusData[7] = (uint8_t)(crc >> 8); // CRC high byte
    }
    
    uint16_t CalculateCRC(uint8_t* data, int length)  //based on the CRC16 algorithm.
    {
        uint16_t crc = 0xFFFF;
        for (int i = 0; i < length; i++)
        {
            crc ^= data[i];
            for (int j = 0; j < 8; j++)
                crc = (crc & 1) ? (crc >> 1) ^ 0xA001 : crc >> 1;
        }
        return crc;
    }

I have extensively checked the hardware setup, ensuring the connections and configurations align with the specifications. I also went through the PIC18F66K22 datasheet meticulously to identify any discrepancies or missed details.

0

There are 0 answers