+ Post New Thread
Results 1 to 19 of 19
  1. #1
    Junior Member level 3
    Points: 221, Level: 2

    Join Date
    Oct 2017
    Posts
    25
    Helped
    0 / 0
    Points
    221
    Level
    2

    PIC18F24K modbus function code 1

    Here I am trying to Interface PIC18F24k40 over modbus RTU. I am posting part of my code . The below code work with function 03 holding register . Now i i am trying same code to modified for function code 1 i. read coil register. I am getting improper modbus response error. can someone sugggest what change to be done make it work.


    Below code will work on function 3
    Code:
    
    
    Code:
    unsigned int crc_fn(unsigned char *dpacket,unsigned int len) // CRC Function(Error calcualtion)
    {
         unsigned int crc = 0xffff,poly = 0xa001;
         unsigned int i=0; 
                    
         for(i=0;i>= 1;
                       crc ^= poly;
                  }
                  else
                         crc >>= 1;
            }
         }
         return (crc); 
    } 
    
    
    
    void ChecksumCal(char No_Bytes)
      {
    
         unsigned char highbyte,lowbyte;
         unsigned short crc,thisbyte,i,shift,lastbit; /* 16 bit word values */
       
         /* compute the CRC over the first 6 chars of the message*/
    
        crc = 0xFFFF; 
    
    
        No_Bytes = No_Bytes -1;
    
         for(i=0;i<=No_Bytes;i++)
          {
            thisbyte = rxbuf[i];
             crc = crc^thisbyte;
               for(shift=1;shift<=8;shift++)
               {
               lastbit = crc&0x0001; 
               crc = (crc>>1)&0x7fff;
                  if(lastbit==0x0001) 
                    {
                      crc=crc^0xa001; 
                    }
               }
          }
         lowbyte = (crc>>8)&0xff;
         highbyte = crc & 0xff;
         crc_msb = highbyte;
         crc_lsb = lowbyte;
        
        
       } 
    
    
    
    
    void Serial_Request()
    {
         unsigned int address,crc1,crc2;
         unsigned char length,i,j=0;
        
         
        // Serial_1_Send_byte(rxbuf[0]);
        crc2=crc_fn(&rxbuf[0],6); //crc function for received protocol from request 
         __delay_ms(10); // Changed on 20.01.2017
        if((rxbuf[6]==(unsigned char)(crc2))&&(rxbuf[7]==((unsigned char)(crc2>>8))))
        {
                    
               if(rxbuf[0]==device_ID)
               {
                
                //Serial_1_Send_byte(rxbuf[0]);
                
                    if(rxbuf[1]==READ_REG)
                    {
                         address=(((unsigned int)(rxbuf[2]<<8))+((unsigned int)(rxbuf[3]))); 
                         if(rxbuf[5]>=1)
                         {
                               // changes i made  for function1, if i used i get an error.
                               length=(rxbuf[5]/8);// function code 1
                               address=0X01;// function code 1
                              // original function 3 code, if i keep below code it works fine for function 3
                              // length=(rxbuf[5]*2);// function 3
                              // address=(address*2);// function 3
    
                               ser_data[0]=device_ID;
                               ser_data[1]=rxbuf[1];
                               ser_data[2]=length;
                               
                               crc_data[0]=device_ID;
                               crc_data[1]=rxbuf[1];
                               crc_data[2]=length;
                               j=3;
                               for(i=address;i<((address+length));i++)
                              {
                                    crc_data[j++]=ser_data[i+3];
                               }
                               crc1 =crc_fn(&crc_data[0],(length+3)); //crc function for response protocol from the device
    
                               Serial_1_Send_byte(ser_data[0]);
                               Serial_1_Send_byte(rxbuf[1]);
                               Serial_1_Send_byte(ser_data[2]);
                        
                               for(i=address;i<((address+length));i++)
                               {
                                    Serial_1_Send_byte(ser_data[i+3]);
                            
                               }
                               Serial_1_Send_byte((unsigned char)crc1);
                               Serial_1_Send_byte((unsigned char)(crc1>>8));
                      
                         } 
                    } 
                __delay_ms(5); 
           }
               
         }
        index=0;
         rec_flag = 0;
       
         
    }

  2. #2
    Super Moderator
    Points: 57,531, Level: 58
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    11,705
    Helped
    2715 / 2715
    Points
    57,531
    Level
    58

    Re: PIC18F24K modbus function code 1

    Hi,

    give a detailed error description.
    What does this mean:
    I am getting improper modbus response error.
    All in all not very descriptive.
    I dont know if the problem is the master or the slave device?
    I don´t know if the code is for master or slave device?

    Klaus
    Please don´t contact me via PM, because there is no time to respond to them. Thank you.



  3. #3
    Junior Member level 3
    Points: 221, Level: 2

    Join Date
    Oct 2017
    Posts
    25
    Helped
    0 / 0
    Points
    221
    Level
    2

    Re: PIC18F24K modbus function code 1

    The master sending request for function code 3 function 03: data input given in Hex 010300000031841E i get proper response. I have modified code wit adding 2 line for function 1
    length=(rxbuf[5]/8);// function code 1
    address=0X01;// function code 1
    if i send request from master like 010100000031fdde invalid response or CRC error



  4. #4
    Super Moderator
    Points: 241,412, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    41,891
    Helped
    12754 / 12754
    Points
    241,412
    Level
    100

    Re: PIC18F24K modbus function code 1

    invalid response or CRC error
    Makes no sense. A request with invalid CRC isn't answered by the a MODBUS server at all. What do you mean by "invalid response"? An invalid response can be only send by a faulty MODBUS server. Or is the server sending an exception code like illegal data address? Holding registers (read function 3) and coils (read function 1) don't necessarily share the same address range.

    In any case, the problem is unlikely related to CRC calculation.



    •   Alt6th April 2018, 16:17

      advertising

        
       

  5. #5
    Junior Member level 3
    Points: 221, Level: 2

    Join Date
    Oct 2017
    Posts
    25
    Helped
    0 / 0
    Points
    221
    Level
    2

    Re: PIC18F24K modbus function code 1

    Click image for larger version. 

