2017-08-11 6 views
0

私はCを使用してatMega1281マイクロコントローラを使用しています。私はSPNを読み取るためにCANバスから4バイトを引き出すルーチンを持っています。私は4バイトを取得することができますが、最初の2バイトを16ビットの数に切り捨てるので、4バイトの数字は印刷できません。私は宣言としてunsigned longを無事に使ってみました。 AVRで32ビットの数字を使うときのトリックは何ですか?AVRを使用してCで4バイトと数式計算を行う方法

unsigned long engine_hours_raw; 
float engine_hours_uint; 

engine_hours_raw = (OneMessage.Msg.Data[3] << 24) | (OneMessage.Msg.Data[2] << 16) | (OneMessage.Msg.Data[1] << 8) | OneMessage.Msg.Data[0]); 
engine_hours_uint = engine_hours_raw * 0.05; 

ftoa(engine_hours_uint, engHours, 1); 
UART1_Printf("Engine Hours: %s ", engHours); 
+0

念のために:どのように4バイトの番号を印刷していますか? –

+0

私はフロートを実際にftoaを使って文字列に変換してから文字列として出力します。 – Eddie

+0

@Eddieベアメタルの組み込みシステムでは、ポインタがメモリ内の実際のアドレスであることがわかっているので標準に固執する必要はありません:) –

答えて

1

(OneMessage.Msg.Data[3] << 24)の発現のためのデフォルトのサイズはint型であるとして0になります。それがキャストされない限り。

代わりに、long intにデータをロードしてからシフトを実行します。

engine_hours_raw = OneMessage.Msg.Data[3]; 
engine_hours_raw <<= 8; 
engine_hours_raw |= OneMessage.Msg.Data[2]; 
engine_hours_raw <<= 8; 
engine_hours_raw |= OneMessage.Msg.Data[1]; 
engine_hours_raw <<= 8; 
engine_hours_raw |= OneMessage.Msg.Data[0]; 

はまた、符号なしのログまたはのuint32_tなどの中間表現をキャストすることができますが、それは同じように厄介と時間がかかることがあります。

engine_hours_raw = ((unit32_t)(OneMessage.Msg.Data[3]) << 24) | ((unit32_t)(OneMessage.Msg.Data[2]) << 16) | ((unit32_t)(OneMessage.Msg.Data[1]) << 8) | (unit32_t)(OneMessage.Msg.Data[0]); 
+0

なぜそれを複雑にするのですか?私たちはベアメタルの埋め込み世界にいます。ポインタとアドレスはよく知られています:) –

+0

この解決策は機能しました。私は宣言についての詳細を説明した文書を見つけました。ありがとうUncleO! – Eddie

0

はるかに簡単かつ簡単な方法があります:)

uint32_t *engine_hours_raw = (uint32_t *)OneMessage.Msg.Data; 
float engine_hours_uint = *engine_hours_raw * 0.05; 
関連する問題