Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] PIC18F24K modbus function code 1

Status
Not open for further replies.

ajit_nayak87

Member level 5
Joined
Oct 30, 2017
Messages
86
Helped
1
Reputation
2
Reaction score
1
Trophy points
8
Activity points
981
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<len;i++)
     {
        crc^= dpacket[i];
        for(j=0;j<8;j++)
        {
              if(crc & 0x01)
              {
                   crc >>= 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
                       [B]   // 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
[/B]
                           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;
   
     
}
[/CODE]
 

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
 

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
 

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.
 

Modbus.jpg
**broken link removed**
Code out.png
Received_respons.jpg

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<len;i++)
 {
    crc^= dpacket[i];
    for(j=0;j<8;j++)
    {
     if(crc & 0x01)
     {
      crc >>= 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 a moderator:

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)

fct1.PNG
 

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 a moderator:

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.
 

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

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 "<number of coils + 7>/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
 

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 a moderator:

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
 

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
 

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,digital_status1,digital_status0}
so on for other 4 byte of array. how can i store them & send for CRC check
 

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
 

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
    • 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
 

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
 

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 <stdint.h>
    #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;
}
[/CODE]
 

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
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top