「Arduinoでラインを処理する」に基づく

今日Geektimesの投稿を読んで、自分の経験を共有したいと思います。 Arduinoの長所と短所については説明しませんが、次の項目を適用したプロジェクトの条件はそれについて行う必要があります。 一番下の行は、デバイスを制御するための端末をユーザーに提供する必要があるということです。 したがって、作品のごく一部が弦楽器の作品ではありません。 提案された解決策を適用するかどうか-誰もが自分で決定できるようにします。



Stringクラスを拒否することにしました:リンカエラー 。 Stringクラスを使用しようとしたときにのみ取得できました。



何が必要でしたか? ユーザーが入力した行の情報出力と処理。 例:

イーサネットコントローラー-OK

静的モード

> 時間

2015-11-16 22:35:27


実際に、ドレインを比較する必要があります。 いいえ。まず、テキストを区切り文字(スペースなど)を使用してフラグメントに分割する必要がありますが、それでも行を比較します。 「1つ、2つのチームと誤算された」チームがあったので、テキストの断片への内訳を削除しました。 上記のエラーのため、Stringクラスを使用できませんでした。 ArduinoはAVR-libcライブラリを使用しています。最初に参照するのが妥当です。

何がありますか?



  1. stdlib.h-数値と文字列の相互変換のための関数(両方向)。
  2. string.h-文字列を操作するための関数。 私たちの主な関心。
  3. stdio.h-標準入出力の関数。


これは機能に限定されません。 言及はタスクに関連しています。



だから、知り合いにはNo.1をお勧めします-突然どこかで別に便利です。 それ自体では、 string.hに対してのみ使用されます。



No. 2- memset関数を使用してバッファを埋めるかクリアします。memcmp-比較のために。 比較するフラグメントの長さを明示的に制限する必要があるため、 strcmpは使用しません。 No. 3-フォーマット済みの読み取りと出力の場合: sprintfsprint_Psscanfsscanf_P 接尾辞_Pを持つ関数は、フォーマット文字列がPROGMEMプログラムのメモリから取得されるという事実によって区別されます。これは、ArduinoライブラリのマクロF()でもあります。



ちなみに
ところで、個別の文字getcputcのI / O関数を完全に実装すると、ファイルを操作するための標準入力、出力、エラー、およびファイルストリームがあります(ある場合)。 通常、これを行うには、標準入力および出力で機能するputchar()およびgetchar()マクロをオーバーライドします。



私の文字列比較は次のようになります。



if ( memcmp(str ,"statlist" ,8)==0 ) { // your code here }
      
      





おそらく、行の先頭が比較されることに言及する価値があります。 memmemを使用して、フラグメントを検索できます。



siの文字列
C strの文字列 、それらはchar * -これはcharシーケンスの先頭へのリンクであり、最後の値は値0x00です。 したがって、それらはどこかに配置する必要があります。 たとえば、配列内。 または、 malloccallocfreeを使用します。 間違いを犯さないの は、プログラマーの配置と制御に対する責任が長いことです。



つまり、チーム検索は次のようになります。



  if ( memcmp(str ,"statclear", 9)==0 ) { memset(journal, 0, sizeof(jrn_rec_t)*JRN_REC_NUM ); Serial.println( F("ok") ); }else if ( memcmp(str ,"statlist" ,8)==0 ) { funcStatlist(); }else if ( memcmp(str ,"cfgshow", 7)==0 ) { funcCfgShow(); }else if ( memcmp(str ,"timeset", 7)==0 ) { funcTimeSet( str); // setup date and time YYYY-MM-DD hh:mm:ss }else if ( memcmp(str ,"cfgset", 6)==0 ) { funcCfgSet( str); //funcPingdel( str); }else if ( memcmp(str ,"time", 4)==0 ) { funcTime(); // print date and time from RTC }else if ( memcmp(str ,"help", 4)==0 ) { // print short help Serial.println( F(" help\r\n statlist statclear\r\n time timeset\r\n cfgshow cfgset") ); }else{ Serial.print( F("unknow cmd> ")); Serial.println( str); }
      
      





明らかでない瞬間
チームは、上記のフラグメントで最初に行く必要があるより長い長さの同じ行です。 なぜだと思う?



次のように行を「収集」します。許容される行の長さを超えるか、改行文字\ rまたは\ nのいずれかが見つかるまで、ポートからバイトを読み取ります。



読書線
改良することをお勧めします...それがある限り。 メインリングで常に呼び出されます。 作業がない場合は、できるだけ早く終了し、 falseを返します 。 新しい行を入力した場合-true。



 bool readln( HardwareSerial &uart, char *outbuf) // return true when find CR, LF or both and if size limit { static char mybuf[SBUF_SZ] = { 0 }; static char idx = 0; while (uart.available()) { if ( uart.peek()!= '\r' && uart.peek()!= '\n' ) { mybuf[ idx++ ] = uart.read(); } else {//  CR uart.read(); if ( uart.peek()=='\n' || uart.peek()=='\r' ) uart.read(); if ( idx == 0 ) { return 0; } mybuf[ idx++ ] = '\0'; //  0 memcpy( outbuf, mybuf, idx); //  idx = 0; return 1; } if ( idx >=(SBUF_SZ-1) ) { //      mybuf[ SBUF_SZ-1 ] = '\0'; //  0 memcpy( outbuf, mybuf, 32); //  idx = 0; return 1; } } return 0; }
      
      







フォーマットされた入出力も非常に便利です。 たとえば、入力された日付と時刻で文字列を解析すると、次のようになります。
 sscanf_P(str, (const char *)F("%*s %d-%d-%d %d:%d:%d"), &y, &m, &d, &hh, &mm, &ss)
      
      





IP出力用の文字列を取得する:



 sprintf_P(buff, (const char *)F("Your IP: %d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]);
      
      





書式文字列の詳細については、たとえば、scanfおよびhere (printf)を参照してください。



それだけです。 この資料が誰かがArduinoを「取り除く」のに役立つか、単に彼らのプログラムをより良く、より短い時間で書くのを助けることを願っています。 しかし、より一般的な状況は、 配線の制限を回避することです。



元の記事の著者に感謝します。この資料をタイプさせてくれただけの場合。



All Articles