ArduinoにUARTのPINを追加する

 ArduinoのSERCOMについて調べたところ、日本語の情報がほとんどなかったので、調べたことを備忘録として書き留めておきます。
※ 簡単に調べただけなので、内容に誤りがある可能性があります

SERCOMとは何か

Serial communication moduleの略であり、MCUが用意しているシリアル通信モジュールのことである。
MCUのPinをどのシリアル通信(I2C、UART、SPI)で使用するのかを定義している。
以下はArduino MKR WAN 1310のMCUであるATSAMD21のデータシートを抜粋した画像です。
このMCUには6つのSERCOMが用意されていると書いてあります。

ArduinoのPinに紐づけられているSERCOMを確認する

ArduinoのPinとSERCOMが紐づけられているので、シリアル通信を使うことができます。
以下はArduino MKR WAN 1310のPin配列図ですが、どこにもSERCOMの記述はありません。

より詳細なPin配列を「Download the full pinout diagram as PDF here.」から確認できます。

先ほどは無かった「Sercom」が表示されています。
例えば、UARTで使用するD13とD14には「SC5」と書いてあるので、SERCOMの5番と紐づいていることが分かります。

SERCOMでシリアル通信用のPinを増やせる

ArduinoはMCUのSERCOMを全て利用しているとは限らないため、未使用のSERCOMがあります。
そのため、シリアル通信以外に割り振られているArduinoのPinと未使用のSERCOMを紐づけることで、シリアル通信用のPinを増やすことができます。
例えば、Arduino MKR WAN 1310のUARTは1つ(D13とD14)しか存在しませんが、他のPinを使ってUART用のPinを増やすことができます。

しかし、実際にSERCOMを使ってシリアル通信用のPinを増やすことはありません。
なぜなら、SoftwareSerialを使えば同様のことが実現可能だし、I2Cは数珠つなぎで最大16個のデバイスを接続できるからです。

なぜ、シリアル通信用のPinを増やそうとしたのか

Arduino MKR WAN 1310にUARTでセンサーを繋ごうとして、インターネットでいろいろ調べているうちに、なぜか以下の勘違いをしてしまいました。

「UART用にD13とD14のPinが用意されているが、USB接続で使用するためPCに接続しているときは使用できない」

実際にはPCと接続していてもD13とD14はUARTとして使用できます。
今となってはなぜこんな勘違いをしたのか分かりませんが、これを解決するためにSoftwareSerialを使おうとしました。
しかし、MKR系のArduinoではSoftwareSerialを使えないのです!!
そのため、SERCOMを使ってUART用のPinを増やそうとしたのです。

MCUのSERCOMを確認する

まずはMCUのデータシートでPinを確認し、シリアル通信に割り当てれそうなPinを探します。
ATSAMD21のデータシートから「7. I/O Multiplexing and Considerations」を参照します。
長い表なので、1ページ目のみ載せます。
Arduino MKR WAN 1310のMCUはATSAMD21Gだと思われるので、Pin列はATSAMD21Gとなります。
A列~H列は機能別に割り当てられており、C列とD列がSERCOMとなります。
※ SERCOM#/PAD[x] の#はSERCOMの番号、PADのXはPADの番号を表す
※ PADはPinの多重化のようなもの??
この表から、1番~5番までのSERCOMがあり、各SERCOMには4つのPADがあることが分かります。

ArduinoとSERCOMの紐づけを確認する

次はArduinoのPinとSERCOMの紐づけを確認します。
variant.cppの変数「g_APinDescription」で定義されており、表がコメントに記載されています。
C:\Users\USER_NAME\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\variants\DEVICE\variant.cpp

以下はシリアル通信を定義している箇所になります。

UARTであるSerial1は13ピンをSERCOM5/PAD[3]に、14ピンをSERCOM5/PAD[2]に紐づけていることが分かります。

variant.cppのシリアル通信の定義から、未使用のSERCOMが分かりました。
今回はお試しとして、SERCOM1が未使用と仮定して話を進めます。

新しくUARTを作成する

スケッチに以下の処理を追加することで、新しくUARTを追加できます。
Uart SERIAL_NAME(&sercom1, PIN_RX, PIN_TX, PAD_RX, PAD_TX );

void SERCOM1_Handler()
{
    SERIAL_NAME.IrqHandler();
}
SERIAL_NAMEは任意の名前です。
Uartの引数は以下となります。
第一引数:使用するSERCOMを指定する。今回は1番を使用するの「&sercom1」を渡す
第二引数:UartのRXとして使用するPinを指定する
第三引数:UartのTXとして使用するPinを指定する
第四引数:第一引数で渡したSERCOMのPAD0~4のうち、どれをRXとして使用するか指定する
第五引数:第一引数で渡したSERCOMのPAD0~4のうち、どれをTXとして使用するか指定する

第二引数と第三引数に指定できるPinはSERCOMで決まるため、再びデータシートの表を確認する。

C列とD列に「SERCOM1」の記載があるのは以下のPinとなる。




MCUとしてはPA01、PA16、PA18、PA19、PA30、PA31のPINをSERCOM1として利用できることが分かりました。
しかし、Arduino MKR WAN 1310にはPA01、PA18、PA30、PA31のPinは無いため、実際に利用できるPinはPA16(D8)、PA19(D10)のみとなります。

第四引数と第五引数のPADですが、どのPADでもUARTのRXとTXに使えるわけではないです。
RXとTXに使用できるPADは「SERCOM.h」に定義されています。

RXは0~3まで定義されているので、結果的にはどのPADでも使用できます。
しかし、TXは0と2しか定義されていません。
ここでMCUの表を再度確認します。
PA16のSERCOM1のPADは0、PA19のSERCOM1のPADは3なので、PA16はRXとTXの両方で使用できますが、PA19はRXにしか使用できません。

そのため、SERCOM1を使用してUartを追加するコードは以下となります。
Uart SERIAL_NAME(&sercom1, 10, 8, SERCOM_RX_PAD_3 , UART_TX_PAD_0);
※ MCUのPA16はArduinoではD8なので、PIN番号は8となる
※ MCUのPA19はArduinoではD10なので、PIN番号は10となる

以下のサイトが良い参考になりました。
https://learn.adafruit.com/using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports/overview

コメント

このブログの人気の投稿

Visual StudioでAngularの開発をする

Arduinoが技適を取得した!?