これまでで一番「情けなかったとき」はいつですか?

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をフラッシュに書き込む。

未熟者でプログラムとして合っているのか解りません。
やり方として問題ないでしょうか?
またもっと良い方法があればご教授願います。

A 回答 (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進数で)きりの良い数のかけ算や割り算は、普通のコンパイラは、内部でシフトに置き換えますので。
    • good
    • 0
この回答へのお礼

皆様、ご回答どうもありがとうございます。
マイコンはルネサスのR8Cでデータフラッシュに書き込みます。
データは自分でしか使用いたしません。

皆様から教えていただいたコード等を参考にやってみます。
まずはお礼のみで失礼いたします。

お礼日時:2010/10/04 01:14

>マイコンのフラッシュ領域にint型のデータ(2バイト)を1バイトづつ書き込む



8bitのIOポートからFIFOバッファを利用して読み書きするタイプなのかな?
IOのアドレスをFportとすると

unsigned int data;
char *c;

c = (char *)&data;
Fport = c[0];
Fport = c[1];

という方法で書き込めます。書いた通りの順番に読み出せば復元できますから、バイト・オーダーとかは気にする必要はありません。
    • good
    • 0
この回答へのお礼

皆様、ご回答どうもありがとうございます。
マイコンはルネサスのR8Cでデータフラッシュに書き込みます。
データは自分でしか使用いたしません。

皆様から教えていただいたコード等を参考にやってみます。
まずはお礼のみで失礼いたします。

お礼日時:2010/10/04 01:14

処理系依存の問題ですね。


エンディアンも含めた対応をここで回答してみます。
マイコンが何かはわかりませんが、ルネサスの純正コンパイラ(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
    • good
    • 0
この回答へのお礼

皆様、ご回答どうもありがとうございます。
マイコンはルネサスのR8Cでデータフラッシュに書き込みます。
データは自分でしか使用いたしません。

皆様から教えていただいたコード等を参考にやってみます。
まずはお礼のみで失礼いたします。

お礼日時:2010/10/04 01:15

処理系に依存する方法ですが、共用体が使えるなら


それを使った方がシフト演算などを使わずにスマートにできます。
下位バイトが先に来る(リトルエンディアン)の処理系なら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];

参考URL:http://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%B3% …
    • good
    • 0
この回答へのお礼

皆様、ご回答どうもありがとうございます。
マイコンはルネサスのR8Cでデータフラッシュに書き込みます。
データは自分でしか使用いたしません。

皆様から教えていただいたコード等を参考にやってみます。
まずはお礼のみで失礼いたします。

お礼日時:2010/10/04 01:15

> 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);

とするのが妥当でしょうね。
    • good
    • 0
この回答へのお礼

皆様、ご回答どうもありがとうございます。
マイコンはルネサスのR8Cでデータフラッシュに書き込みます。
データは自分でしか使用いたしません。

皆様から教えていただいたコード等を参考にやってみます。
まずはお礼のみで失礼いたします。

お礼日時:2010/10/04 01:16

そのコードだと単に変数領域(RAM)にデータを書いてるだけでは?

    • good
    • 0
この回答へのお礼

皆様、ご回答どうもありがとうございます。
マイコンはルネサスのR8Cでデータフラッシュに書き込みます。
データは自分でしか使用いたしません。

皆様から教えていただいたコード等を参考にやってみます。
まずはお礼のみで失礼いたします。

お礼日時:2010/10/04 01:16

dat2 = (char)(data >> 8);

    • good
    • 0
この回答へのお礼

皆様、ご回答どうもありがとうございます。
マイコンはルネサスのR8Cでデータフラッシュに書き込みます。
データは自分でしか使用いたしません。

皆様から教えていただいたコード等を参考にやってみます。
まずはお礼のみで失礼いたします。

お礼日時:2010/10/04 01:16

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報