Name:	Modbus.jpg 
Views:	3 
Size:	119.4 KB 
ID:	145860
    Attachment 145861
    Click image for larger version. 

Name:	Code out.png 
Views:	4 
Size:	73.3 KB 
ID:	145858
    Click image for larger version. 

Name:	Received_respons.jpg 
Views:	2 
Size:	122.1 KB 
ID:	145859

    Here is my code. Below code work fine with function 3. But facing issue with function 1
    I have attached send request & response from slave device. The request goes well while getting response i get only 6 byte.Can some one suggest what alternation i need to do


    Serial_Request()
    Is function i am calling in interrupt. I am checking first 8 byte of messages 01 01 00 00 00 31 fd de
    rxbuf[0]= 01 //device Id always
    rxbuf[1]= 01 //Functional code
    rxbuf[2]= 00 //higher byte of start address
    rxbuf[3]= 00 //Lower byte of start address
    rxbuf[4]= 00 //higher byte of end address
    rxbuf[5]= 31 //Lower byte of end address
    rxbuf[6]= FD //CRC1
    rxbuf[7]= DE //CRC2
    First i will check CRC1 & CRC2 is Valid or not if valid
    Get rxbuf[0]= 01 match with device ID then
    rxbuf[1]= 01 match with function code
    Then calculate length assign start address & length
    Store the values & check CRC again.



    Function1: actual i am trying & working on function 3
    Code:
    unsigned int crc_fn(unsigned char *dpacket,unsigned int len) // CRC Function(Error calcualtion)
    {
     unsigned int crc = 0xffff,poly = 0xa001;
     unsigned int i=0; 
       
     for(i=0;i>= 1;
          crc ^= poly;
         }
         else
        crc >>= 1;
        }
     }
     return (crc); 
    } 
    
    
    /* Tried changes with crc function */
    
    #define READ_REG 1
    
    static const unsigned long crc16_tab[] = {
    
    0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
    
    0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
    
    0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
    
    0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
    
    0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
    
    0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
    
    0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
    
    0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
    
    0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
    
    0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
    
    0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
    
    0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
    
    0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
    
    0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
    
    0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
    
    0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
    
    0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
    
    0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
    
    0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
    
    0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
    
    0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
    
    0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
    
    0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
    
    0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
    
    0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
    
    0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
    
    0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
    
    0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
    
    0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
    
    0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
    
    0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
    
    0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
    
    };
    
    
    unsigned short crc16(char * buf, unsigned short size)
    
    {
    
    unsigned int crc = 0;
    
    while (size--)
    
    crc = (crc << 8) ^ crc16_tab[(crc >> 8) ^ * buf++];
    
    return crc;
    
    }


    Code:
    void Serial_Request()
    {
         unsigned int address,crc1,crc2;
         unsigned char length,i,j=0;
        
         
        // Serial_1_Send_byte(rxbuf[0]);
        crc2=crc_fn(&rxbuf[0],6); //crc function for received protocol from request 
         __delay_ms(10); // Changed on 20.01.2017
        if((rxbuf[6]==(unsigned char)(crc2))&&(rxbuf[7]==((unsigned char)(crc2>>8))))
        {
                    
               if(rxbuf[0]==device_ID)
               {
                
                //Serial_1_Send_byte(rxbuf[0]);
                
                    if(rxbuf[1]==READ_REG)
                    {
                         address=(((unsigned int)(rxbuf[2]<<8))+((unsigned int)(rxbuf[3]))); 
                         if(rxbuf[5]>=1)
                         {
                               // changes i made for function1, if i used i get an error.
                               length=(rxbuf[5]/8);// function code 1
                               address=0X01;// function code 1
                              // original function 3 code, if i keep below code it works fine for function 3
                               length=(rxbuf[5]*2);// function 3
                               address=(address*2);// function 3
    
                               ser_data[0]=device_ID;
                               ser_data[1]=rxbuf[1];
                               ser_data[2]=length;
                               ser_data[3]=0;
                               ser_data[4]=0;
                               ser_data[5]=0;
                               ser_data[6]=0;
                               ser_data[7]=0;
                               ser_data[8]=0;
                               ser_data[9]=0;
                               ser_data[10]=0;
                               ser_data[11]=0;
                               ser_data[12]=length;
                               ser_data[13]=0;
                               ser_data[14]=0;
                               ser_data[15]=0;
                               ser_data[16]=0;
                               ser_data[17]=0;
                               ser_data[18]=0;
                               ser_data[19]=0;
                               ser_data[20]=0;
                               ser_data[21]=0;
    
    
    
    
                               
                               crc_data[0]=device_ID;
                               crc_data[1]=rxbuf[1];
                               crc_data[2]=length;
                               j=3;
                               for(i=address;i<((address+length));i++)
                              {
                                    crc_data[j++]=ser_data[i+3];
                               }
                               crc1 =crc_fn(&crc_data[0],(length+3)); //crc function for response protocol from the device
    
                               Serial_1_Send_byte(ser_data[0]);
                               Serial_1_Send_byte(rxbuf[1]);
                               Serial_1_Send_byte(ser_data[2]);
                        
                               for(i=address;i<((address+length));i++)
                               {
                                    Serial_1_Send_byte(ser_data[i+3]);
                            
                               }
                               Serial_1_Send_byte((unsigned char)crc1);
                               Serial_1_Send_byte((unsigned char)(crc1>>8));
                      
                         } 
                    } 
                __delay_ms(5); 
           }
               
         }
        index=0;
         rec_flag = 0;
       
         
    }
    Last edited by KlausST; 7th April 2018 at 07:59. Reason: corrected tags



  6. #6
    Super Moderator
    Points: 241,412, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    41,891
    Helped
    12754 / 12754
    Points
    241,412
    Level
    100

    Re: PIC18F24K modbus function code 1

    I didn't understand the question correctly, you are asking about server not client code.

    Your function 1 response has incorrect format. Length information is byte rather than bit count, review the MODBUS specification. The Tester is expecting a different response length and thus seeing CRC error.

    See Fct1 format below (without device ID and CRC)

    Click image for larger version. 

