マイコン・メモ
USARTインタフェースの使い方
ホームページに戻るトップページに戻る前ページに戻る次のページ最後のページ
AVRマイコン ATmega328P のUSARTインタフェースの基本的な使い方を、これまで製作で使用したものを基に紹介します。
USARTインタフェースを持っている機種であれば、若干の修正で他のAVRマイコンでも使えるハズです。ただし未確認。
1.USARTによる通信とは

USART(Universal Synchronous and Asynchronous Receiver and Transmitter)は、同期および非同期で使用できるシリアル通信インタフェースです。SPI通信も行うことができますが、ここでは触れません。
同期通信には次のようなものがありますが、このUSARTで使えるのは bのクロック同期方式です。
下図に、クロック同期通信の1キャラクタ分のフォーマットを示します。ただし、同期クロックXCKの立ち上がりでデータが切り換わる設定とした場合です。AVRマイコンでは、レジスタUCSRnCでUCPOLn=0とした場合です。
同期通信は、非同期通信に比べ高速な通信が可能です。
クロック同期のフォーマット
一方、非同期通信の1キャラクタ分のフォーマットは下図のようになります。このように、同期クロックではなく、1キャラクタごとにスタートビットとストップビットで同期をとって通信する方法です。
パリティビットとは、通信エラーを検知する手段の一つです。あらかじめ、データビット+パリティビットで'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インタフェース制御レジスタを下記に示します。
レジスタUDRn, UCSRnA
レジスタUCSRnB
レジスタUCSRnC, UBRRn
注意:
(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となります。
ちなみに、変調をかけないでデータをそのままの帯域(速度)で送る方式を「ベースバンド伝送」といいます。その場合は、ボーレート=ビットレートと言えます。

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"で宣言していますが、このプログラム例には含まれていません。

4.関数の説明

前記プログラム例のソースファイルにある関数について、使用方法を説明します。

(1)USARTインタフェースの初期化

    BOOL Init_USART(BYTE byMode, BYTE byRateNum)

USARTインタフェースの初期化を行います。
マイコンの起動後に、割り込みマスク状態で一度だけ呼ぶ必要があります。
割り込みマスクは、メインループに入るまでに解除してください。
引数の構成を下記に示します。
引数byMode, byRateNumの構成

(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は対応していません。

(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をリセットするよう、プログラムを修正してください。

ホームページに戻るトップページに戻る前ページに戻る次のページ最後のページ
■■■ 注 意 ■■■
1.ここに掲載された内容(写真,図,表などを含む)の、全てまたは一部を無断で使用しないでください。
2.ここで紹介した手法(構造や仕組み,回路,プログラムなどを含む)を使用したことにより、問題や不利益が発生したとしても一切関知しません。
3.ここで紹介したプログラム例は、正常なコンパイルおよび正常な動作を保証するものではありません。