お世話になっております。現在、PCとRX621間でBluetoothを用いたシリアル通信を行っています。
今、PC側に保存された5つのエクセルデータ(~.csv //1秒ごとに値が更新されます。)
をTeraTermを用いてRX621に送信し、callbackでPC側に表示させることができました。(PC側のTeraterm上には -0.0611,0.0109,0.048,0.1388,0.3029と表示されていることから、シリアル通信はできていると思っています。)
次に、RX621が受信した上記のデータをカンマごとに区切り、A,B,C,D,Eのそれぞれに分けて計算をしたいと思っていますが、受信したデータを分割して配列するために、どのようなコードを記述すればよいか分かりません。ご教授お願いいたします。
念のために、以下にシリアル通信のプログラムを貼ります。RX621が受信したデータは "ch"に入れています。
unsigned char sci_recv(void){ unsigned char ch;
#ifdef USE_IR while (IR(SCI1,RXI1) == 0) ;#else while (SCI1.SSR.BIT.RDRF == 0) ;#endif
ch =SCI1.RDR;
#ifdef USE_IR IR(SCI1,RXI1) = 0;#endif return ch;}
void sci_send(unsigned char ch){#ifdef USE_IR while (IR(SCI1,TXI1) == 0) ; IR(SCI1,TXI1) = 0;#else while (SCI1.SSR.BIT.TDRE == 0) ;#endif
SCI1.TDR = ch;}
sscanf() が使えればそれを使うだけですね。
$ cat -n test.c 1 #include <stdio.h> 2 3 int main(void) 4 { 5 float a, b, c, d, e; 6 const char data[] = "-0.0611,0.0109,0.048,0.1388,0.3029"; 7 sscanf(data, "%f,%f,%f,%f,%f", &a, &b, &c, &d, &e); 8 printf("a = %f, b = %f, c = %f, d = %f, e = %f\n", a, b, c, d, e); 9 } $ gcc -Wall -Wextra -O2 test.c ; ./a a = -0.061100, b = 0.010900, c = 0.048000, d = 0.138800, e = 0.302900 $
>fujita様、わわい様 上記のサンプルを参考にプログラムを修正してみました。 シリアル通信で受信したデータの内、1つだけ取り出して送信するというプログラムです。 ①.シリアル通信で受信したcvsデータをdataに格納する。 ②.配列Data[ ] に dataを代入する。 ③.Data[ ] に入れたcvsデータをカンマ区切りにしてa~eの5つに分割する。 ④.XにData[0] (=a)を代入する。 ⑤.シリアル通信でXを送信する。 配列?で間違ってると思うのですが、初心者なので、何がどう間違っているのかよく分かりません。 エラーとしては156、157、159行で「実行文の後、宣言が現れないかもしれない」、警告としては161行で引数が非対応、144行でdataが設定されたが使われていない。 144行目の警告ですが、while文内で使っているので、なぜこの警告が出るのか分かりません。 void main(void)//メイン関数 { 144 unsigned char data; //受信データを格納する変数の宣言 setup_clock(); setup_port(); //ポートの振り分け setup_sci(); //シリアル通信の初期設定 while(1){ data = sci_recv(); //①受信したデータをdataに格納する 156 float a, b, c, d, e; 157 const char Data[] = "data" ; //② 158 sscanf(Data,"%f,%f,%f,%f,%f", &a, &b, &c, &d, &e); //③ 159 float X= Data[0]; //④ 161 sci_send(X); //⑤ } }
> CSVが文字列であるというヒントをうけて、まずは受信した文字列をカンマ区切りで配列に格納しようと考えました。
while(1){ data = sci_recv(); // シリアル通信で受信したデータ(文字列)をdataに格納する
「文字」と「文字列」が異なることに理解が及んでない様見受けられます。購入された本でその辺りの説明を良く読み直されることをお勧めします。
なお、受信した「文字」を「文字列(=文字の配列)」に格納する方法は既に例示しています。
japan.renesasrulz.com/.../22828
> なぜ、char型の配列csvDataをだた宣言しただけであるのにエラーがでるのですか?
C 言語の仕様によっては配列の大きさを変数で指定できないので
const int CsvDataSize = 100; // CSV データの最大文字数を 100と仮定
は
#define CsvDataSize 100 // CSV データの最大文字数を 100と仮定
と修正してください。
> 配列のサイズの指定は定数じゃないとダメってことですね。
C89 とそれ以前では配列定義時の要素数は定数式である必要がありましたが C99 では可変長配列が仕様として採用され変数での指定が可能になりました。現在市販されている C 言語入門の書籍の多くは C99 かそれ以降の仕様で書かれていると思います。
RX の純正コンパイラである CC-RX の最新の版 V2.06.00 ではコンパイルオプション `-lang=c' か `-lang=c99' で C89 と C99 を選択できますが、C99 を選んでも可変長配列はなんでか
E0520028:Expression must have a constant value
エラーとなるようです。
自己レス
> C99 を選んでも可変長配列はなんでかエラーとなるようです。
https://www.renesas.com/ja-jp/products/software-tools/tools/compiler-assembler/compiler-package-for-rx-family.html
> 特 長 > ANSI規格準拠 > C89、C99(可変長配列を除く)、C++言語をサポート
仕様の模様。
> C99の可変長配列ってのはAUTO変数限定ですわな
前提としてそういう話をしてますよ。
http://japan.renesasrulz.com/cafe_rene/f/forum5/4361/rx621-csv/22828#22828
const int CsvDataSize = 100; // CSV データの最大文字数を 100と仮定 char csvData[CsvDataSize + 1]; int i; for (i = 0; i < CsvDataSize;) {
MISRA-C のルールに可変長配列の使用禁止があり、言語仕様としてそれを採用している気がします。
https://www.google.co.jp/search?q=MISRA-C+%22variable-length+array+types%22