Name:	fct1.PNG 
Views:	4 
Size:	42.9 KB 
ID:	145864



    •   Alt7th April 2018, 09:30

      advertising

        
       

  7. #7
    Junior Member level 3
    Points: 221, Level: 2

    Join Date
    Oct 2017
    Posts
    25
    Helped
    0 / 0
    Points
    221
    Level
    2

    Re: PIC18F24K modbus function code 1

    The main issue i found is packing of data for function 1 & function3. Function 3 uses byte of data for packing and function 1 uses bit of data.The code work with byte of data i.e for function 3. How can i modify the below for read coils as bits and check for response.

    Code C - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    
    void Serial_Request()
    {
         unsigned int address,crc1,crc2;
         unsigned char length,i,j=0;
        
         
        // Serial_1_Send_byte(rxbuf[0]);
        crc2=crc_fn(&rxbuf[0],6); //crc function for received protocol from request 
         __delay_ms(10); // Changed on 20.01.2017
        if((rxbuf[6]==(unsigned char)(crc2))&&(rxbuf[7]==((unsigned char)(crc2>>8))))
        {
                    
               if(rxbuf[0]==device_ID)
               {
                
                //Serial_1_Send_byte(rxbuf[0]);
                
                    if(rxbuf[1]==READ_REG)
                    {
                         address=(((unsigned int)(rxbuf[2]<<8))+((unsigned int)(rxbuf[3]))); 
                         if(rxbuf[5]>=1)
                         {
                               // changes i made for function1, if i used i get an error.
                               length=(rxbuf[5]/8);// function code 1
                               address=0X01;// function code 1
                              // original function 3 code, if i keep below code it works fine for function 3
                               length=(rxbuf[5]*2);// function 3
                               address=(address*2);// function 3
     
                               ser_data[0]=device_ID;
                               ser_data[1]=rxbuf[1];
                               ser_data[2]=length;
                               ser_data[3]=0;
                               ser_data[4]=0;
                               ser_data[5]=0;
                               ser_data[6]=0;
                               ser_data[7]=0;
                               ser_data[8]=0;
                               ser_data[9]=0;
                               ser_data[10]=0;
                               ser_data[11]=0;
                               ser_data[12]=length;
                               ser_data[13]=0;
                               ser_data[14]=0;
                               ser_data[15]=0;
                               ser_data[16]=0;
                               ser_data[17]=0;
                               ser_data[18]=0;
                               ser_data[19]=0;
                               ser_data[20]=0;
                               ser_data[21]=0;
     
     
     
     
                               
                               crc_data[0]=device_ID;
                               crc_data[1]=rxbuf[1];
                               crc_data[2]=length;
                               j=3;
                               for(i=address;i<((address+length));i++)
                              {
                                    crc_data[j++]=ser_data[i+3];
                               }
                               crc1 =crc_fn(&crc_data[0],(length+3)); //crc function for response protocol from the device
     
                               Serial_1_Send_byte(ser_data[0]);
                               Serial_1_Send_byte(rxbuf[1]);
                               Serial_1_Send_byte(ser_data[2]);
                        
                               for(i=address;i<((address+length));i++)
                               {
                                    Serial_1_Send_byte(ser_data[i+3]);
                            
                               }
                               Serial_1_Send_byte((unsigned char)crc1);
                               Serial_1_Send_byte((unsigned char)(crc1>>8));
                      
                         } 
                    } 
                __delay_ms(5); 
           }
               
         }
        index=0;
         rec_flag = 0;
       
         
    }
    Last edited by andre_teprom; 15th April 2018 at 03:11. Reason: added syntax tags



    •   Alt15th April 2018, 03:04

      advertising

        
       

  8. #8
    Super Moderator
    Points: 241,412, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    41,891
    Helped
    12754 / 12754
    Points
    241,412
    Level
    100

    Re: PIC18F24K modbus function code 1

    The code looks arbitrarily complicated to me, I'm not particularly motivated to fix it. However if you have working function 3 server code, it should be rather easy to make the function 1 code.

    As previously explained, the difference is in the different meaning of request length field. In the request it's a bit count (number of coils), you need to calculate the respective byte count for the response. Format of function 1 and function 3 response as such is identical.



  9. #9
    Junior Member level 3
    Points: 221, Level: 2

    Join Date
    Oct 2017
    Posts
    25
    Helped
    0 / 0
    Points
    221
    Level
    2

    Re: PIC18F24K modbus function code 1

    How can i calculate bit count instead of byte.Can i get sample code for it . accordingly i can modifiy it



  10. #10
    Advanced Member level 3
    Points: 6,179, Level: 18

    Join Date
    Jan 2015
    Posts
    899
    Helped
    284 / 284
    Points
    6,179
    Level
    18

    Re: PIC18F24K modbus function code 1

    How many coils are you trying to read?
    Then send the address of the first coil to read (as a 16-bit value) and then send the number of coils to read (again as a 16-bit value).
    In return you will get a 16-bit value that tells you the number of *bytes* you will get back and then that number of bytes.
    The issue will be that the value for each coil is only 1 bit long.
    To take an example, say you want to read 3 coils, starting from coil #7.
    You will send:
    - 0x0007 (the address of the first coil)
    - 0x0003 (the number of coils)
    You will get back
    - 0x01 (an 8 bit value telling you that there is 1 byte to follow)
    - 0x0n (see below)
    As you have asked for 3 coil values, you need to look at the bottom 3 bits of the value 'n' and they will be the coil values.
    Given the number of coils you asked for, then you will get back "/8" bytes (there being 8 bits to a byte). So if you asked for 10 coils, you would get back 2 bytes with the first byte holding the values for the first 8 coils, and the 2nd byte holding the values for the next 2 coils.
    Susan



  11. #11
    Junior Member level 3
    Points: 221, Level: 2

    Join Date
    Oct 2017
    Posts
    25
    Helped
    0 / 0
    Points
    221
    Level
    2

    Re: PIC18F24K modbus function code 1

    I want to read totally 32 coil register , starting from 0-32 min.The code i share i could able to get crc & pack data properly.

    How can i send mine 32 bits/ read coil register here.rxbuf[5] contain my total length asked for example
    00 start address end address 20(hex) 32 in dec .
    There for no of bits required 20/8=4 .
    Problem i am facing after getting actual length move data for packing. In below code i moved as byte . first bit of data to be converted to byte then send as response for CRC check



    Code:
    length=(rxbuf[5]/8);
    crc_data[0]=device_ID;
                               crc_data[1]=rxbuf[1];
                               crc_data[2]=length;
                               j=3;
                               for(i=address;i<((address+length));i++)
                              {
                                    crc_data[j++]=ser_data[i+3];
                               }
                               crc1 =crc_fn(&crc_data[0],(length+3)); //crc function for response protocol from the device
    
                               Serial_1_Send_byte(ser_data[0]);
                               Serial_1_Send_byte(rxbuf[1]);
                               Serial_1_Send_byte(ser_data[2]);
                        
                               for(i=address;i<((address+length));i++)
                               {
                                    Serial_1_Send_byte(ser_data[i+3]);
                            
                               }
                               Serial_1_Send_byte((unsigned char)crc1);
                               Serial_1_Send_byte((unsigned char)(crc1>>8));
    Last edited by KlausST; 16th April 2018 at 12:09. Reason: added code tags



  12. #12
    Super Moderator
    Points: 57,531, Level: 58
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    11,705
    Helped
    2715 / 2715
    Points
    57,531
    Level
    58

    Re: PIC18F24K modbus function code 1

    Hi,

    I want to read totally 32 coil register , starting from 0-32 min.
    0..32 means 33 items.
    Maybe you want 0..31.

    Klaus
    Please don´t contact me via PM, because there is no time to respond to them. Thank you.



  13. #13
    Advanced Member level 3
    Points: 6,179, Level: 18

    Join Date
    Jan 2015
    Posts
    899
    Helped
    284 / 284
    Points
    6,179
    Level
    18

    Re: PIC18F24K modbus function code 1

    Perhaps you need to explain the full picture as I am rather confused (as are others looking at the responses above) as to what devices we are actually talking about.
    At a guess, is the overall configuration:

    Server A <---exchange---> Pic <---modbus---> some device

    Is the code you have provided us with the "exchange" command/response between the "Server A" and the "Pic" as that is the only place that seems to fit your inclusion of a start and end address as well as a checksum?
    If that is the case, then is your problem that you don't know how to convert the 'start' and 'end' address values into the number of bytes you will receive over the modbus interface from 'some device'? If so, then I've given you the answer and you have used it (sort of) in your post #11 (although it would have been clearer to show the values in decimal or include he hex prefix for the '20') so I don't understand the problem you still have.
    Susan



  14. #14
    Junior Member level 3
    Points: 221, Level: 2

    Join Date
    Oct 2017
    Posts
    25
    Helped
    0 / 0
    Points
    221
    Level
    2

    Re: PIC18F24K modbus function code 1

    The code i have written for modbus RTU for function code 3. where PIC receive data in byte and send as byte data. there is no issue where i can send & receive response as per function code3.

    Now i would like to modify same code for function1 . where data received as same format , but when we pack data , data format should be in bit format. Since request format remain same i kept same code. but need to change response format.where instead of byte data i need to store bit to byte and then send . for example 32 bits equivalent to 4 byte

    How can i pack these 32 bit of data & send back for crc check to get proper response.

    Since read coil read status of digital io like high or low.

    length i got from length=(rxbuf[5]/8); or length=(rxbuf[5]-rxbuf[3])/8
    As i understood Byte_array[0]={digital_status7,digital_status6,digital_status5, digital_status4,digital_status3,digital_status2,di gital_status1,digital_status0}
    so on for other 4 byte of array. how can i store them & send for CRC check



  15. #15
    Advanced Member level 3
    Points: 6,179, Level: 18

    Join Date
    Jan 2015
    Posts
    899
    Helped
    284 / 284
    Points
    6,179
    Level
    18

    Re: PIC18F24K modbus function code 1

    Quote Originally Posted by ajit_nayak87 View Post
    length i got from length=(rxbuf[5]/8); or length=(rxbuf[5]-rxbuf[3])/8
    That code does not work as you expect as it will be performed using integer arithmetic. That means that for values of 'rxbuf[5]' from 0 to 7, the value of 'length' will be 0 and not 1 as you would require. You need to use the formula such as the one I gave earlier (post #10).
    Why do you need to convert the bits in the byte to individual values - can you not pass them back to whatever the PIC is talking to as a byte. You can also use the byte values for the CRC calculation.
    If you really do need to send a whole lot of bytes values (that will be either 0x00 or 0x01) then use the normal C bit shifting and masking operators to put each bit into a separate byte array.
    Susan



    •   Alt17th April 2018, 05:44

      advertising

        
       

  16. #16
    Junior Member level 3
    Points: 221, Level: 2

    Join Date
    Oct 2017
    Posts
    25
    Helped
    0 / 0
    Points
    221
    Level
    2

    Re: PIC18F24K modbus function code 1

    if my data send from master look like this. what should be expected length for below request.


    You will send:
    - 0x0007 (the address of the first coil)
    - 0x0031 (the number of coils)
    You will get back
    - 0x01 (an 8 bit value telling you that there is 1 byte to follow)
    - 0x0n (see below)

    I am sendind
    0x0000 (the address of the first coil)
    0x0031 (the number of coils)
    You will get back

    I am requesting for 50 coils . i should receive 6 byte of data and send in 2 byte
    can get sample code for it if i am sending same request .
    In attached code on first thread
    [LIST]
    • How to calculate legth in code for reading coil
    • after calculating readcoil, store the coil into bit value to byte,
    • how to send byte of data crc check





    Is function i am calling in interrupt. I am checking first 8 byte of messages 01 01 00 00 00 31 fd de
    rxbuf[0]= 01 //device Id always
    rxbuf[1]= 01 //Functional code
    rxbuf[2]= 00 //higher byte of start address
    rxbuf[3]= 00 //Lower byte of start address
    rxbuf[4]= 00 //higher byte of end address
    rxbuf[5]= 31 //Lower byte of end address
    rxbuf[6]= FD //CRC1
    rxbuf[7]= DE //CRC2



  17. #17
    Advanced Member level 3
    Points: 6,179, Level: 18

    Join Date
    Jan 2015
    Posts
    899
    Helped
    284 / 284
    Points
    6,179
    Level
    18

    Re: PIC18F24K modbus function code 1

    You are getting things a little confused here. If you are getting a request from the master with a start address of 0 and an end address of 0x31, then you are correct, you have 50 (decimal) coils to read. However the value you need to send via the modbus is the *number* of coils to read and not the address of the last one. Therefore you should be sending:
    Code:
    0x0000 (the address of the first coil)
    0x0032 (the number of coils to read - 50 decimal in this case)
    This will result in 50 bits being sent back to you. Those 50 bits will be packed into 8-bit bytes (i.e. you will receive data back in bytes and not bits via the modbus protocol).
    Using the formula I have provided above, (50+7)/8 = 7. That means you will get back the first 8 bits as the first byte, the next 8 bits in the send and so on but you will get the last 2 bits packed into the lower 2 bits of the 7th byte- the remaining 6 bits will be zero padded.
    Therefore the 50 bit values will already be packed into 7 8-bit bytes for you and you can then construct the packet to send back to the 'master' around that.
    Not sure what formula you want to use for the CRC but that can be calculated once you have the complete packet to send back to the master.
    Susan



  18. #18
    Junior Member level 3
    Points: 221, Level: 2

    Join Date
    Oct 2017
    Posts
    25
    Helped
    0 / 0
    Points
    221
    Level
    2

    Re: PIC18F24K modbus function code 1

    Can you send me sample code. I am getting data properly.
    if u can illustriate function above code i can modify accordingly. just for 8 bit. and send data for crc check


    Code:
    #include 
        #define CRC16 0x8005
        uint16_t gen_crc16(const uint8_t *data, uint16_t size)
        {
            uint16_t out = 0;
            int bits_read = 0, bit_flag;
    
            /* Sanity check: */
            if(data == NULL)
                return 0;
    
            while(size > 0)
            {
                    bit_flag = out >> 15;
    
                    /* Get next bit: */
                    out <<= 1;
                    out |= (*data >> (7 - bits_read)) & 1;
    
                    /* Increment bit counter: */
                    bits_read++;
                    if(bits_read > 7)
                    {
                        bits_read = 0;
                        data++;
                        size--;
                }
    
                /* Cycle check: */
                if(bit_flag)
                    out ^= CRC16;
    
            }
            return out;
    }
    
    
    
    
    Code:
    int bitsCount(unsigned x)
    {
        int b;
        for (b = 0; x != 0; x >>= 1)
            if (x & 01)
                b++;
        return b;
    }



  19. #19
    Advanced Member level 3
    Points: 6,179, Level: 18

    Join Date
    Jan 2015
    Posts
    899
    Helped
    284 / 284
    Points
    6,179
    Level
    18

    Re: PIC18F24K modbus function code 1

    Seriously? You can write the CRC code but can't write code given the descriptions provided in this thread?
    This is really 'Programming 101' level coding.
    [Possible approach without dynamic memory allocation] Work out the maximum number of coils you will ever be asked to return, calculate how many bytes is required to hold that number of bits, add however many bytes for the header and CRC values, create an array of the required size as part of the pre-programming design work; fill in the header, copy over the received bytes from the modbus response (this will vary with the actual number of coils in the request) using an incremented index value, calculate the CDC and put that in the next byte(s) using the same incremented index value.
    [Possible approach using dynamic memory allocation] Same as above but allocate the memory before you start and free it after you are done instead of using a fixed size array.
    Susan



--[[ ]]--