CAN メッセージのデータ フィールドの値を 16 進形式の一連のショートとして出力できるコードを作成しようとしています。CAN メッセージ データ フィールドには 4 つの short が含まれているため、たとえば、1 つのメッセージを「FFFF EEEE ABAB 2013」として出力する場合があります。
CAN メッセージの 2 つの short を整数値にエンコードできます。整数の 32 番目のビットが設定されていない限り、すべて正常に動作します。Java は符号付き整数を使用するため、32 番目のビットを設定すると、一連の "f" が出力されます。私が望むのは、整数を符号なしの値として機能させて、出力しても問題が発生しないようにすることです。
うまくいかない例を次に示します。
(int value): 0x80000000
(string rep short 1): 0xffff8000
<crash>
そして、これが他のすべての場合にどのように機能するかを示します。
(int value): 0x40000000
(string rep short 1): 0x4000
(string rep short 2): 0x0
CAN メッセージ データを表現しようとするコードとクラッシュが発生するコード:
public String getFormattedData() {
String dataString = "";
for(String aShort : Utility.splitStringByWhitespace(getData())) {
try{
dataString += ("0000".substring(0, 4 - aShort.length()) + aShort) + " ";
} catch(Exception e) {
System.out.println(getData());
System.exit(1);
}
}
return dataString.toUpperCase();
}
具体的には、「f」が short の文字列表現の長さを 8 文字に増やし、「4 - aShort.length()」が無効な負の値を生成するため、クラッシュが発生します。
編集:お尋ねの場合、この特定のケースでは、文字列表現に変換する前に整数を使用してデータをエンコードする方法を次に示します。
public String convertToCANMessageData(PWMChannel channel) {
int channelVal = channel.getValue();
int entryDataHI = 0, entryDataLO = 0;
entryDataHI += channelVal << 24;
entryDataHI += smallData << 8;
entryDataHI += (largeData >> 8) & 0xFF;
entryDataLO += (largeData & 0xFF) << 24;
if(ramping) {
entryDataHI = entryDataHI | (1 << 16);
} else {
entryDataHI = entryDataHI & ~(1 << 16);
}
if(jumping) {
entryDataHI = entryDataHI | (1 << 17);
} else {
entryDataHI = entryDataHI & ~(1 << 17);
}
if(frequencySetting) {
entryDataHI = entryDataHI | (1 << 18);
} else {
entryDataHI = entryDataHI & ~(1 << 18);
}
return String.format("%x %x %x %x", entryDataHI >> 16, entryDataHI & 0xFFFF,
entryDataLO >> 16, entryDataLO & 0xFFFF);
}