Technical Information/etc.

Edit  

Seeeduino XIAO のSerialの増設方法 2

2021/3/3

Technical Information/etc./XIAO Serial Extension で説明した方法ではWireを使用するときにSERCOMの競合エラーが発生するので、対策した方法を説明します。

WSB000008.JPG
WSB000557.PNG

 
Edit  

方針

  • 既存の公式ライブラリを流用する

 
Edit  

調査内容

  • XIAOで使用しているマイコン ATSAMD21G18 のデータシートより各ピンへ割り当てられるペリフェラルを調査すると、4pin, 5pin,9pin,10pinにシリアルペリフェラルが割り当てられそうです。

    SAMD215_Port.png

    WSB000562.PNG

 
Edit  

ライブラリ変更内容

  • C:\Users\Username\AppData\Local\Arduino15\packages\Seeeduino\hardware\samd\1.7.8\variants\XIAO_m0\variant.cpp *1の変更は必要ありませんので、オリジナルの状態に戻します。
  • C:\Users\Username\AppData\Local\Arduino15\packages\Seeeduino\hardware\samd\1.7.8\variants\XIAO_m0\variant.h の172行目(// Serial1 の一連の記述のあとで、#endif // __cplusplus の前) に、下記内容を追加:
    // Serial2
    extern Uart Serial2;
    #define PIN_SERIAL2_TX       (4ul)
    #define PIN_SERIAL2_RX       (5ul)
    #define PAD_SERIAL2_TX       (UART_TX_PAD_0)
    #define PAD_SERIAL2_RX       (SERCOM_RX_PAD_1)
    // Serial3
    extern Uart Serial3;
    #define PIN_SERIAL3_TX       (10ul)
    #define PIN_SERIAL3_RX       (9ul)
    #define PAD_SERIAL3_TX       (UART_TX_PAD_2)
    #define PAD_SERIAL3_RX       (SERCOM_RX_PAD_1)
  • C:\Users\wdn\AppData\Local\Arduino15\packages\Seeeduino\hardware\samd\1.7.8\libraries フォルダに Serial2 フォルダを作成し、そのフォルダに下記に示す2つのファイルを作成します。
    • Serial2.h
      #ifndef Serial2_h
      #define Serial2_h
      
      #include "variant.h"
      
      void SERCOM2_Handler(void);
      
      #endif
    • Serial2.cpp
      #include "Serial2.h"
      
      Uart Serial2( &sercom2, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX ) ;
      
      void SERCOM2_Handler()
      {
        Serial2.IrqHandler();
      }
  • C:\Users\wdn\AppData\Local\Arduino15\packages\Seeeduino\hardware\samd\1.7.8\libraries フォルダに Serial3 フォルダを作成し、そのフォルダに下記に示す2つのファイルを作成します。
    • Serial3.h
      #ifndef Serial3_h
      #define Serial3_h
      
      #include "variant.h"
      
      void SERCOM0_Handler(void);
      
      #endif
    • Serial3.cpp
      #include "Serial3.h"
      
      Uart Serial3( &sercom0, PIN_SERIAL3_RX, PIN_SERIAL3_TX, PAD_SERIAL3_RX, PAD_SERIAL3_TX ) ;
      
      void SERCOM0_Handler()
      {
        Serial3.IrqHandler();
      }


      以上の変更で、XIAOで Serial2 と Serial3 が使えるようになります。Wireも使用できます。

      Serial2 TX4 pin
      Serial2 RX5 pin
      Serial3 TX10 pin
      Serial3 RX9 pin

 
Edit  

使用方法

  • Serial2, Serial3 の使い方は Serial1 と同じですが、Serial2 を使用する場合はスケッチファイルの先頭に下記の1行を追加します。
    #include "Serial2.h"
    また、Serial3 を使用する場合は、下記1行を追加します。
    #include "Serial3.h"
    Wireを使用する場合はピンが競合してSerial2は使用できないため、Serial2.hのインクルードは行わないでください。同様に、SPIを使用する場合は Serial3.h のインクルードは行わないでください。(SPIの場合はインクルードするだけならエラーは起こりませんが、Serial2に合わせた形に変更してあります)

 
Edit  

動作確認

  • 下記の配線でSerial1~Serial3のすべてのTX/RX端子の動作確認を行いました。
XIAO_Serial23.PNG
  • サンプルコードは以下のとおりです。外部配線は上の図の通りとします。
    //
    // Serial2, Serial3 機能追加 動作確認
    //
    // 接続 および USBシリアルへの表示(1秒毎)
    // 開始表示                          "Start"
    // Serial1-Tx (6) - Serial2-Rx (5)  "Send 1->"
    // Serial2-Tx (4) - Serial3-Rx (9)  "Send 1->2->"
    // Serial3-Rx (10)- Serial1-Rx (7)  "Send 1->2->3->"
    // -> Serial0-Tx 結果表示            "send 1->2->3->1->0"
    
    #include "Serial2.h"
    #include "Serial3.h"
    #include <TimerTC3.h>
    int sendflag = 0;
    
    void sendmsg(void){
      sendflag = 1;
    }
    
    void setup() {
        Serial.begin(115200);
        Serial1.begin(115200);
        Serial2.begin(115200);
        Serial3.begin(115200);
        delay(3000);
        while (!Serial);
        Serial.println("Serial ready.");
        while (!Serial1);
        Serial.println("Serial1 ready");
        //Serial1.println("Serial1 ready");
        while (!Serial2);
        Serial.println("Serial2 ready");
        //Serial2.println("Serial2 ready");
        while (!Serial3);
        Serial.println("Serial3 ready");
        //Serial3.println("Serial3 ready");
    
        TimerTc3.initialize(1000000);  // 1000,000us = 1s
        TimerTc3.attachInterrupt(sendmsg);
        TimerTc3.start();
    }
    
    void loop() {
      char rxchr;
      static char buff1[256];
      static char buff2[256];
      static char buff3[256];
      static int i1=0;
      static int i2=0;
      static int i3=0;
    
      if (sendflag==1){
        sendflag=0;
        Serial.println("Start");
        Serial1.println("send 1->"); // 1->2
      }
      if (Serial2.available() > 0) {
        // データが受信されたら1バイト読み込む
        while( -1 == (rxchr = Serial2.read()) );
          buff2[i2++] = rxchr;
          if(rxchr == '\n'){
          buff2[i2-2]=0x00; //delete \r\n
          strcat(buff2,"2->\r\n");
          Serial2.print(buff2); // 2->3
          i2=0;
        }
      }
      delay(1);
      if (Serial3.available() > 0) {
        // データが受信されたら1バイト読み込む
        while( -1 == (rxchr = Serial3.read()) );
          buff3[i3++] = rxchr;
          if(rxchr == '\n'){
          buff3[i3-2]=0x00; // delete \r\n
          strcat(buff3,"3->\r\n");
          Serial3.print(buff3); // 3->1
          i3=0;
        }
      }
      delay(1);
      if (Serial1.available() > 0) {
        // データが受信されたら1バイト読み込む
        while( -1 == (rxchr = Serial1.read()) );
          buff1[i1++] = rxchr;
          if(rxchr == '\n'){
          buff1[i1-2]=0x00; // delete \r\n
          strcat(buff1,"1->0\r\n");
          Serial.print(buff1); // 1->0(usb)
          i1=0;
        }
      }
      delay(1);
    }
 
Edit  

実行結果

  • 約1秒ごとに「send 1->2->3->1->0」がシリアルコンソールに表示されます。

    P1080936.JPG

    WSB000561.PNG


*1 1.7.8の部分はボード情報追加時のバージョンで、タイミングによっては変更される場合があります。また、WindowsでOneDriveを使っている方は \AppData\Local\Arduino15\ の部分が \OneDrive\ドキュメント\ArduinoData\ 等になる場合がありますので、適宜変更してください。

トップ   リロード   一覧 単語検索