2012-09-24 5 views
1

RC 비행기를위한 간단한 지상 제어 스테이션을 만들려고합니다. 거의 끝났지 만 체크섬 계산에 많은 문제가 있습니다. 자바와 C#의 데이터 유형이 다르다는 것을 이해합니다. 나는 그것을 설명하려고 시도했으나 성공하지 못했습니다. 이 프로그램은 CRC-16-CCITT 방법을 사용합니다. 여기 작은 C# 체크섬 프로그램을 Java로 변환

내 포트 :

public int crc_accumulate(int b, int crc) { 
     int ch = (b^(crc & 0x00ff)); 
     ch = (ch^(ch << 4)); 
     return ((crc >> 8)^(ch << 8)^(ch << 3)^(ch >> 4)); 
} 

public byte[] crc_calculate() { 
     int[] pBuffer=new int[]{255,9,19,1,1,0,0,0,0,0,2,3,81,4,3}; 
     int crcEx=0; 
     int clength=pBuffer.length; 
     int[] X25_INIT_CRC=new int[]{255,255}; 
     byte[] crcTmp=new byte[]{(byte)255,(byte)255}; 
     int crcTmp2 = ((crcTmp[0] & 0xff) << 8) | (crcTmp[1] & 0xff); 
     crcTmp[0]=(byte)crcTmp2; 
     crcTmp[1]=(byte)(crcTmp2 >> 8); 
     System.out.println("pre-calculation: 0x"+Integer.toHexString((crcTmp[0]&0xff))+" 0x"+Integer.toHexString((crcTmp[1]&0xff))+"; ushort: "+crcTmp2); 
     if (clength < 1) { 
       System.out.println("clength < 1"); 
       return crcTmp; 
     } 
     for (int i=1; i<clength; i++) { 
       crcTmp2 = crc_accumulate(pBuffer[i], crcTmp2); 
     } 
     crcTmp[0]=(byte)crcTmp2; 
     crcTmp[1]=(byte)(crcTmp2 >> 8); 
     System.out.print("crc calculation: 0x"+Integer.toHexString((crcTmp[0]&0xff))+" 0x"+Integer.toHexString((crcTmp[1]&0xff))+"; ushort: "+crcTmp2); 
     if (crcEx!=-1) { 
       System.out.println(" extraCRC["+crcEx+"]="+extraCRC[crcEx]); 
       crcTmp2=crc_accumulate(extraCRC[crcEx], crcTmp2); 
       crcTmp[0]=(byte)crcTmp2; 
       crcTmp[1]=(byte)(crcTmp2 >> 8); 
     System.out.println("with extra CRC: 0x"+Integer.toHexString((crcTmp[0]&0xff))+" 0x"+Integer.toHexString((crcTmp[1]&0xff))+"; ushort: "+crcTmp2+"\n\n"); 
     } 
     return crcTmp; 
} 

이 원래의 C# 파일입니다

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ArdupilotMega 
{ 
class MavlinkCRC 
{ 
    const int X25_INIT_CRC = 0xffff; 
    const int X25_VALIDATE_CRC = 0xf0b8; 

    public static ushort crc_accumulate(byte b, ushort crc) 
    { 
     unchecked 
     { 
      byte ch = (byte)(b^(byte)(crc & 0x00ff)); 
      ch = (byte)(ch^(ch << 4)); 
      return (ushort)((crc >> 8)^(ch << 8)^(ch << 3)^(ch >> 4)); 
     } 
    } 

    public static ushort crc_calculate(byte[] pBuffer, int length) 
    { 
     if (length < 1) 
     { 
      return 0xffff; 
     } 
     // For a "message" of length bytes contained in the unsigned char array 
     // pointed to by pBuffer, calculate the CRC 
     // crcCalculate(unsigned char* pBuffer, int length, unsigned short* checkConst) < not needed 

     ushort crcTmp; 
     int i; 

     crcTmp = X25_INIT_CRC; 

     for (i = 1; i < length; i++) // skips header U 
     { 
      crcTmp = crc_accumulate(pBuffer[i], crcTmp); 
      //Console.WriteLine(crcTmp + " " + pBuffer[i] + " " + length); 
     } 

     return (crcTmp); 
    } 

} 
} 

