USART(Universal Synchronous and Asynchronous Receiver and Transmitter)は、同期および非同期で使用できるシリアル通信インタフェースです。SPI通信も行うことができますが、ここでは触れません。
同期通信には次のようなものがありますが、このUSARTで使えるのは bのクロック同期方式です。
- 同期文字(SYNなど)を送り、続けてデータを送るキャラクタ同期方式。
- データと同時に同期クロックを出力するクロック同期方式。
同期通信は、非同期通信に比べ高速な通信が可能です。

パリティビットとは、通信エラーを検知する手段の一つです。あらかじめ、データビット+パリティビットで'1'のビットの数が偶数または奇数となるよう取り決めたパリティビットを付加して送信し、受信側でチェックして異常を検知します。'1'のビットの数を偶数とするものを「偶数パリティ」、奇数とするものを「奇数パリティ」といいます。
パリティビットの付加とチェックは、パリティビットを使うという設定をすれば、USARTインタフェースが自動的に行ってくれます。
非同期通信は、同期通信に比べ低速な通信になります。なお、非同期通信を調歩同期通信とも呼びます。

長い距離の通信を行うにはドライバICを介して通信を行います。例えば、RS-232,RS-422,RS-485などという通信規格は、昔からよく使われている規格で、ドライバICも容易に入手可能です。
「RS-232C」という名で知られるシリアル通信は、非同期通信を使用している場合が多いです。RS-232Cは機械的および電気的規格を規定した名称で、通信フォーマットや通信手順などを指すわけではありません。したがって、RS-232Cで同期通信も非同期通信も可能です。ただし、クロック端子がないのでクロック同期はできません。
ちなみに、RS-232Cの"C"は規格の改定記号で、近年では C→D→E→F と改定されているようです。
2.USARTインタフェース制御レジスタ
AVRマイコンのUSARTインタフェース制御レジスタを下記に示します。



注意:
(1)受信異常フラグ(パリティエラー、オーバーランエラー、フレーミングエラー)で割り込みを発生することはできません。
(2)受信異常フラグは、受信時にデータレジスタUDRnより先に読み込む必要があります。
(3)上図に示すレジスタ名の"n"は、ATmega328Pの場合"0"です。例えば、UCSRnA は UCSR0A となります。
(4)詳細はAVRマイコンのデータシートで確認してください。
(1)受信異常フラグ(パリティエラー、オーバーランエラー、フレーミングエラー)で割り込みを発生することはできません。
(2)受信異常フラグは、受信時にデータレジスタUDRnより先に読み込む必要があります。
(3)上図に示すレジスタ名の"n"は、ATmega328Pの場合"0"です。例えば、UCSRnA は UCSR0A となります。
(4)詳細はAVRマイコンのデータシートで確認してください。
参考:
"ボーレート"(baud rate)という言葉は通信速度、つまり1秒間に送れる情報量を指しますが、1秒間に何ビット送れるかという情報量(ビットレート=bps)とは若干異なります。
シリアル通信では、変調をかけて一度に何ビットかまとめて送ることもあります。その時の速度を「変調速度」または「ボーレート」と言います。したがって、必ずしもボーレート=ビットレートではありません。
簡単な例では、90度の位相変化でデータを表す「位相変調」があります。その変調は、変化なしの位相0度でバイナリデータ'00'を、90度変化で'01'を、180度変化で'10'、270度変化で'11'を表します。この位相変化が、1秒間に1000回であれば1000ボーです。データ自体は、1回の変調につき2ビット送ることになるので、2倍の2000bpsとなります。
ちなみに、変調をかけないでデータをそのままの帯域(速度)で送る方式を「ベースバンド伝送」といいます。その場合は、ボーレート=ビットレートと言えます。
"ボーレート"(baud rate)という言葉は通信速度、つまり1秒間に送れる情報量を指しますが、1秒間に何ビット送れるかという情報量(ビットレート=bps)とは若干異なります。
シリアル通信では、変調をかけて一度に何ビットかまとめて送ることもあります。その時の速度を「変調速度」または「ボーレート」と言います。したがって、必ずしもボーレート=ビットレートではありません。
簡単な例では、90度の位相変化でデータを表す「位相変調」があります。その変調は、変化なしの位相0度でバイナリデータ'00'を、90度変化で'01'を、180度変化で'10'、270度変化で'11'を表します。この位相変化が、1秒間に1000回であれば1000ボーです。データ自体は、1回の変調につき2ビット送ることになるので、2倍の2000bpsとなります。
ちなみに、変調をかけないでデータをそのままの帯域(速度)で送る方式を「ベースバンド伝送」といいます。その場合は、ボーレート=ビットレートと言えます。
3.制御プログラム例
以下に紹介するプログラム例は非同期通信で、下図のようなフォーマットに限定した文字列による通信例です。送信・受信ともに割り込みで動作するので、CPUの使用効率を上げることができます。
ヘッダコードおよび終端コードはヘッダファイル"USART.h"で定義していて、自由に変えることができます。ただし、ヘッダコードは記号文字、終端コードはコード0x20未満の制御コードで、共に1バイトです。
通信データ本体は0x20~0xFFのASCII文字コードで、0x20未満の制御コードを含めることはできません。データ文字数(=バイト数)は、送信/受信バッファのサイズー2バイト以内で任意です。このプログラム例では、送信バッファは64バイト、受信バッファは128バイトとしています。

