目次

ArduinoMega2560マルチ通信

 ArduinoMega2560は、シリアルインタフェースを
 0から3の4チャネル持ちます。



 チャネル0とチャネル1のデータ転送速度が異なる
 システムが必要となったので、次の仕様でUSB接続
 されているチャネル0で、チャネル1と外部装置の
 データ交換を試験してみます。



 システム構成を見ると、次のようになります。

 チャネル0がチャネル1の動作をモニタするので
 チャネル0を、デバッキングエイドにした。

 パーソナルコンピュータとチャネル0のインタフェースは
 データ交換するための受信割込みは、次のように定義して
 おきます。

void serialEvent()
{
  byte ch;

  if ( Serial.available() > 0 ) {
    /* get 1 character */
    ch = Serial.read();
    /* store */
    *(sbuf+sindex) = ch ;
    /* increment */
    sindex++ ;
    /* judge */
    if ( ch == '\r' ) {
      sindex = 0 ; 
      uflag  = ON ;
    }
  }
}

 USB/シリアルのチップを使うので、9600bps程度では
 パーソナルコンピュータからの1文字コマンドを受信
 バッファに格納するだけで充分。

 受信バッファは、次のように配列で確保すれば充分。

char sbuf[16] ;
byte sindex ;

 配列の中に情報格納するためのインデクスポインタに
 sindexを使います。

 コマンドとパラメータで構成したフレームの最後は
 '\r'として、検出したなら対応ブロックが動作できる
 ように、通知フラグにて、お知らせ。

 通知フラグでトリガーがかかると、次のように
 対応した処理を実行します。

  if ( uflag ) {
    /* clear flag */
    uflag = OFF ;
    /* execute command interpreter */
    execdebug();
  }

 チャネル1では、データ転送速度が高速なので
 取りこぼさないよう、リングバッファを採用。

 リングバッファを扱う関数は、以下。

char sbrbuf[128] ;
byte sbrdp ;
byte sbwdp ;
byte sbcap ;

void init_sbring()
{
  byte ii ;
  /* clear */
  for ( ii = 0 ; ii < 16 ; ii++ ) {
    *(sbrbuf+ii) = '\0' ;
  }
  sbrdp = 0 ;
  sbwdp = 0 ;
  sbcap = 0 ;
}

void put_sbring(char x)
{
  /* store */
  *(sbrbuf+sbwdp) = x ;
  /* update pointer */
  sbwdp++ ;
  sbwdp &= 0x7f ;
  /* update capacitor */
  sbcap++;
}

char get_sbring()
{
  char result ;
  /* get */
  result = *(sbrbuf+sbrdp) ;
  /* update pointer */
  sbrdp++ ;
  sbrdp &= 0x7f ;
  /* update capacitor */
  sbcap--;

 return result ;
}

byte get_sbring_size()
{
  return sbcap ;
}

void show_sbring()
{
  byte ii ;
  /* show */
  for ( ii = 0 ; ii < 128 ; ii++ ) {
    /* show 1 character */
    rs_putchar( *(sbrbuf+ii) );
    /* new line */
    if ( (ii % 16) == 15 ) crlf();
  }
}

 128バイトの配列を用意し、リード、ライトのポインタに
 使っている容量を計算しています。

 リングバッファを使うと、受信割込みハンドラは
 次のように記述できます。

void serialEvent1()
{
  byte ch ;
  byte sbn ;
  byte ii ;

  /* get code */
  sbn = Serial1.available() ;
  if ( sbn > 0 ) {
    for ( ii = 0 ; ii < sbn ; ii++ ) {
      /* get 1 character */
      ch = Serial1.read();
      /* store */
      put_sbring( ch );
      /* judge */
      if ( ch == 0x0a ) { sbuflag = ON ; }
    }
  }
}

 Serial1クラスでは、内部に64バイト程度の
 バッファを用意しているので、受信文字数を
 取得し、リングバッファに格納しておきます。

 データフレームは、ラインフィードで終了するとして
 1フレームがリングバッファに格納されたなら、通知
 フラグで、処理ブロックにトリガーを出力。

 通知フラグを貰ったブロックは、次のように必要な
 仕事を、下位へと渡します。

  if ( sbuflag ) {
    /* clear flag */
    sbuflag = OFF ;
    /* execute command interpreter */
    sbexec();
  }

 2台のArduinoMega2560は、次のようにブレッドボード経由で
 TxD、RxD、GNDを接続して実験しました。



 素麺の木箱にビスを立てて、ArduinoMega2560を挿し
 ブレッドボードのワイヤーで、クロス接続状態にし
 通信環境を整えています。

 それぞれのArduinoMega2560とは端末ソフトTeraTermで
 PC上からの操作ができるようにておきます。

 次のように2つの端末画面で、データ交換を確認。



 左と右で、役割を分担しています。

 左でパラメータを伴うコマンドを入力すると、右には
 送信文字を表示。表示と同時に、該当情報を返信。
 左の端末は、受信データを表示。

 PCとArduinoMega2560の間は、9600bpsでデータ交換しますが
 ArduinoMega2560の間は、115200bpsと高速で通信しています。

 この形態を使うと、Arduinoを他のマイコン基板用の
 デバッガに変身させることも可能になります。


目次

inserted by FC2 system