お世話になっております。現在、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 は 1行(=char の配列)にカンマで区切られて情報が配置されるので、1文字ごとに入力される文字を配列にまとめる必要があります。
例えば
const int CsvDataSize = 100; // CSV データの最大文字数を 100と仮定 char csvData[CsvDataSize + 1]; int i; for (i = 0; i < CsvDataSize;) { int recievedChar; recievedChar = sci_recv(); if (recievedChar == '\r' || recievedChar == '\n') { if (i > 0) { break; } } else { csvData[i++] = (char)recievedChar; } } csvData[i] = '\0';
こんな感じですね。
> 配列?で間違ってると思うのですが、初心者なので、何がどう間違っているのかよく分かりません。
Amazon 辺りで評判の良い C の入門書でも調べて読まれたらいかがですか。
ミントさん、こんにちは。NoMaYと申します。投稿されていたソースを見たのですが、最初の投稿時のソースは以下のスレッドを参照されたものかな、と思ったのですが、そこにfujitaさんのソースを嵌め込んだものを投稿されたのですよね。・ 初歩の質問ですみません。シリアル通信ができません。・ RX621マイコンでのSCI通信についてこの嵌め込んだソースなのですが、動かないのは承知の上でコンパイル出来るかどうか見ようとしたら見知らぬワーニングが出たので質問をされた、というのではなくて、きっとこれで動くだろうと思ってコーディング/コンパイルしたらワーニングが出たので質問をされた、という経緯でしょうか? 後者だとすると、藤田さんが仰ったように、入門書を読まれた方が良いように思います。一応、もしかするとArduinoやmbedは経験済みで、その時のやり方が出てしまったのだろうか、とは思いましたので、それらのAPIを見てみたのですが、どうもそうでもないようですし、、、Arduino シリアルAPIgarretlab.web.fc2.com/arduino_reference/.../serial/以下はGitHubにあるヘッダファイルです(上級者向けかと思うので灰色文字にしました)GitHub: HardwareSerial.hGitHub: Stream.hGitHub: Print.hmbed APIdocs.mbed.com/.../Serial/以下はGitHubにあるヘッダファイルです(上級者向けかと思うので灰色文字にしました)GitHub: SerialBase.hGitHub: Stream.hそれで、144行目の「dataが設定されたが使われていない」というワーニングですが、注意して読むと気付くのですが、単に「使われていない」という警告では無く、「設定されたが使われていない」という警告であり、この時の「使われていない」というのは「参照されていない」という意味なのです。(⑤は元々はsci_send(data);だったかと思いますが、それに戻すと「参照されていない」状態が解消されるので出なくなります。もっとも、今度は④のfloat X= Data[0];のXが「参照されていない」状態になりますので、Xに対して同じ警告が出るようになりますが、、、)[余談]思うところあって、以下のソース(inoファイル)をArduino 1.8.3でArduino UNO用にコンパイルしてみたところ、インストール(私の場合は習慣でZIPファイルをダウンロードして解凍)した直後のArduino IDEの設定では、ワーニング無し、エラー無し、でコンパイルが通りました。
void my_main(void)//メイン関数{ unsigned char data; //受信データを格納する変数の宣言 setup_clock(); setup_port(); //ポートの振り分け setup_sci(); //シリアル通信の初期設定 while(1){ data = sci_recv(); //①受信したデータをdataに格納する float a, b, c, d, e; const char Data[] = "data" ; //② sscanf(Data,"%f,%f,%f,%f,%f", &a, &b, &c, &d, &e); //③ float X= Data[0]; //④ sci_send(X); //⑤ }}void setup() {my_main();}void loop() {}void setup_clock() {}void setup_port() {}void setup_sci() {}unsigned char sci_ch = '*';unsigned char sci_recv() {return sci_ch;}void sci_send(unsigned char ch) {sci_ch = ch;}
画面コピーただし「dataが設定されたが使われていない」というワーニングは、Arduino IDEの設定を変えてコンパイラの警告の設定を[より多く]もしく[全て]にすると、出るようになりました。とは言え、この設定を[全て]にした場合でも、出るワーニングは以下のこれのみでした。
C:\Temp\UserName\arduino_modified_sketch_623403\sketch_jun10a.ino: In function 'void my_main()':C:\Temp\UserName\arduino_modified_sketch_623403\sketch_jun10a.ino:3:19: warning: variable 'data' set but not used [-Wunused-but-set-variable] unsigned char data; //受信データを格納する変数の宣言 ^
画面コピー
こんにちは。本を買うしかなかった昔と違って、今ならウェブサイトも選択肢かと思い、少し探してみました。Google検索: C言語 入門 OR 学習 サイトパラパラっと見た印象では、以下の2つの昔ながらのウェブサイトが良さげでした。(ウェブサイトとしては、動画サイトやスライドサイトもあったのですが、有料コンテンツの一部を無料公開しているような雰囲気でしたので、そちらは全く見ませんでした。)苦しんで覚えるC言語9cguide.appspot.com/「苦しんで覚えるC言語(苦C)は、初心者を対象としたC言語入門サイトです。C言語の基本機能を体系立てて解説しており、市販書籍と同等以上の完成度です。」scanf関数(sscanf関数の同類)についてのページstrtok関数を利用する方法についてのページRulzのスレッドでのstrtok関数についてのトピックス(上級者向け)0から始めるC言語学習帳effy.ldw.jp/c/「本サイトは、ソフトバンク・パブリッシング(現ソフトバンク・クリエイティブ)より発刊されていた雑誌「Cマガジン」で私が2002年4月から1年間にわたって連載してきたC言語入門の記事を、編集部より許可を頂き加筆訂正し公開するものです。」scanf関数(sscanf関数の同類)についてのページ上に書いたウェブサイトの他にも、Rulzのページ上部のリンクを辿って、ルネサスさんの半導体セミナのテキストを閲覧出来るページへも行ったのですが、立ち読みコーナーというところで公開されていた以下のテキスト(PDF)を見た印象では、上に書いたウェブサイトが良さげでした。基礎技術セミナー(一部のみ公開)・ プログラムを書くためのロジック思考入門・ 組み込みC言語入門 ~文法編~・ 組み込みC言語入門 ~実装編~・ ポインタ徹底活用・ C言語アドバンスはじめてシリーズ(一部のみ公開)・ はじめてのC言語プログラミング
> 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と仮定
と修正してください。