こんばんは、NAKAといいます。
初心者あるあるで申し訳ないんですが、C言語を教えてください。
8バイト(DATA[0]~DATA[7])の送受信データをやり取りしてます。
配列データのDATA[0]=0x12,DATA[1]=0x34 から変数SPEED=0x1234というデータを作りたく、両者を共用したいので
struct{ union { struct { unsigned short SPEED; unsigned short RPM; unsigned short NE; unsigned char SIG1; unsigned char SIG2; }SIG; unsigned char DATA[8]; }BYTE; }TXRX;
配列と構造体を共用体として宣言しました。
配列に
TXRX.BYTE.DATA[0] = 0x12; TXRX.BYTE.DATA[1] = 0x34; TXRX.BYTE.DATA[2] = 0x56; TXRX.BYTE.DATA[3] = 0x78; TXRX.BYTE.DATA[4] = 0x9A; TXRX.BYTE.DATA[5] = 0xBB; TXRX.BYTE.DATA[6] = 0xCC; TXRX.BYTE.DATA[7] = 0xDD;
ようにデータをいれたのですが、エンディアンが逆なので
のようにSPEED=0x1234 となってほしいのですが SPEED=0x3412となってしまいます。
当然
TXRX.BYTE.SIG.SPEED = 0x1234;
とするとDATA[0]に0x34、DATA[1]に0x12が入っちゃいます。
SPEED=0x1234と入るように作るにはどうすれば良いのでしょうか?
あぁ情けない!(T_T)
NAKAさん、こんにちは。NoMaYです。何かC言語でやり方があったような気がするけれども???と感じているのは、以下の別の話だったりしないでしょうか?(推測ですけど、、、) コンパイラの種類が書かれていなかったので、とりあえずCC-RXでプロジェクトを作って添付してみました。プロジェクトのファイル一式 (RX621 SIM、CS+プロジェクト(rcpeファイル同梱))issue_20190309.zipデータのオフセット位置を構造体定義に任せる & 値を取り出すマクロ & 値を設定するマクロ
#pragma packstruct TXRX_USVAL{ unsigned char val_h; unsigned char val_l;};union{ struct { struct TXRX_USVAL SPEED; struct TXRX_USVAL RPM; struct TXRX_USVAL NE; unsigned char SIG1; unsigned char SIG2; }SIG; /* とりあえず以下は残しておきました */ struct { unsigned char DATA[8]; }BYTE;}TXRX;#pragma packoption#define TXRX_GET_SPEED(txrx)\ ((unsigned short)((txrx.SIG.SPEED.val_h << 8) | txrx.SIG.SPEED.val_l))#define TXRX_SET_SPEED(txrx, speed)\ do{\ txrx.SIG.SPEED.val_h = (unsigned char)(speed >> 8);\ txrx.SIG.SPEED.val_l = (unsigned char)speed;\ }while(0)
debug_val = TXRX_GET_SPEED(TXRX); TXRX_SET_SPEED(TXRX, 0xABCD);
[追記]もしRXマイコンだったとしたら、実行時間を1クロックでも削る必要がある場合には、CC-RXの組み込み関数であるrevw()をマクロ内で使う手もあります。(TXRX_USVALの定義も共用体へ変更します。)プロジェクトのファイル一式 (RX621 SIM、CS+プロジェクト(rcpeファイル同梱))issue_20190309B.zip
union TXRX_USVAL{ struct { unsigned char val_h; unsigned char val_l; }VAL; unsigned short val_ushort_internal_use_only;};union{ struct { union TXRX_USVAL SPEED; union TXRX_USVAL RPM; union TXRX_USVAL NE; unsigned char SIG1; unsigned char SIG2; }SIG; /* とりあえず以下は残しておきました */ struct { unsigned char DATA[8]; }BYTE;}TXRX;#pragma packoption#define TXRX_GET_SPEED(txrx)\ ((unsigned short)revw(txrx.SIG.SPEED.val_ushort_internal_use_only))#define TXRX_SET_SPEED(txrx, speed)\ do{\ txrx.SIG.SPEED.val_ushort_internal_use_only = ((unsigned short)revw(speed));\ }while(0)
皆さん、おはようございます&ありがとうございます、NAKAです。 実は、 通信はCANでch1バスで受けたID100のデータ一部をch2バスのID200の違う位置にビットアサインし 流すみたいなことを簡単にやりたいと思いました。 データはIDごと最大8バイトですが、IDごとに固定のバイト単位ではなく、中途半端な12bitが バイトをまたいで配置されていたり、スイッチなどは1bitが混じってたりします。 しかもch1⇒ch2に渡す信号のデータbit数が変わるものもあります。(T_T) なので、ch1バス受信はIDごとの配列で受け、送信時IDごとに共用化された構造体の信号を、送信 する構造体信号に入れ直し(複数)、ch2バスに入れ直した構造体と共用された配列で送信しようと 考えました。 今までは、普通にビットシフトしたりマスクかけたりしてやってましたが、NAKAはおっちょこちょい で時々凡ミスしちゃうため、信号名になっていたらミスが無くなるかな?と考えました。 やっぱり結構複雑で構造体を作る時点で間違いを起こしそうですね!(*_*; 一番、シンプルな方法をもう少し検討したいと思います。 皆さん!本当にありがとうございました。_(._.)_
NAKAさん、こんにちは。NoMaYです。余りスレッドを引き延ばすつもりは無いですが、やりたかったことのイメージは、こんな感じですか?データとCPUのエンディアンが同じなら、素朴にビットフィールドを使って実現出来そうなことに思います。データとCPUのエンディアンが異なる今回の場合、更に、#pragma bit_order leftを併用すれば良いような気がします。([追記] ←これは#pragma bit_order leftでは片付かない話のような気がして来ました。すみません。) 具体的なデータの構造を教えて頂ければ、もう少し考えを進められそうですが、さすがにそれは業務上無理そうですかね?(やりたかった事が私がイメージしたようなことであれば、ですが、、、) あと、教えて頂ければと思うのは、コンパイラが何か?ですね。
データのエンディアンはビッグエンディアンCPUのエンディアンはリトルエンディアン
ch1バスのデータ (↓のch2バスのデータとはデータの構造が異なる)
8バイト12bitがバイトをまたいで配置スイッチなどは1bitが混じってたりch1⇒ch2に渡す信号のデータbit数が変わるものもある
ch2バスのデータ (↑のch1バスのデータとはデータの構造が異なる)
やりたかった事?
ch2.SPEED = ch1.SPEED;ch2.SW = ch1.SW;等々
NoMaY先生、いつも!いつも!ありがとうございます。NAKAです。 まさにそんな感じです。 配列DATA[8]とSPEED、SWなどの構造体が共用されており 受信 CAN_1ch_RX(ID_100.DATA); CAN_1ch_RX(ID_200.DATA); 送信
ID_100.SPEED=ID_100.SPEED+0x1000; //※時々 ID_300.SPEED = ID_100.SPEED; ID_300.SW=ID_200.SW; CAN_2ch_TX(ID_300.DATA); みたいにできたらなと思いました。 コンパイラはCC-RX(RX63N)やCC-RL(RL78/F15)などです。 ビットシフトやマスクで何とか並べ替えは出来てはいるのですが(汗) そのうち間違えそうな気がして........
NAKAです。 前の返信を書いてて思ったのですが、別にエンディアンが逆さのままでもいいのかな?という気に なってきました。値をいじるときだけ気を付けて、受信で逆さになっても結局、送信でまた逆さになるなら そのままでいいのかな?もう少しよく考えてみます。
NAKAさん、こんにちは。NoMaYです。>値をいじるときだけ気を付けて気を付ける、という意気込みだけでは間違えそうな気がします、、、せめて変数の末尾に_BE_DATA等付けて気付き易くするとか、でしょうか、、、あと、ベタなネーミング/やり方ですが、以下のようにいっそのことバラバラにしてしまうとか、、、
union{ struct { unsigned char SPEED_h; unsigned char SPEED_l; unsigned char RPM_h; unsigned char RPM_l; unsigned char NE_h; unsigned char NE_l; unsigned char VAL_h4:4; /* DATA[6] bit3-bit0 */ unsigned char SIG1:2; /* DATA[6] bit5,bit4 */ unsigned char SIG2:2; /* DATA[6] bit7,bit6 */ unsigned char VAL_l8; }SIG; unsigned char DATA[8];}CH1;union{ struct { unsigned char SPEED_h; unsigned char SPEED_l; unsigned char RPM_h; unsigned char RPM_l; unsigned char NE_h; unsigned char NE_l; unsigned char VAL_h6:6; /* DATA[6] bit5-bit0 */ unsigned char SIG1:2; /* DATA[6] bit7,bit6 */ unsigned char VAL_l8; }SIG; unsigned char DATA[8];}CH2;
CH2.SIG.SPEED_h = CH1.SIG.SPEED_h + 0x10; CH2.SIG.SPEED_l = CH1.SIG.SPEED_l; CH2.SIG.RPM_h = CH1.SIG.RPM_h; CH2.SIG.RPM_l = CH1.SIG.RPM_l; CH2.SIG.NE_h = CH1.SIG.NE_h; CH2.SIG.NE_l = CH1.SIG.NE_l; CH2.SIG.SIG1 = CH1.SIG.SIG1; CH2.SIG.VAL_h6 = CH1.SIG.VAL_h4 + 0x20; CH2.SIG.VAL_l8 = CH1.SIG.VAL_l8;