・USARTインタフェースの制御フロー図(ATmega328_USART_ProgramFlow.pdf)
・USARTインタフェースの制御プログラムのソースファイル(USART.c)
・USARTインタフェースの制御プログラムのヘッダファイル(USART.h)
注意:必ずしも正常にコンパイルおよび正常に動作することを保証するものではありません。
■独自型宣言など
BYTE → unsigned char
WORD → unsigned short
BOOL → int
FALSE = 0
TRUE = 1
NULL = 0
これらは、ヘッダファイル"hdwareInfo.h"で宣言していますが、このプログラム例には含まれていません。
BYTE → unsigned char
WORD → unsigned short
BOOL → int
FALSE = 0
TRUE = 1
NULL = 0
これらは、ヘッダファイル"hdwareInfo.h"で宣言していますが、このプログラム例には含まれていません。
4.関数の説明
前記プログラム例のソースファイルにある関数について、使用方法を説明します。
(1)USARTインタフェースの初期化
BOOL Init_USART(BYTE byMode, BYTE byRateNum)
USARTインタフェースの初期化を行います。
マイコンの起動後に、割り込みマスク状態で一度だけ呼ぶ必要があります。
割り込みマスクは、メインループに入るまでに解除してください。
引数の構成を下記に示します。

(2)定周期割り込み処理
void Timer01mS_USART(void)
送信および受信関数で、タイムアウトを監視するための時間計測を行います。
1mS周期で定周期割り込み処理(割り込みマスク状態)から呼ぶ必要があります。
(3)受信データの破棄
void PurgeRxd_USART(void)
すでに受信バッファにある受信データをすべて破棄します。
(4)受信データの有無をチェック
BOOL CheckRcv_USART(void)
受信バッファに受信データがあるかどうか調べます。
ある場合はTRUEを、ない場合はFALSEを返します。
なお、この場合の「ある/ない」は、1バイト以上の受信データがあるかどうかで、終端コードまで受信した文字列があるかどうかではありません。
(5)ASCII文字列送信
BOOL TxString_USART(WORD wTimeOut, const char* strData)
末尾が終端コード(UART_TERM)になっている文字列を送信します。なお、先頭がヘッダコード(UART_HEADER)かどうかはチェックしていません。
以下に引数の意味を示します。
wTimeOut = タイムアウトとする時間(1~65535,1mS単位注1)
strData = 送信するASCII文字列の先頭アドレス(UART_TERMで終端.プログラムメモリのアドレスは不可注2)
正常に終了すればTRUEを、タイムアウトになればFALSEを返します。
タイムアウトは、wTimeOutで指定した時間待っても前回の送信が終了しないことにより発生します。この関数は送信終了を待たずに戻るので、今回の送信が完了しないことによるタイムアウトではありません。
注1:WDT(ウォッチドッグタイマ)を使用している場合、タイムアウト時間を長くすると作動してリセットしてしまいます。その場合は、この関数の待ちループ中にWDTをリセットするよう、プログラムを修正してください。
注2:AVRマイコンは、データがプログラムメモリ(フラッシュROM)中にある場合は、通常のデータのように読み出すことができません。読み出しには専用関数(マクロ)が必要ですが、この関数TxString_USARTは対応していません。
注2:AVRマイコンは、データがプログラムメモリ(フラッシュROM)中にある場合は、通常のデータのように読み出すことができません。読み出しには専用関数(マクロ)が必要ですが、この関数TxString_USARTは対応していません。
(6)ASCII文字列受信
int RxString_USART(WORD wTimeOut, WORD wBuffSz, char* pRcvBuff)
ヘッダコード(UART_HEADER)で始まり、終端コード(UART_TERM)で終わる文字列を受信し、指定の場所に格納します。
以下に引数の意味を示します。
wTimeOut = タイムアウトとする時間(1~65535,1mS単位注3)
wBuffSz = 受信データ格納場所のバイト数
pRcvBuff = 受信データ格納場所のアドレス
正常に終了すれば終端コードを除いた受信文字数を返し、タイムアウトになれば0を返します。
受信データ格納場所には、ヘッダコードも終端コードも格納されます。
この関数は、受信が完了するかタイムアウトが発生するまで戻ってきません。いつ受信があるかわからない、あるいは受信があるまで他の処理を行っていたい場合は、あらかじめ受信データがあることを関数CheckRcv_USARTで確認してから、この関数RxString_USARTを呼ぶことをお勧めします。
注3:WDT(ウォッチドッグタイマ)を使用している場合、タイムアウト時間を長くすると作動してリセットしてしまいます。その場合は、この関数の待ちループ中にWDTをリセットするよう、プログラムを修正してください。
