7

Dynamic C 9 を使用する組み込みハードウェア、Rabbit SBC を使用しています。

マイクロコントローラーを使用して、シリアル ポートの 1 つを使用してデジタル コンパス センサーから情報を読み取っています。

センサーは、1 つの符号付きバイトを使用して値をマイクロコントローラーに送信します。(-85~85)

charこのデータを受け取ったら、それを変数に入れています

これは正の値に対しては正常に機能しますが、センサーが負の値を送信し始めると、読み取り値は 255 にジャンプし、その後 0 に戻ります。これは、最後のビットが負/正を決定するために使用されているためだと思います。そして、実際の値を歪めています。

私の最初の考えは、データ型を に変更することでしたsigned char

ただし、私が抱えている問題は、私が使用しているマイクロコントローラーの Dynamic C のバージョンが、符号付きの char 値をネイティブにサポートしておらず、符号なしのみをサポートしていることです。

受け取ったデータを手動で符号付きの値にキャストする方法があるかどうか疑問に思っていますか?

4

4 に答える 4

11

参考書を取り出して、コントローラーによって負の数がどのように表されるかを読む必要があります。残りはただタイプするだけです。

たとえば、2の補数は値mod 256をとることで表されるため、モジュラスで調整する必要があります。

int signed_from_unsignedchar(unsigned char c)
{
    int result = c;
    if (result >= 128) result -= 256;
    return result;
}

1の補数ははるかに単純です。ビットを反転するだけです。

int signed_from_unsignedchar(unsigned char c)
{
    int result = c;
    if (result >= 128) result = -(int)(unsigned char)~c;
    return result;
}

符号の大きさは、上位ビットを設定することによって負の数を表すため、ビットをクリアして否定する必要があります。

int signed_from_unsignedchar(unsigned char c)
{
    int result = c;
    if (result >= 128) result = -(result & 0x7F);
    return result;
}
于 2011-09-25T14:23:27.243 に答える
1

私はこれがあなたが求めているものだと思います(32ビットのintと8ビットのcharを想定しています):

unsigned char c = 255;
int i = ((int)(((unsigned int)c) << 24)) >> 24;

もちろん、ここでは、プラットフォームが符号付き整数をサポートしていると想定していますが、そうではない場合があります。

于 2011-09-25T14:22:48.153 に答える
1

符号付きと符号なしの値はすべて単なるビットの集まりであり、それらを符号付きまたは符号なしにするのはあなたの解釈です。たとえば、ハードウェアが2の補数を生成する場合、0xffを読み取ると、-1または255として解釈できますが、実際には同じ数です。

自由に使える場合はunsigned char、負の値の動作をエミュレートする必要があります。

例えば:

c < 0

に変更

c > 127

幸いなことに、追加は変更する必要はありません。減算も同じです(これを確認してください。100%確信が持てません)。

たとえば掛け算の場合は、自分でチェックする必要があります。まず、2の補数で、数値の正の値を取得する方法は次のとおりです。

pos_c =〜neg_c + 1

これは数学的に言えば256-neg_c、256を法とする合同なものは単純です-neg_c

ここで、符号なしの2つの数値を乗算したいが、それらを符号付きとして解釈したいとします。

unsigned char abs_a = a, abs_b = b;
char final_sign = 0; // 0 for positive, 1 for negative
if (a > 128)
{
    abs_a = ~a+1
    final_sign = 1-final_sign;
}
if (b > 128)
{
    abs_b = ~b+1
    final_sign = 1-final_sign;
}
result = abs_a*abs_b;
if (sign == 1)
    result = ~result+1;

あなたはアイデアを得る!

于 2011-09-25T14:26:26.510 に答える
0

プラットフォームがsigned ints をサポートしている場合は、他の回答をいくつか確認してください。

そうでなく、値が間違いなく -85 から +85 の間にあり、2 の補数である場合は、入力値に 85 を追加し、0 から 170 の間の値を解釈するようにプログラム ロジックを調整して、signed をいじる必要がないようにします。もはや整数。

それが1の補数である場合は、これを試してください:

if (x >= 128) {
    x = 85 - (x ^ 0xff);
} else {
    x = x + 85;
}

これにより、0 から 170 の間の値も残ります。

編集: はい、サインマグニチュードもあります。次に、ここで同じコードを使用しますが、2 行目を に変更しx = 85 - (x & 0x7f)ます。

于 2011-09-25T14:36:49.130 に答える