RX621でシリアル通信したcsvファイルを分割したい

お世話になっております。現在、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;
}

Parents
  • 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

  • >fujitaさん
    japan.renesasrulz.com/.../22828

    ご教授いただいた上記のプログラムで疑問があります。
    char csvData[CsvDataSize + 1];
    が「式の値が定数ではない」というエラーがでたのですが、なぜ、char型の配列csvDataをだた宣言しただけであるのにエラーがでるのですか?
  • > なぜ、char型の配列csvDataをだた宣言しただけであるのにエラーがでるのですか?

    C 言語の仕様によっては配列の大きさを変数で指定できないので

        const int CsvDataSize = 100;        // CSV データの最大文字数を 100と仮定
    

        #define CsvDataSize 100        // CSV データの最大文字数を 100と仮定
    

    と修正してください。

  • わわいです
    配列のサイズの指定は定数じゃないとダメってことですね。
    どうも基本的なところから理解が足りないようなので、まずはC言語の基礎から勉強なさってはどうでしょうか
  • > 配列のサイズの指定は定数じゃないとダメってことですね。

    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変数限定ですわな
    まあ、スタックを消費するので、組込系としてはあんましありがたくもなしってところで。
    #AUTO変数の宣言位置の制限がないのは便利ですねー
  • > 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

  • > fujitaさんのサンプルプログラムにポインタを上手く組み合わせることで、無事解決することができました。
    ありがとうございました。
Reply Children
No Data