• ベストアンサー

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をフラッシュに書き込む。 未熟者でプログラムとして合っているのか解りません。 やり方として問題ないでしょうか? またもっと良い方法があればご教授願います。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.6

まず考えるべきは、フラッシュメモリの書き込んだデータは誰が使うのか? です。 自分(というか、そのシステム)だけでしか使わないのであれば、余り気にすることはありません。 この場合だと、 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進数で)きりの良い数のかけ算や割り算は、普通のコンパイラは、内部でシフトに置き換えますので。

new_okwave
質問者

お礼

皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。

その他の回答 (6)

回答No.7

>マイコンのフラッシュ領域にint型のデータ(2バイト)を1バイトづつ書き込む 8bitのIOポートからFIFOバッファを利用して読み書きするタイプなのかな? IOのアドレスをFportとすると unsigned int data; char *c; c = (char *)&data; Fport = c[0]; Fport = c[1]; という方法で書き込めます。書いた通りの順番に読み出せば復元できますから、バイト・オーダーとかは気にする必要はありません。

new_okwave
質問者

お礼

皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。

  • R32C
  • ベストアンサー率39% (115/290)
回答No.5

処理系依存の問題ですね。 エンディアンも含めた対応をここで回答してみます。 マイコンが何かはわかりませんが、ルネサスの純正コンパイラ(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

new_okwave
質問者

お礼

皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。

  • yama1718
  • ベストアンサー率41% (670/1618)
回答No.4

処理系に依存する方法ですが、共用体が使えるなら それを使った方がシフト演算などを使わずにスマートにできます。 下位バイトが先に来る(リトルエンディアン)の処理系なら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%E3%83%87%E3%82%A3%E3%82%A2%E3%83%B3
new_okwave
質問者

お礼

皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

> 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); とするのが妥当でしょうね。

new_okwave
質問者

お礼

皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。

  • ts244
  • ベストアンサー率41% (53/127)
回答No.2

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

new_okwave
質問者

お礼

皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。

  • joqr
  • ベストアンサー率18% (742/4026)
回答No.1

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

new_okwave
質問者

お礼

皆様、ご回答どうもありがとうございます。 マイコンはルネサスのR8Cでデータフラッシュに書き込みます。 データは自分でしか使用いたしません。 皆様から教えていただいたコード等を参考にやってみます。 まずはお礼のみで失礼いたします。

