Hot!PIC18F MODBUS COMMUNICATION

Author
Arsalan
Starting Member
  • Total Posts : 11
  • Reward points : 0
  • Joined: 2012/10/17 03:21:37
  • Location: 0
  • Status: offline
2017/10/29 00:32:20 (permalink)
0

PIC18F MODBUS COMMUNICATION

Hello everyone,
 
this is my first post so forgive/bear me if i am wrong, 
 
I wrote a code for MODBUS RTU SLAVE protocol for PIC18F46K22, which was working fine when i was in debug mode, data were travelling to and fro from PC SIDE MODPOLL software to PIC18F26K22 slave.
 
But when i programmed the device for standalone application, PC software gives me TIMEOUT ERROR. and if i again connect it in debug mode it again works fine.
 
any suggestion please where i am getting wrong.
 
Thanks
Regards
#1

19 Replies Related Threads

    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2017/10/30 13:53:01 (permalink)
    0
    Is your code running at all in "not-debug" mode?
    Do you have MCLR pin raised, proper power supply, proper decoupling capacitors...?

    GENOVA :D :D ! GODO
    #2
    qhb
    Superb Member
    • Total Posts : 9620
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: PIC18F MODBUS COMMUNICATION 2017/10/30 15:30:42 (permalink)
    +1 (1)
    Which pins are you using for communication?
    If they are analog capable, have you switched them to digital mode?
    (The debugger switches some pins to digital mode for its own use. That won't happen in run mode.)
     
     
     
    #3
    Arsalan
    Starting Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2012/10/17 03:21:37
    • Location: 0
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2017/10/30 22:31:01 (permalink)
    +1 (1)
    ya my rest of the code was running in "not-debug" mode.
    By the way i resolved that issue by selecting my current project as 'main project' from RUN toolbar menu which was earlier set to 'none'.
     
    But now i am facing other problem that when i program my code using PICKIT-3 at first it works and all the features including modbus communication works properly.
     
    But when i restart my project, rest of the code works fine except for rs-485 modbus and again at PC side modbpoll software it gives me TIMEOUT error.
    #4
    Arsalan
    Starting Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2012/10/17 03:21:37
    • Location: 0
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2017/10/30 22:40:36 (permalink)
    0
    i am using tx1 and rx1 RC6 and RC7 which are analog pins as well but i had disable the analog function in my main code. also i am using RE2 pin for communication direction control of MAX-485. which is also i guess i had set as digital pin.
    below is main code.
     
    static bit disp_mode,prog_mode;
    char read1,read2,read3,read4;

    OSCCON = 0b01110011; //internal osc 16 Mhz HFINTOSC

    ANSELA = 0x00; //DISABLE ANALOG CHANNELS
    TRISA = 0b00000000; //LCD DATA PINS DIRECTION = OUTPUT

    lcd = 0b00000000; //LCD DATA PINS DEFAULT VALUE

    ANSELCbits.ANSC2 = 0; //digital pins and not analog
    ANSELCbits.ANSC3 = 0; //digital pins and not analog
    ANSELCbits.ANSC4 = 0; //digital pins and not analog
    ANSELCbits.ANSC6 = 0; //digital pins and not analog TX1
    ANSELCbits.ANSC7 = 0; //digital pins and not analog RX1


    TRISCbits.TRISC4 = 1;
    TRISCbits.TRISC3 = 1;

    TRISCbits.TRISC2 = 1; // SET CAPTURE CCP1 AS INPUT PIN

    ANSELE = 0x00; //DIGITAL PINS
    ADCON0 = 0x00; //SHUT OFF ADC MODULE
    TRISE = 0b00000000; //LCD CONTROL PINS and TX_RX CONTROL PINS DIRECTION = OUTPUT

    ANSELB = 0x00;
    TRISB = 0x3C; //PINS RB2 - RB5 SELECTED AS INPUTS.
    PORTB = 0xFF; //DEFAULT VALUE OF INPUT PINS AS 1 (SINCE ACTIVE LOW INPUTS)
    WPUB = 0x3C; // enable weak pull up of corresponding input pin
    INTCON2bits.RBPU = 0; // enable weak pull up of port B;

    init_lcd();
    display_all("PCD-TFM-V2.0");
    lcdcmd(0xC2);
    display_all("PROCESS");
    eunit.ui = read_eeprom(0x01);
    tunit.ui = read_eeprom(0x02);
    deci.ui = read_eeprom(0x03);

    read1 = read_eeprom(0x04);
    read2 = read_eeprom(0x05);
    read3 = read_eeprom(0x06);
    read4 = read_eeprom(0x07);
    range_val.ui = (read1*1000)+(read2*100)+(read3*10)+read4;

    __delay_ms(200);__delay_ms(200);__delay_ms(200);

    lcdcmd(0xC2);
    display_all("CONTROL");

    k1 = read_eeprom(0x08);
    k2 = read_eeprom(0x09);
    k3 = read_eeprom(0x0A);
    k4 = read_eeprom(0x0B);
    k5 = read_eeprom(0x0C);
    K_VALUE.f = ((k1+(k2*0.1)+(k3*0.01)+(k4*0.001)+(k5*0.0001)));

    read1 = read_eeprom(0x16);
    read2 = read_eeprom(0x17);
    read3 = read_eeprom(0x18);
    read4 = read_eeprom(0x19);
    zero.ui = (read1*1000)+(read2*100)+(read3*10)+read4;

    __delay_ms(200);__delay_ms(200);__delay_ms(200);

    lcdcmd(0xC2);
    display_all("DEVICES");
    __delay_ms(200);__delay_ms(200);__delay_ms(200);

    read1 = read_eeprom(0x1A);
    read2 = read_eeprom(0x1B);
    read3 = read_eeprom(0x1C);
    read4 = read_eeprom(0x1D);
    span.ui = (read1*1000)+(read2*100)+(read3*10)+read4;

    read1 = read_eeprom(0x10);
    read2 = read_eeprom(0x11);
    read3 = read_eeprom(0x12);
    read4 = read_eeprom(0x13);
    ENTFREQ.f = (read1*1000)+(read2*100)+(read3*10)+read4;

    read1 = read_eeprom(0x28);
    read2 = read_eeprom(0x29);
    read3 = read_eeprom(0x2A);
    read4 = read_eeprom(0x2B);
    ENTFR.f = (read1*1000)+(read2*100)+(read3*10)+read4;

    sen_k.f=(ENTFR.f/ENTFREQ.f); //calculate the k-value
    eeprom_read_object(0x20, &total.f, sizeof total.f);

    lpm.f=((span.ui-zero.ui)/(float)range_val.ui);

    I2CINIT();
    init_timer0();
    init_timer1();
    init_ccp1();
    init_esuart1();

    lcdcmd(0x01);

    i=0;
    disp_mode=1;prog_mode=0;
    state=1;dp=1;kmode=0;baud_sel=4;

    database[20] = password.ub[1];database[21] = password.ub[0];
    database[54] = xtal.ub[3];database[55] = xtal.ub[2];database[56] = xtal.ub[1];database[57] = xtal.ub[0];
    database[62] = 0;database[63] = hw_version;
    database[64] = 0;database[65] = sw_version;
    rx_index=0;rx_done=0;tx_enable=0;
    ovr_bit=0;fer_bit=0;tx_rx=0;
     
    T0CONbits.TMR0ON = 1; // start timer0 for totalizer sampling
    T1CONbits.TMR1ON = 1; // start timer1 for counting timeperiod
     
    #5
    Arsalan
    Starting Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2012/10/17 03:21:37
    • Location: 0
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2017/10/30 22:49:33 (permalink)
    0
    sorry for incomplete code, below is my esuart1 initialization code
     
    void init_esuart1(void)
    {
    INTCONbits.GIE = 0; //disable global interrupt
    INTCONbits.PEIE = 0; //DISABLE PERIPHERAL INTERRUPT
    SPBRGH1 = 0x01; //HEX values for 416 for 9592~9600 baud rate
    SPBRG1 = 0xA0;
    TXSTA1bits.BRGH = 1; //high baud rates
    BAUDCON1bits.BRG16 = 1; //16-bits baud register.

    TRISCbits.TRISC6 = 1; //FOR ESUART AYSYNCHRONOUS RECEPTION AND TRANSMISSION
    TRISCbits.TRISC7 = 1;

    RCSTA1bits.SPEN = 1; //ENABLE EUSART
    TXSTA1bits.SYNC = 0; //ASYNCHRONOUS MODE

    INTCONbits.GIE = 0; //GLOBAL INTERRUPT DISABLE
    INTCONbits.PEIE = 0; //PERIPHERAL INTERRUPT DISBALE
    PIE1bits.RC1IE = 0; //RECEIVE INTERRUPT DISBALE

    RCSTA1bits.RX9 = 1; //ENABLE 9-BIT RECEPTION
    RCSTA1bits.CREN = 1; //enable reception.

    TXSTA1bits.TX9 = 1; //ENABLE 9-bit TRANSMISSION
    TXSTA1bits.TX9D = 1; //SET 9TH BIT TO 1 FOR TWO STOP BITS PURPOSE
    TXSTA1bits.TXEN = 1; //enable transmission.

    temp1 = RCREG1; //FLUSH RECEIVE REGISTER
    temp2 = RCREG1;

    INTCONbits.GIE = 1; //GLOBAL INTERRUPT DISABLE
    INTCONbits.PEIE = 1; //PERIPHERAL INTERRUPT DISBALE
    PIE1bits.RC1IE = 1; //RECEIVE INTERRUPT ENABLE
    }
    #6
    Arsalan
    Starting Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2012/10/17 03:21:37
    • Location: 0
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2017/10/30 23:34:47 (permalink)
    +1 (1)
    i have the raised the MCLR pin to VDD by using 10K resistor, power supply is also proper but i dnt knw about decoupling capacitor. i have used 0.1mfd capacitor on vdd and vss thats it.
     
    #7
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2017/10/31 02:02:39 (permalink)
    0
    good!

    GENOVA :D :D ! GODO
    #8
    Arsalan
    Starting Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2012/10/17 03:21:37
    • Location: 0
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2017/10/31 02:15:19 (permalink)
    0
    But the issue is still there as, when i am first programming (not in debug mode)my device using pickit-3, the code works fine and so as modbus communication. but when switch off the power and switch it back on, except for modbus communicaton feature rest of the code works fine. on PC side modpoll software it gives me TIMEOUT error.
     
    Please help me with this, i dnt knw whether something is wrong in my code or my programming methods are wrong.
     
    i am using MPLAB X IDE V3.5 with xc8 compiler which is in free mode.
     
    #9
    Arsalan
    Starting Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2012/10/17 03:21:37
    • Location: 0
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2017/10/31 07:30:06 (permalink)
    +1 (1)
    Okay so after 2 days i found out that after power on restart. my code or pic18f itself(i dont know) is generating receive interrupt. which was not being generated first time when i programmed it. I dont know why and how.
     
    But to solve this issue i just put a flag saying that it is initialized receive interrupt and not actual.
    and problem solved
     
    Thanks all of you guys.
    #10
    Jim Nickerson
    User 452
    • Total Posts : 5842
    • Reward points : 0
    • Joined: 2003/11/07 12:35:10
    • Location: San Diego, CA
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2017/10/31 07:41:51 (permalink)
    0
    Maybe this thread might shed some light on the startup issues http://www.microchip.com/forums/FindPost/1015683
    #11
    rotting79
    New Member
    • Total Posts : 19
    • Reward points : 0
    • Joined: 2012/04/17 17:29:08
    • Location: 0
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2018/08/20 21:47:17 (permalink)
    +1 (1)
    hey there
     
    (even when the thread in a little old) Im gonna try to contribute with some hints instead complain about some bug. Last week I just finished a little program with PIC18F26K80, I chose that one because the memory space as Im using an OLED display and no other reason, and hopefully u can find out that this hint useful - even on a PIC16 fits.
     
     
    Im communicating with a gen-set controller on MODBus RTU protocol, and as almost everything on industrial components such HMIs, PLC, etc. This gen-set controllers acts as 'slave' so u have to"ask" for some information from it as a 'master'. So the easy part is to get the UART works, set a pair of arrays, one for Transmission and the other one for Reception.
     
    #define MAX_BUFFER_SIZE_TX 0x08 
    #define MAX_BUFFER_SIZE_RX 0x40            // 64 dec.
    unsigned char PAYLOAD_MODBUS_TX [ MAX_BUFFER_SIZE_TX ];
    unsigned char PAYLOAD_MODBUS_RX [ MAX_BUFFER_SIZE_RX ];

     
    Writing the transmission array fulfilling the RTU protocol (ID, function, starting address Hi, Lo, number of points Hi, Lo, CRC Hi, Lo) which these information get it from every control manufacturer as everyone chose their own registers, and getting a response.
     
    On my library u only set the Tx Array once, as the same information u are going to get it every second. then just the Rx Array will be fill it up with the new data, at the end if the CRC (Checksum) is matching, it will display the new data.
     
    void setFrameMODBus ( unsigned char id, unsigned char functionCode,
                            unsigned char addHi, unsigned char addLo, 
                            unsigned char registerHi, unsigned char registerLo, 
                            unsigned char *ptrArrayTx )
    {
        ptrArrayTx [ 0 ] = id;
        ptrArrayTx [ 1 ] = functionCode;
        ptrArrayTx [ 2 ] = addHi;
        ptrArrayTx [ 3 ] = addLo;
        ptrArrayTx [ 4 ] = registerHi;
        ptrArrayTx [ 5 ] = registerLo;
        modBusCRC ( ptrArrayTx, WRITE_MODBUS, WRITE_MODBUS_CRC );
        } // setting frame values.

     
     

    writeModBusRegsiter ( PAYLOAD_MODBUS_TX );
    readModBusRegister ( PAYLOAD_MODBUS_RX );
     
    if ( modBusCRC ( PAYLOAD_MODBUS_RX, PAYLOAD_MODBUS_RX [ 3 ] + 3, READ_MODBUS_CRC ) )
              printfOutData ( );

     
     
     
     
    post edited by rotting79 - 2018/08/21 21:34:06

    Attached Image(s)

    #12
    SILAMBU
    New Member
    • Total Posts : 9
    • Reward points : 0
    • Joined: 2018/08/21 05:11:54
    • Location: 0
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2018/08/22 01:00:46 (permalink)
    0
    Hello Friends, Is there any code for PIC16F877a as a Modbus RTU Master to read holding register from slave.
     
    Thanks
    SILAMBU
    #13
    rotting79
    New Member
    • Total Posts : 19
    • Reward points : 0
    • Joined: 2012/04/17 17:29:08
    • Location: 0
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2018/08/22 22:05:31 (permalink)
    0
    for sure SILAMBU
     
    there is no magic on that and reading "hold register" is the easiest part of the journey, just to need to know whats the register number from the slave and your are in, do u have those registers numbers??? so  u can apply these library
     
     
    #14
    rotting79
    New Member
    • Total Posts : 19
    • Reward points : 0
    • Joined: 2012/04/17 17:29:08
    • Location: 0
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2018/08/27 19:36:23 (permalink)
    0
    well, here is a video where I explain how to apply  these piece of code
     
    https://www.youtube.com/watch?v=ppxZgfDghPI
     
    As I dont have access to upload any file, here is the fragments from them...
     
    main.c

    int main ( int argc, char** argv )
    {
    /* Set Up the uC. */
    setUp ( );

    setFrameMODBus ( slaveID, functionCode, startingAddressHi, startingAddressLo,
    numberOfRegistersHi, numberOfRegistersLo, PAYLOAD_MODBUS_TX );

    EnableInterrupt ( TMR0_INTERRUPT );
    EnableInterrupt ( GLOBAL_INTERRUPT );

    /* Forever Loop */
    while ( TRUE )
    {
    if ( INT_1000ms )
    {
    writeModBusRegsiter ( PAYLOAD_MODBUS_TX );
    readModBusRegister ( PAYLOAD_MODBUS_RX );

    if ( modBusCRC ( PAYLOAD_MODBUS_RX, PAYLOAD_MODBUS_RX [ 3 ] + 3, READ_MODBUS_CRC ) )
    printfOutData ( );

    else
    {
    printf( "shit, CRC No valid \n");
    sprintf ( OLED_VAR, "CRC NOT OK!", CLEAR );
    OLEDText ( 5, 26, OLED_VAR, SIZE_TWO, OLED_WHITE );

    OLEDUpdateDisplay ( DDGRAM_CLEAR );
    }

    INT_3 = CLEAR;
    }

    } // forever loop.

    return ( EXIT_SUCCESS );
    } // main fuction.
    [/code] 
     
     
    MODBus.h

    #define DE_RE_PIN               LATAbits . LATA0

    //#define DETECT_I2C_MODULE_PRESENT
    #define I2C_BUS_1
    //#define MODBUS_UART1
    #define MODBUS_UART2

    #define OLED_ADDRESS 0x78

    unsigned char slaveID = 0x0A;
    unsigned char functionCode = 0x03;
    unsigned char startingAddressHi = 0x04;
    unsigned char startingAddressLo = 0x00;
    unsigned char numberOfRegistersHi = 0x00;
    unsigned char numberOfRegistersLo = 0x07;
    unsigned char CRCHi = 0x06;
    unsigned char CRCLo = 0x07;


    unsigned char OLED_Text_1 [ ] = "MODBus v1.0";
    unsigned char OLED_Text_2 [ ] = "theRottingOne";

    #define MAX_BUFFER_SIZE_TX 0x08
    #define MAX_BUFFER_SIZE_RX 0x40 // 64 dec.
    unsigned char PAYLOAD_MODBUS_TX [ MAX_BUFFER_SIZE_TX ];
    unsigned char PAYLOAD_MODBUS_RX [ MAX_BUFFER_SIZE_RX ];

    unsigned char OLED_VAR [ 6 ];

    #define WRITE_MODBUS 0X06
    #define WRITE_MODBUS_CRC 0X00
    #define READ_MODBUS_CRC 0X01


    void setFrameMODBus ( unsigned char id, unsigned char functionCode,
    unsigned char addHi, unsigned char addLo,
    unsigned char registerHi, unsigned char registerLo,
    unsigned char *ptrArrayTx );
    void writeModBusRegsiter ( unsigned char *ptrArrayTx );
    void readModBusRegister ( unsigned char *ptrArrayRx );
    bit checkDataBuffer ( void );
    bit modBusCRC ( unsigned char *ptrArray, unsigned char byteCount, unsigned char crcWR );
     [/code]
     
    ModBus.c
     

    void setFrameMODBus ( unsigned char id, unsigned char functionCode,
    unsigned char addHi, unsigned char addLo,
    unsigned char registerHi, unsigned char registerLo,
    unsigned char *ptrArrayTx )
    {
    ptrArrayTx [ 0 ] = id;
    ptrArrayTx [ 1 ] = functionCode;
    ptrArrayTx [ 2 ] = addHi;
    ptrArrayTx [ 3 ] = addLo;
    ptrArrayTx [ 4 ] = registerHi;
    ptrArrayTx [ 5 ] = registerLo;

    modBusCRC ( ptrArrayTx, WRITE_MODBUS, WRITE_MODBUS_CRC );

    } // setting frame values.


    void writeModBusRegsiter ( unsigned char *ptrArrayTx )
    {
    DE_RE_PIN = HIGH; // Activating trasnmition.
    LED_0 = ON;

    for ( unsigned char i = 0; i < MAX_BUFFER_SIZE_TX; i++ ) // Transmitting 8bytes of info.
    {
    #ifdef MODBUS_UART1
    while( !TXSTA1bits . TRMT ) // While transmit shift register is full.
    ;
    TX1REG = *ptrArrayTx++; // Write the data byte to the USART.
    #endif
    #ifdef MODBUS_UART2
    while( !TXSTA2bits . TRMT ) // While transmit shift register is full.
    ;
    TX2REG = *ptrArrayTx++; // Write the data byte to the USART.
    #endif
    }

    DE_RE_PIN = LOW; // Deactivationg transmition.
    LED_0 = OFF;

    } // write 8bytes of transmition.


    void readModBusRegister ( unsigned char *ptrArrayRx )
    {
    unsigned char counter = CLEAR;
    signed char skipSearching = CLEAR;

    // The function will do the scan on the Rx pin until there is nothing in the bus.
    while ( !skipSearching )
    if ( !checkDataBuffer ( ) )
    skipSearching = SET;
    else
    {
    if ( counter < MAX_BUFFER_SIZE_RX )
    {
    #ifdef MODBUS_UART1
    *ptrArrayRx = getChUSART1 ( );
    #endif
    #ifdef MODBUS_UART2
    *ptrArrayRx = getChUSART2 ( );
    #endif
    ptrArrayRx++; // Increment the string pointer
    counter++;
    }
    else
    printf ( " MAXIMUM BUFFER SIZE REACHED\n" );

    }

    #ifdef DEBUG
    // printf ( "%d ", counter );
    printfBuffer ( PAYLOAD_MODBUS_RX );
    #endif

    } // read n bytes from the buffer.


    bit checkDataBuffer ( void )
    {
    unsigned int j = CLEAR;

    #ifdef MODBUS_UART1
    while ( ( !dataRdyUSART1 ( ) ) && ( j < 30000 ) )
    j++;

    return RC1IF;
    #endif

    #ifdef MODBUS_UART2
    while ( ( !dataRdyUSART2 ( ) ) && ( j < 30000 ) )
    j++;

    return RC2IF;
    #endif

    }


    bit modBusCRC ( unsigned char *ptrArray, unsigned char byteCount, unsigned char crcWR )
    {
    unsigned int checkSum = 0xFFFF;

    if ( crcWR == READ_MODBUS_CRC )
    {
    for ( unsigned char i = 0x01; i <= byteCount; i++ )
    {
    checkSum = checkSum ^ ( unsigned int ) ptrArray [ i ];
    for ( unsigned char j = 8; j > 0; j-- )
    if ( checkSum & 0x0001 )
    checkSum = ( checkSum >> 1 ) ^ 0xA001;
    else
    checkSum >> = 0x01;
    }

    unsigned char crcHi = checkSum;
    unsigned char crcLo = checkSum >> 0x08;

    #ifdef DEBUG
    printf( "[%d], [%d] \n", crcHi, crcLo );
    #endif

    if ( ( ptrArray [ byteCount + 1 ] == crcHi ) && ( ptrArray [ byteCount + 2 ] == crcLo ) )
    return 0x01;
    } // if CRC functions comes froma a Read command.


    if ( crcWR == WRITE_MODBUS_CRC )
    {
    for ( unsigned char i = 0x00; i < WRITE_MODBUS; i++ )
    {
    checkSum = checkSum ^ ( unsigned int ) ptrArray [ i ];
    for ( unsigned char j = 8; j > 0; j-- )
    if ( checkSum & 0x0001 )
    checkSum = ( checkSum >> 1 ) ^ 0xA001;
    else
    checkSum >> = 0x01;
    }

    ptrArray [ CRCHi ] = checkSum;
    ptrArray [ CRCLo ] = checkSum >> 0x08;

    return 0x00;
    } // if CRC functions comes froma a Write command.

    return 0;
    } // calculate and write CRC to the buffer.
      [/code]
     
     
    #15
    rotting79
    New Member
    • Total Posts : 19
    • Reward points : 0
    • Joined: 2012/04/17 17:29:08
    • Location: 0
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2018/08/27 19:54:48 (permalink)
    0
    for some reason I can't edit my previous writing and I just mess up the files, but u get the idea 
    post edited by rotting79 - 2018/08/27 19:57:50
    #16
    qhb
    Superb Member
    • Total Posts : 9620
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: PIC18F MODBUS COMMUNICATION 2018/08/27 20:57:56 (permalink)
    0
    rotting79
    well, here is a video where I explain how to apply  these piece of code
     
    https://www.youtube.com/watch?v=ppxZgfDghPI
     
    As I dont have access to upload any file, here is the fragments from them...
     
    main.c
    int main ( int argc, char** argv )
    {
    /* Set Up the uC. */
    setUp ( );

    setFrameMODBus ( slaveID, functionCode, startingAddressHi, startingAddressLo,
    numberOfRegistersHi, numberOfRegistersLo, PAYLOAD_MODBUS_TX );

    EnableInterrupt ( TMR0_INTERRUPT );
    EnableInterrupt ( GLOBAL_INTERRUPT );

    /* Forever Loop */
    while ( TRUE )
    {
    if ( INT_1000ms )
    {
    writeModBusRegsiter ( PAYLOAD_MODBUS_TX );
    readModBusRegister ( PAYLOAD_MODBUS_RX );

    if ( modBusCRC ( PAYLOAD_MODBUS_RX, PAYLOAD_MODBUS_RX [ 3 ] + 3, READ_MODBUS_CRC ) )
    printfOutData ( );

    else
    {
    printf( "shit, CRC No valid \n");
    sprintf ( OLED_VAR, "CRC NOT OK!", CLEAR );
    OLEDText ( 5, 26, OLED_VAR, SIZE_TWO, OLED_WHITE );

    OLEDUpdateDisplay ( DDGRAM_CLEAR );
    }

    INT_3 = CLEAR;
    }

    } // forever loop.

    return ( EXIT_SUCCESS );
    } // main fuction.

     
    MODBus.h
    #define DE_RE_PIN LATAbits . LATA0

    //#define DETECT_I2C_MODULE_PRESENT
    #define I2C_BUS_1
    //#define MODBUS_UART1
    #define MODBUS_UART2

    #define OLED_ADDRESS 0x78

    unsigned char slaveID = 0x0A;
    unsigned char functionCode = 0x03;
    unsigned char startingAddressHi = 0x04;
    unsigned char startingAddressLo = 0x00;
    unsigned char numberOfRegistersHi = 0x00;
    unsigned char numberOfRegistersLo = 0x07;
    unsigned char CRCHi = 0x06;
    unsigned char CRCLo = 0x07;


    unsigned char OLED_Text_1 [ ] = "MODBus v1.0";
    unsigned char OLED_Text_2 [ ] = "theRottingOne";

    #define MAX_BUFFER_SIZE_TX 0x08
    #define MAX_BUFFER_SIZE_RX 0x40 // 64 dec.
    unsigned char PAYLOAD_MODBUS_TX [ MAX_BUFFER_SIZE_TX ];
    unsigned char PAYLOAD_MODBUS_RX [ MAX_BUFFER_SIZE_RX ];

    unsigned char OLED_VAR [ 6 ];

    #define WRITE_MODBUS 0X06
    #define WRITE_MODBUS_CRC 0X00
    #define READ_MODBUS_CRC 0X01


    void setFrameMODBus ( unsigned char id, unsigned char functionCode,
    unsigned char addHi, unsigned char addLo,
    unsigned char registerHi, unsigned char registerLo,
    unsigned char *ptrArrayTx );
    void writeModBusRegsiter ( unsigned char *ptrArrayTx );
    void readModBusRegister ( unsigned char *ptrArrayRx );
    bit checkDataBuffer ( void );
    bit modBusCRC ( unsigned char *ptrArray, unsigned char byteCount, unsigned char crcWR );

     
    ModBus.c
    void setFrameMODBus ( unsigned char id, unsigned char functionCode,
    unsigned char addHi, unsigned char addLo,
    unsigned char registerHi, unsigned char registerLo,
    unsigned char *ptrArrayTx )
    {
    ptrArrayTx [ 0 ] = id;
    ptrArrayTx [ 1 ] = functionCode;
    ptrArrayTx [ 2 ] = addHi;
    ptrArrayTx [ 3 ] = addLo;
    ptrArrayTx [ 4 ] = registerHi;
    ptrArrayTx [ 5 ] = registerLo;

    modBusCRC ( ptrArrayTx, WRITE_MODBUS, WRITE_MODBUS_CRC );

    } // setting frame values.


    void writeModBusRegsiter ( unsigned char *ptrArrayTx )
    {
    DE_RE_PIN = HIGH; // Activating trasnmition.
    LED_0 = ON;

    for ( unsigned char i = 0; i < MAX_BUFFER_SIZE_TX; i++ ) // Transmitting 8bytes of info.
    {
    #ifdef MODBUS_UART1
    while( !TXSTA1bits . TRMT ) // While transmit shift register is full.
    ;
    TX1REG = *ptrArrayTx++; // Write the data byte to the USART.
    #endif
    #ifdef MODBUS_UART2
    while( !TXSTA2bits . TRMT ) // While transmit shift register is full.
    ;
    TX2REG = *ptrArrayTx++; // Write the data byte to the USART.
    #endif
    }

    DE_RE_PIN = LOW; // Deactivationg transmition.
    LED_0 = OFF;

    } // write 8bytes of transmition.


    void readModBusRegister ( unsigned char *ptrArrayRx )
    {
    unsigned char counter = CLEAR;
    signed char skipSearching = CLEAR;

    // The function will do the scan on the Rx pin until there is nothing in the bus.
    while ( !skipSearching )
    if ( !checkDataBuffer ( ) )
    skipSearching = SET;
    else
    {
    if ( counter < MAX_BUFFER_SIZE_RX )
    {
    #ifdef MODBUS_UART1
    *ptrArrayRx = getChUSART1 ( );
    #endif
    #ifdef MODBUS_UART2
    *ptrArrayRx = getChUSART2 ( );
    #endif
    ptrArrayRx++; // Increment the string pointer
    counter++;
    }
    else
    printf ( " MAXIMUM BUFFER SIZE REACHED\n" );

    }

    #ifdef DEBUG
    // printf ( "%d ", counter );
    printfBuffer ( PAYLOAD_MODBUS_RX );
    #endif

    } // read n bytes from the buffer.


    bit checkDataBuffer ( void )
    {
    unsigned int j = CLEAR;

    #ifdef MODBUS_UART1
    while ( ( !dataRdyUSART1 ( ) ) && ( j < 30000 ) )
    j++;

    return RC1IF;
    #endif

    #ifdef MODBUS_UART2
    while ( ( !dataRdyUSART2 ( ) ) && ( j < 30000 ) )
    j++;

    return RC2IF;
    #endif

    }


    bit modBusCRC ( unsigned char *ptrArray, unsigned char byteCount, unsigned char crcWR )
    {
    unsigned int checkSum = 0xFFFF;

    if ( crcWR == READ_MODBUS_CRC )
    {
    for ( unsigned char i = 0x01; i <= byteCount; i++ )
    {
    checkSum = checkSum ^ ( unsigned int ) ptrArray [ i ];
    for ( unsigned char j = 8; j > 0; j-- )
    if ( checkSum & 0x0001 )
    checkSum = ( checkSum >> 1 ) ^ 0xA001;
    else
    checkSum >> = 0x01;
    }

    unsigned char crcHi = checkSum;
    unsigned char crcLo = checkSum >> 0x08;

    #ifdef DEBUG
    printf( "[%d], [%d] \n", crcHi, crcLo );
    #endif

    if ( ( ptrArray [ byteCount + 1 ] == crcHi ) && ( ptrArray [ byteCount + 2 ] == crcLo ) )
    return 0x01;
    } // if CRC functions comes froma a Read command.


    if ( crcWR == WRITE_MODBUS_CRC )
    {
    for ( unsigned char i = 0x00; i < WRITE_MODBUS; i++ )
    {
    checkSum = checkSum ^ ( unsigned int ) ptrArray [ i ];
    for ( unsigned char j = 8; j > 0; j-- )
    if ( checkSum & 0x0001 )
    checkSum = ( checkSum >> 1 ) ^ 0xA001;
    else
    checkSum >> = 0x01;
    }

    ptrArray [ CRCHi ] = checkSum;
    ptrArray [ CRCLo ] = checkSum >> 0x08;

    return 0x00;
    } // if CRC functions comes froma a Write command.

    return 0;
    } // calculate and write CRC to the buffer.




    #17
    qhb
    Superb Member
    • Total Posts : 9620
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: PIC18F MODBUS COMMUNICATION 2018/08/27 20:59:37 (permalink)
    0
    rotting79
    for some reason I can't edit my previous writing and I just mess up the files, but u get the idea

    It's the live link in the post causing the problem. You have to "unlink" it to be able to edit the post.
    See: How to avoid errors when editing posts
     
    #18
    rotting79
    New Member
    • Total Posts : 19
    • Reward points : 0
    • Joined: 2012/04/17 17:29:08
    • Location: 0
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2018/08/29 12:28:33 (permalink)
    0
    @ qhb
     
    thanks for your help
    #19
    rotting79
    New Member
    • Total Posts : 19
    • Reward points : 0
    • Joined: 2012/04/17 17:29:08
    • Location: 0
    • Status: offline
    Re: PIC18F MODBUS COMMUNICATION 2018/08/30 21:38:08 (permalink)
    0
    hey there
     
    Here is a small video on how the PIC18F26K80 is working with two Genset controllers,  the first one from DeepSea and  the second one is from ComAp, and the modifications done toke about 2 minutes
     
    https://youtu.be/J9WQsv_28Jw
     
    #20
    Jump to:
    © 2019 APG vNext Commercial Version 4.5