내 포트에 문제가 라인 1 5. 기대 사이에 놓여 있음을 확신 해요 0x94 0x88의 출력을 얻으려면 대신 프로그램은 0x2D 0xF4를 출력합니다.

내가 잘못한 부분을 누군가 보여 주면 크게 감사하겠습니다. 어떤 도움

감사합니다, 카메론

+1

원본 코드의 관련 부분과 여기 포트를 링크가 아닌 질문 본문에 게시하십시오. –

+0

내 첫 모습에서는 crc 계산을 위해 다른 유형을 사용합니다. 적절한 캐스팅을 사용하여 동일한 (또는 유사한) 데이터 유형을 사용해 보는 것이 어떻습니까? –

+0

@Cameron : 여기에 관심 분야 코드를 게시하십시오. 많은 사람들이 오염 우려가있는 링크에 가지 않거나 방화벽 때문에 링크로 갈 수 없습니다. –

답변

2

좋아는, 우선 조금 C# 코드 정리 할 수 ​​있습니다 :

const int X25_INIT_CRC = 0xffff; 

public static ushort crc_accumulate(byte b, ushort crc) 
{ 
    unchecked 
    { 
     byte ch = (byte)(b^(byte)(crc & 0x00ff)); 
     ch = (byte)(ch^(ch << 4)); 

     return (ushort)((crc >> 8)^(ch << 8)^(ch << 3)^(ch >> 4)); 
    } 
} 

public static ushort crc_calculate(byte[] pBuffer) 
{ 
    ushort crcTmp = X25_INIT_CRC; 

    for (int i = 1; i < pBuffer.Length; i++) // skips header U 
     crcTmp = crc_accumulate(pBuffer[i], crcTmp); 

    return crcTmp; 
} 

을 지금 여기에 가장 큰 문제는 자바에는 부호없는 숫자 형식이없는 것을 따라서 ushortbyte 대신 다음 큰 숫자 형식을 사용하고 필요에 따라 상위 비트를 마스킹하여이 문제를 해결해야합니다. Java에서 어쨌든 오버플로 검사가 없으므로 unchecked을 삭제할 수도 있습니다. C#을 정리,

public static final int X25_INIT_CRC = 0xffff; 

public static int crc_accumulate(short b, int crc) { 
    short ch = (short)((b^crc) & 0xff); 
    ch = (short)((ch^(ch << 4)) & 0xff); 

    return ((crc >> 8)^(ch << 8)^(ch << 3)^(ch >> 4)) & 0xffff; 
} 

public static int crc_calculate(short[] pBuffer) { 
    int crcTmp = X25_INIT_CRC; 

    for (int i = 1; i < pBuffer.length; i++) // skips header U 
     crcTmp = crc_accumulate(pBuffer[i], crcTmp); 

    return crcTmp; 
} 

질문 ({ 255, 9, 19, 1, 1, 0, 0, 0, 0, 0, 2, 3, 81, 4, 3 }) 원래 C#에서 입력 및 자바 모든 0xfc7e을 생산 : 최종 결과는이 같은 것입니다.

+0

와우, 그런 신속하고 완전한 응답을 기대하지 않았다! 고맙습니다. 이제 일하러 가야하지만 돌아 오면 즉시 테스트 해 보겠습니다. 다시 한 번 감사드립니다! –

+0

내 프로그램에 코드를 적용 했는데도 0xFC 0x7E을 출력으로받습니다. 누군가가 제공 한 LabView 계산기 덕분에 0x94 0x88을 기대했지만 코드의 C# 및 C#이 거의 동일하기 때문에 LabView 계산기의 오류라고 확신합니다. 감사! –

+0

@CameronLattz 제가 대답의 마지막 부분에서 말했듯이, 링크의 원래 C# 코드는'0xfc7e'가됩니다. 어쩌면 입력 배열을 두 번 확인해보십시오. 항목을 놓쳤거나 숫자를 바꿀 수 있습니다. – verdesmarald