関連するQ&A

  • 1バイトデータの読み出しについて

    こんばんは。 すみません。文字操作?ポインタ操作が苦手なので教えてください。 以下のような構造体があり、その構造体から1バイトずつ読み出して 自作の関数のパラメータ(1バイト指定領域)に渡したいのですが、 構造体から1バイトずつデータを読み出すには、どのようにすればいいのでしょうか? typedef struct { PACKET_HEADER head; unsigned char Sp_Pr_St[1]; unsigned char ctrl_flow[1]; unsigned char product_org[10]; unsigned char product_name[10]; unsigned char product_ver[3]; }PRODUCT_RESPONS; typedef struct { unsigned char head; unsigned char type; unsigned char data_len; } HEADER; どうぞよろしくお願いします。

  • int型の変数値をバイト列としてコピー

    あるint型の変数に格納されている情報を、バイト列としてコピーする方法で困っています。 変数の入っている領域をそのままコピーしたいので、memcpyを使うかと思うですが、 コピーされた結果を見ると文字列の並びが逆転しているように見えます。 --サンプルコード抜粋 unsigned int i= 12345; unsigned char *c; c = (char *)malloc(sizeof(int)); printf("i_hex=%x\n",i); memcpy(c,(int *)&i,sizeof(int)); 出力結果 i_hex=3039 cの出力結果 3930000000 単純にmemcpyではダメなのでしょうか? 実行環境は、CentOS(32bit)+gccです。よろしくお願いします。

  • unsigned int型について

    C言語初心者です。 unsigned int型に関する質問です。 --------------------------------- #include <stdio.h> int main(void) { unsigned int in1 = 10; unsigned int in2 = -10; unsigned char ch1 = 10; unsigned char ch2 = -10; printf("in1 = %d\n", i); printf("in2 = %d\n", i); printf("ch1 = %d\n", ch1); printf("ch2 = %d\n", ch2); return 0; } --------------------------------- 上記のプログラムを作成して実行すると、結果は以下の通りです。 [実行結果] in1 = 10; in2 = -10; ch1 = 10; ch2 = 246; 変数in2の値を表示した結果に関してですが、 unsigned int型にも関わらず負の値「-10」が表示されるのは 何故でしょうか?

  • メモリをアドレスを直接指定して値を取得するには

    マイコンのプログラムを書いております。 やりたい事はC言語でフラッシュメモリの物理アドレスを直接指定してそのアドレスの値を1バイト読むことです。例えば0xF000番地のアドレスから1バイト読む場合、以下のソースコードで問題ありますでしょうか?なおアドレスは2バイトで表現されます。 unsigned char *p_value; unsigned char value; p_value=&value; p_value=0xF000; この時点で変数valueには0xF000番地の値が正確に代入されてますでしょうか? よろしくお願いします。

  • エンディアン:2バイトのデータをShort intにしたいのですが?

    1.Intelの CPU リトルエンディアンでの、問題です。 バイナリファイルをバイト単位で読込み、これを16ビットの整数にしたいのですが、以下のようにコーディングしましたが、うまくいきません。解決方法をご教示下さい。 char s[2]; short int x;   // 16ビットの整数です // s[0] s[1]に、データを読み込みます。 x = (short)(s[0] + 256 * s[1]); 2.同様の問題で、ビッグエンディアンの場合は、どうすればよいかも、ご教示下さい。 よろしくお願いします。

  • C言語でファイル読み書きを早くしたい。

    いつも利用させてもらって助かっています。 あるプログラムを作成しているのですが、ファイル入力の部分がネックとなってしまって、全体が使いものにならない状況に陥っています。 たくさんのデータをfread1回で読み込むことにより、読み込み速度はずいぶんと改善されましたが、まだ圧倒的に遅い状況です。システムコールを使いましたが、ほとんど改善されませんでした。 読み込み/書き込みの速度を改善する方法として,SSDメモリを使ったりする方法があると思いますが,プログラムの観点から改善できるところはないでしょうか? 下に、ファイル読み込みの部分だけ記述したコードを添付させて頂いたので、改善できる点があれば、御指摘頂けると助かります。 なお、前提として, (1)データはスタック領域だと不足するので、ヒープ領域に確保 (2)データファイルは改行無しの一連のデータ とします。 ちなみに、環境は OS   : CentOS5.3 memory   : 6GB コンパイラ : gcc です。 よろしくお願いします。 //----------------------------------------------------- //通常バージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; FILE *fp; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } fp = fopen("filein.dat", "rb"); fread( data, sizeof( unsigned char), (int)SIZE, fp ); fclose(fp); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; } //----------------------------------------------------- //readシステムコールを使ったバージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } int fd; fd = open( "filein.dat" ); read( fd, data, sizeof(unsigned char)*SIZE); close(fd); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ FILE *fp; fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; }

  • c言語でint配列をdoubleに変換

    c言語でマイコンプログラムを作成しています. int型の配列をdoubleに変換するために以下のプログラムを記述し,テストしました. int a[4] = {0,0,1,8}; char s[4]; double d; char *temp; sprintf(s,"%d%d%d%d",a[0],a[1],a[2],a[3]); //文字列charをdoubleに変換 d = strtod(s,&temp); 望む結果は 18 ですが,なぜか上記結果は 1800 となりました. 試しに int a[4] = {1,2,3,4}; と,1234と表示されました. 上記より,出力値が左詰めのようになっています. 試しにVisual Studio 2013 C++で同様のプログラムを実行すると,所望の結果を得ることが出来ました. プログラムがおかしいのでしょうか?それともマイコンのコンパイラのバグでしょうか? お分かりになられる方がいらっしゃいましたら,ご教授宜しくお願い致します.

  • int型の文字列について

    文字列を扱う場合はchar型をつかいますが、int型がchar型より大きいメモリ領域を確保しているとすると、int型で文字列を扱っても問題はないのではと思いました。 実際にやってみると、処理系によって問題なく作動するものとそうでないものが有りますが、基本的な考え方として文字列をint型で扱うことは問題があるのでしょうか? ご存知の方よろしくお願いいたします。 <補足> 要は、255以下の数字を扱うときに、char型でないといけないという制約はなく当然int型を使えるように、文字列においてint型を使うことは、基本的な考え方として問題なのかをお聞きしたい。 当然、処理系において、ルール的に禁じている場合は使えないということは理解できますが。

  • javaのbyte配列へintなどを埋め込む方法

    javaのbyte配列へintなどを埋め込む方法 java初心者です。データ編集がわからなくて悩んでいます。 下記のコードは"棒読みちゃん"といソフトへのTCPパケットを作成するコードです。 char buf[15]; *((short*)&buf[0]) = 0x0001; *((short*)&buf[2]) = speed; *((short*)&buf[4]) = tone; *((short*)&buf[6]) = volume; *((short*)&buf[8]) = voice; *((char* )&buf[10]) = 2; *((long* )&buf[11]) = len; 同じことをJAVAでしたいのですがわかりません。 (バイト型配列へint,long型を簡単に埋め込む方法がわかりません) よろしくお願いします。 よかったら、こちらもお願いします memcpy(&buf[15],message,strlen(messege)); TCPパケットのようなデータ処理が頻繁にある場合、 このようなコードは、どうしたらいいでしょうか? *((unsigned char* )&buf[15]) = message; CとJAVAになってますが、このような処理を簡単に書けないでしょうか?

    • ベストアンサー
    • Java
  • 1バイトデータの扱い方

    IPアドレスを4バイトのデータとして扱おうと思ったのですが、 どうしたら良いのか方法がわかりません。 Cなら、 int IPData1=255; char chIP[4]; chIP[0]=(char)IPData1; というような感じだと思うのですが、PHPではどうしたらよいのでしょうか。

    • ベストアンサー
    • PHP

専門家に質問してみよう