Can someone help me with this serial protocol.

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • kryptonite88
    New Member
    • Jul 2009
    • 10

    Can someone help me with this serial protocol.

    I am making a link between 2 systems. They communicate over a serial link. I know the protocol and all the commands.
    However I can’t figure out what the “dn” is supposed to mean. Is it the number of d’s?
    I also don’t know what the crc.high and crc.low is all about. I know that the crc is a checksum and I know how to calculate it but I don’t know what the high and low are.

  • JosAH
    Recognized Expert MVP
    • Mar 2007
    • 11453

    #2
    dn is the last byte of data; d1 is the first data byte, d2 is the second data byte and when you have n bytes of data, dn is the last data byte. crc.high and crc.lo are the hi and lo bytes of the 16 bit wide crc number (16 bits == 2 bytes).

    kind regards,

    Jos

    Comment

    • kryptonite88
      New Member
      • Jul 2009
      • 10

      #3
      Thank you man, you are my hero.

      Comment

      • JosAH
        Recognized Expert MVP
        • Mar 2007
        • 11453

        #4
        Originally posted by kryptonite88
        Thank you man, you are my hero.
        You're welcome of course; you still have to read the specification because from that picture I can't tell whether or not the 'cmd' byte (or the leading/trailing bytes) is/are included in the crc value.

        kind regards,

        Jos

        Comment

        • kryptonite88
          New Member
          • Jul 2009
          • 10

          #5
          Yes, they are. They are calculated in way I don’t rely understand. It says I have to divide the crc by 0x147A. But is crc the sum of the command and the trailing bytes or zero? I have included a screenshot of the calculation.

          I’m not really used to the level of technical programming. I’m more involved in making windows apps and web apps. Though I really like this technical stuff, it’s just hard to understand without the proper education.

          Comment

          • JosAH
            Recognized Expert MVP
            • Mar 2007
            • 11453

            #6
            Originally posted by kryptonite88
            Yes, they are. They are calculated in way I don’t rely understand. It says I have to divide the crc by 0x147A. But is crc the sum of the command and the trailing bytes or zero? I have included a screenshot of the calculation.

            I’m not really used to the level of technical programming. I’m more involved in making windows apps and web apps. Though I really like this technical stuff, it’s just hard to understand without the proper education.

            You just have to initialize the crc value to 0x147a according to that picture. Then rotate it and do the funny add as described in step 2c. Perform those steps for the cmd byte and all the d bytes.

            kind regards,

            Jos

            Comment

            • kryptonite88
              New Member
              • Jul 2009
              • 10

              #7
              Originally posted by JosAH
              You just have to initialize the crc value to 0x147a according to that picture. Then rotate it and do the funny add as described in step 2c. Perform those steps for the cmd byte and all the d bytes.

              kind regards,

              Jos
              So I code the initial crc like this :

              Code:
              uint crc = 0x147A;           
              crc = crc << 1;
              crc ^= 0xFFFF;
              Then the example they gave in 2c would be :

              Code:
              uint test = 0xFEDC; // crc
              test += GetHighLow(test.ToString("X")).high; //crc.high
              test += 0xA9; // b

              Comment

              • JosAH
                Recognized Expert MVP
                • Mar 2007
                • 11453

                #8
                Originally posted by kryptonite88
                So I code the initial crc like this :

                Code:
                uint crc = 0x147A;           
                crc = crc << 1;
                crc ^= 0xFFFF;
                Not really; they want to rotate the crc value; you're just shifting it to the left one bit; change the second line to:

                Code:
                crc= (crc<<1)|((crc>>15)&1);
                this code snippet shifts the crc to the left one bit and 'or's bit 15 in as the new lo bit (bit #0); this mimics a rotate operation.

                kind regards,

                Jos

                Comment

                • kryptonite88
                  New Member
                  • Jul 2009
                  • 10

                  #9
                  Thanks for finding that error in my code.
                  I think there is still something wrong with my calculation. In the example below I’m sending a command that requires 4 bytes of data. The protocol is designed to not give a reply if there is something wrong with the crc.

                  I confirmed that communicating through code is working when I use the system in monitoring mode. So the cable and the communication setting are correct. It has to be something in this piece of code.


                  Code:
                  private void button1_Click(object sender, EventArgs e)
                          {
                              serialPort.Open();
                  
                              byte[] versturen = new byte[11];
                  
                              // Start
                              versturen[0] = 0xFE;
                              versturen[1] = 0xFE;
                              
                              // Command
                              versturen[2] = 0xE0;
                  
                              // 4 byte data
                              versturen[3] = 0x12;
                              versturen[4] = 0x34;
                              versturen[5] = 0x5F;
                              versturen[6] = 0xFF;
                  
                              // crc
                              versturen[7] = CalcCrc(0xE0 | 0x12 | 0x34 | 0x5F | 0xFF).high;
                              versturen[8] = CalcCrc(0xE0 | 0x12 | 0x34 | 0x5F | 0xFF).low;
                              
                              // End
                              versturen[9] = 0xFE;
                              versturen[10] = 0x0D;
                  
                              serialPort.Write(versturen, 0, versturen.Length);
                              MessageBox.Show(ReadData().ToString());
                              serialPort.Close();
                          }
                  
                  private byte Hex(string hex)
                          {
                              return byte.Parse(hex, System.Globalization.NumberStyles.HexNumber);
                          }
                  
                          private HighLow CalcCrc(params byte[] list)
                          {
                              uint crc = 0x147A; // crc
                  
                              foreach (byte b in list)
                              {
                                  crc = (crc << 1) | ((crc >> 15) & 1); ; // crc left rotation
                                  crc ^= 0xFFFF; // crc / 0xFFFF
                  
                                  crc += GetHighLow(crc.ToString("X")).high;
                                  crc += b;
                              }
                  
                              return GetHighLow(((crc.ToString("X")).Substring((crc.ToString("X").Length - 4), 4)));
                          }
                  
                          private HighLow GetHighLow(string format)
                          {
                              return new HighLow(Hex(format.Substring(0, 2)),
                                  Hex(format.Substring(2, 2)));
                          }
                  
                          private struct HighLow
                          {
                              public HighLow(byte high, byte low)
                              {
                                  this.high = high;
                                  this.low = low;
                              }
                  
                              public byte high;
                              public byte low;
                          }

                  Comment

                  • JosAH
                    Recognized Expert MVP
                    • Mar 2007
                    • 11453

                    #10
                    Originally posted by kryptonite88
                    Code:
                                // crc
                                versturen[7] = CalcCrc(0xE0 | 0x12 | 0x34 | 0x5F | 0xFF).high;
                                versturen[8] = CalcCrc(0xE0 | 0x12 | 0x34 | 0x5F | 0xFF).low;
                    What do these lines do? If this is Java or C# the parameter (a single one!) certainly doesn't result in an array of bytes; the | operator bitwise-or's its operands which most certainly is not what you want.

                    kind regards,

                    Jos

                    Comment

                    • kryptonite88
                      New Member
                      • Jul 2009
                      • 10

                      #11
                      Originally posted by JosAH
                      What do these lines do? If this is Java or C# the parameter (a single one!) certainly doesn't result in an array of bytes; the | operator bitwise-or's its operands which most certainly is not what you want.

                      kind regards,

                      Jos
                      Changed it to :
                      Code:
                      // crc
                                  versturen[7] = CalcCrc(new byte[] {0xE0, 0x12, 0x34, 0x5F, 0xFF}).high;
                                  versturen[8] = CalcCrc(new byte[] {0xE0, 0x12, 0x34, 0x5F, 0xFF}).low;
                      But still no result.

                      Comment

                      • JosAH
                        Recognized Expert MVP
                        • Mar 2007
                        • 11453

                        #12
                        Originally posted by kryptonite88
                        Changed it to :
                        Code:
                        // crc
                                    versturen[7] = CalcCrc(new byte[] {0xE0, 0x12, 0x34, 0x5F, 0xFF}).high;
                                    versturen[8] = CalcCrc(new byte[] {0xE0, 0x12, 0x34, 0x5F, 0xFF}).low;
                        But still no result.
                        Next I don't understand what your line #47 does:

                        Code:
                         crc += GetHighLow(crc.ToString("X")).high;
                        Better change that to:

                        Code:
                        crc+= (crc>>8)&0xff;
                        That adds the high byte of the crc to the crc value itself, just as your documentation says so.

                        kind regards,

                        Jos

                        Comment

                        • kryptonite88
                          New Member
                          • Jul 2009
                          • 10

                          #13
                          It finally worked. I found out that my ReadData() method had a check for bytes in the buffer which failed and told me the buffer was empty. If is just start reading I receive a reply.

                          I thank you very much Jos. I could not have begun to crack this without your help.

                          BTW. Can I assume that if
                          Code:
                          (crc>>8)&0xff
                          get me the high,
                          Code:
                          (crc<<8)&0xff
                          gives me the low?

                          Comment

                          • JosAH
                            Recognized Expert MVP
                            • Mar 2007
                            • 11453

                            #14
                            Originally posted by kryptonite88
                            It finally worked. I found out that my ReadData() method had a check for bytes in the buffer which failed and told me the buffer was empty. If is just start reading I receive a reply.

                            I thank you very much Jos. I could not have begun to crack this without your help.

                            BTW. Can I assume that if
                            Code:
                            (crc>>8)&0xff
                            get me the high,
                            Code:
                            (crc<<8)&0xff
                            gives me the low?
                            Nope, the first expression shifts the crc value 8 bits to the right and masks everything away except for the lower 8 bits (that's the value 0xff). So if you want to keep just the lo byte there's no need to shift anything, just mask everything except for the lowest eight bits away; like this:

                            Code:
                            int lo= crc&0xff;
                            kind regards,

                            Jos

                            Comment

                            Working...