Skip to content

SoftwareUART

朝日薫 edited this page Jan 1, 2023 · 6 revisions

SoftwareUART クラスリファレンス

最小フットプリントの、二線式半二重UART通信SoftwareUART_Class基本クラス。 Arduino互換APIの<SoftwareSerial.h>を代替するが上位互換ではない。 プロトコルは 8N1 専用。 割込も計時器周辺機能もFIFOバッファも使用しない。 従って全体割り込み禁止中でも、割込ハンドラの中からでも使用できる。 実装サイズは(print拡張を使わなければ)必要最小限しかない。

reduceAVR は未対応

用例

#include <variant.h> /* 外部端子定義取得 */
#include <SoftwareUART.h>
SoftwareUART_Class SoftSerial = {PIN_USART0_TXD, PIN_USART0_RXD};

void setup (void) {
  SoftSerial.begin(CONSOLE_BAUD);
}
void loop (void) {
  size_t length;
  char buff[INTERNAL_SRAM_SIZE / 4]; // 適当な大きさの1行ぶんのバッファメモリ
  length = SoftSerial.readBytes(&buff, sizeof(buff), '\n'); // `\n` 受信で方向切替
  if (length) SoftSerial.write(&buff, length);
}

このクラスは半二重通信専用なので、送信と受信は同時には行えない。 また受信に際してはreadBytesメソッドだけが実装されている。 このreadBytes実行中のみ外部端子を監視し、変化があれば受信キャラクタとして認識しようとする。

その性質から「固定長ヘッダ+可変長ペイロード」形式の受信用途には適していない。

制約

1. 計時基準は遅延ループで生成されるため、受信送信とも動作中は全体割込が禁止される。

ソフトウェア模倣動作なので対応可能なボーレートはF_CPUに強く依存する。 115200bps で送受信できるようにするには、少なくとも12000000L(12MHz)以上必要だろう。

2. 通常の UART通信クラスと異なり、以下はのメソッドは存在せず、使用できない。

  • read available availableForWrite peek

3. 以下のメソッドは存在するが、何もしない。

  • flush

<SoftwareUART.h>

依存性:<avr/io.h> <util/atomic.h> <api/delay_busywait.h> <api/Print.h>

クラスインスタンス

クラスインスタンスを作成するには、送信端子と受信端子を初期値として指定する。 指定できるのは<variant.h>で定義されているPIN_Pxnとその別名である。 送信専用あるいは受信専用とする場合は、使用しない方にNOT_A_PINを与える。

SoftwareUART_Class& begin (uint32_t baudrate)

UARTの使用を、任意のボーレート値で開始する。 自身のオブジェクトを返すので、メソッドチェーンを後続できる。 指定するボーレート値は変数ではなく、静定数であるべきだ。

SoftwareUART_Class SoftSerial = {PIN_PA2, PIN_PA3}; /* クラスインスタンス */
SoftSerial.begin(CONSOLE_BAUD);

SoftwareUART_Class& beginRxDriveOnly (uint32_t baudrate)

beginの別版。 受信専用UARTの使用を、任意のボーレート値で開始する。 自身のオブジェクトを返すので、メソッドチェーンを後続できる。 指定するボーレート値は変数ではなく、静定数であるべきだ。 受信専用であるからwrite print等の送信メソッドを使用してはならない。

SoftwareUART_Class SoftSerial = {NOT_A_PIN, PIN_PA3}; /* クラスインスタンス */
SoftSerial.beginRxDriveOnly(CONSOLE_BAUD);

SoftwareUART_Class& beginTxDriveOnly (uint32_t baudrate)

beginの別版。 送信専用UARTの使用を、任意のボーレート値で開始する。 自身のオブジェクトを返すので、メソッドチェーンを後続できる。 指定するボーレート値は変数ではなく、静定数であるべきだ。 送信専用であるからreadBytes受信メソッドを使用してはならない。

SoftwareUART_Class SoftSerial = {PIN_PA2, NOT_A_PIN}; /* クラスインスタンス */
SoftSerial.beginTxDriveOnly(CONSOLE_BAUD);

void end (void)

UART通信の使用を停止し、専有していた外部端子を未使用に戻す。 通信を再開するには先立って再びbeginを実行する。

  • 一般に、UART対向機器の電源が落ちている場合は TX線が Hi-Zか LOWになるだろう。 これを調べるには TX端子をデジタル入力許可に変えなければならない。 end後はそれが可能な状態になる。

size_t write (const uint8_t _c)

1キャラクタを出力する。 出力中は全体割込が禁止される。 常に1を返す。 全体割込が禁止されていても動作する。

size_t write (const uint8_t* _buffer, size_t _length)

指定のバッファから指定の量を書き出す。書けた量を返す。 全体割込が禁止されていても動作する。

size_t readBytes (void* _buffer, size_t _limit, char _terminate = 0, uint8_t _swevent = 0)

指定の_bufferに、最大_limit文字数、 あるいは_terminate指定キャラクタ出現までを取得する。取得されたキャラクタ数を返す。 _bufferの最後に\0は補完されないことに注意。

_terminate指定キャラクタは取得内容に含まれる。しかし\0は指定できない。 受信キャラクタが\0であればそれは含まれる。 そしてBREAK と見做して受信待機を打ち切るだろう。

このメソッドが呼ばれると、少なくとも 20bit時間のあいだ通信線を監視して IDLE 状態が続いたなら何も取得せずに終了し0を返す。 STOP ビット以外の受信中は全体割込が禁止される。

つまりNOBLOCK動作であるから、必要に応じて繰り返し呼び出さなければならない。

逆に_bufferに格納される最初の文字はその前に 約10bit長以上の IDLE 状態が検出されなければならない。

従って例えば シリアルGPSの NMEA出力は、概ね新たな行頭から採取されるだろう。

_swevent0以外であるなら、それは事象システム EVSYS ストローブ指令と解釈され、 最初の受信キャラクタ検出の瞬間に以下の IOレジスタへ代入し、 任意の事象イベントを発火することが出来る。

tinyAVR-0/1 megaAVR-0 その他のmodernAVR
EVSYS_ASYNCSTROBE EVSYS_STROBE EVSYS_SWEVENTA

各ビットがEVSYSチャネル番号[0-7]に対応。チャネル8番以上には対応していない。
発火イベントが割込を惹起する場合はそちらの実行が優先され、そして受信落ちを経験するだろう。 だが全体割込禁止中でもこのメソッドが機能することは留意されたい。
この機能は例えば 1PPS割込のない シリアルGPSで、秒タイミングを測るのに使える。

uint16_t is_baud (void)

現在の基準遅延ループ数を返す。デバッグ用途で通常の用途はない。

Print& print (...)

print文とその派生メソッドは<api/Print.h>を参照のこと。

....

この他の、特にタイムアウトを伴うストリーム読込系の機能は用意されていない。