- ベストアンサー
int型(2バイト)データの分割
int型(2バイト)データの分割 マイコンのフラッシュ領域にint型のデータ(2バイト)を 1バイトづつ書き込むのに以下のコードを考えています。 unsigned int data; unsigned char dat1,dat2; data = 555; dat1 = 0; dat2 = 0; dat1 = (char)data; dat2 = (char)data >> 8; 以下、dat1とdat2をフラッシュに書き込む。 未熟者でプログラムとして合っているのか解りません。 やり方として問題ないでしょうか? またもっと良い方法があればご教授願います。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
まず考えるべきは、フラッシュメモリの書き込んだデータは誰が使うのか? です。 自分(というか、そのシステム)だけでしか使わないのであれば、余り気にすることはありません。 この場合だと、 data = 555; に対して、 dat1 = data % 0x100; dat2 = data / 0x100; が一番安全でしょう。 右辺はいずれも int のサイズで計算されて、代入の際に、(数値として)下の桁から、char 分が代入されます。 ※代入の直前までは、int で計算されることに注意。 読み出しの場合は、 data = dat2 * 0x100 + dat1; で安全に元に戻せます。 (これも、0x100 が int 幅なので、 dat2 * 0x100 は int に拡張され、それに対して、int に拡張された dat1 が加算されます) すべて符号無しなので、char -> int への拡張も問題なく行われます。 あと、かけ算や割り算は効率が悪いのではないか? という心配も無用です。 0x100 のような、(2進数で)きりの良い数のかけ算や割り算は、普通のコンパイラは、内部でシフトに置き換えますので。
その他の回答 (6)
- 正親町(@Ohgimachi)
- ベストアンサー率43% (110/252)
>マイコンのフラッシュ領域にint型のデータ(2バイト)を1バイトづつ書き込む 8bitのIOポートからFIFOバッファを利用して読み書きするタイプなのかな? IOのアドレスをFportとすると unsigned int data; char *c; c = (char *)&data; Fport = c[0]; Fport = c[1]; という方法で書き込めます。書いた通りの順番に読み出せば復元できますから、バイト・オーダーとかは気にする必要はありません。
お礼
皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。
- R32C
- ベストアンサー率39% (115/290)
処理系依存の問題ですね。 エンディアンも含めた対応をここで回答してみます。 マイコンが何かはわかりませんが、ルネサスの純正コンパイラ(H8でもVer6以降) であれば、#pragma bit_order でビットの並びが右並びか左並びを指定できます。 仕様として、質問者の例として 555 == 0x22B dat1に2B dat2に02 を書くことを目的とすることを考えてみます。 意図した質問かどうかにもよりますが、質問者の例(dat2 = (char)(data >> 8);に訂正済み)では bigエンディアンの場合にdat2がdat1と連続したアドレスで、dat1のアドレスからintで見たとき に22Bにならず2B02の動作例になります。 逆にメモリが連続していて、intで見たとき22Bを意図するならmemcpyもありなわけです。 どちらを意図するかによっても回答が異なります。 私の場合は、上記(仕様として)に基づいて回答してみます。 #pragma bit_order right union { unsigned int intdat; struct { unsigned int chdatLow:8; unsigned int chdatHigh:8; } chdat; } data; #pragma bit_order /* 以降のビット並びはオプションに従う */ data.intdat = 555; dat1 = data.chdat.chdatLow; dat2 = data.chdat.chdatHigh; 説明 リトルエンディアンの場合には 0000:indat == 0x22B 0000:chdatLow == 0x2B 0001:chdatHigh == 0x02 dat1 == 0x2B dat2 == 0x02 ビッグエンディアンの場合は 0000:indat == 0x22B 0000:chdatHigh == 0x02 0001:chdatLow == 0x2B dat1 == 0x2B dat2 == 0x02
お礼
皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。
- yama1718
- ベストアンサー率41% (670/1618)
処理系に依存する方法ですが、共用体が使えるなら それを使った方がシフト演算などを使わずにスマートにできます。 下位バイトが先に来る(リトルエンディアン)の処理系ならchdat[0]とchdat[1]の順番で 上位バイトが先に来る(ビッグエンディアン)の処理系ならchdat[1]とchdat[0]の順番になります。 インテル系のCPUならリトルエンディアンですが、マイコンなら機種により違うので 確認して見て上位と下位が逆だったならchdat[0]とchdat[1]を入れ替えればいいでしょう。 質問者さんの例に合わせて書くなら、こんな感じになります。 union { unsigned int intdat; unsigned char chdat[2]; } data; data.intdat = 555; dat1 = data.chdat[0]; dat2 = data.chdat[1];
お礼
皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。
- jacta
- ベストアンサー率26% (845/3158)
> dat2 = (char)data >> 8; ここが間違っていることは明らかですが、それ以外は処理系不明なので何ともいえません。 (int型が2バイトであること以外)処理系に依存しないようにするのであれば、 unsigned int data; unsigned char dat1,dat2; data = 555; dat1 = (unsigned char)data; dat2 = (unsigned char)(data >> CHAR_BIT); とするのが妥当でしょうね。
お礼
皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。
- ts244
- ベストアンサー率41% (53/127)
そのコードだと単に変数領域(RAM)にデータを書いてるだけでは?
お礼
皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。
- joqr
- ベストアンサー率18% (742/4026)
dat2 = (char)(data >> 8);
お礼
皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。
お礼
皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。