AVR
uart
USART
シリアル通信
ATmega328P

AVRマイコンでUART(シリアル)通信

はじめに

AVRマイコンに用意されているUSARTを使ってUARTシリアル通信をしてみます。

USARTはUniversal Synchronous Asynchronous Receiver Transmitterの略で、
非同期通信のUARTだけでなく、同期通信も可能とした機能のことです。

今回は非同期通信のUARTについてのみ記述します。
基本的にはデータシートに記載されていることを簡潔に述べるようにします。

※サンプルコードの表記について
U16やF32はそれぞれunsigned short(16bit), float(32bit)を表しています。

準備

AVRマイコンでUARTを使うには

  1. ボーレートの設定
  2. レシーバーとトランスミッターの有効化
  3. フレームフォーマットの設定

を行う必要があります。

1. ボーレートの設定

設定したいボーレート(通信速度)に合わせて通信用の内部クロックを生成するため、
下表の式に従ってレジスタUBRRの値を算出します。
BAUD:ボーレート
Fosc:マイコンのクロック

baudrate.png

/* Set baudrate parameter */
UBRR0 =  (U16)(((F32)F_CPU / (F32)BAUDRATE / 16.0) - 1.0 + 0.5);    //RoundOff

表と式が異なりますが、
そのまま計算すると整数切り捨てのため誤差が大きくなるため、四捨五入で誤差を小さくしています。

UBRRのサンプル値もデータシートに記載されているので、そちらを参照して定数で指定してもいいと思います。
例えば、マイコンのクロック8MHzにおいて、ボーレート19.2kbpsに設定したければUBRRは25になります。

example_baudrate.png

誤差が大きくなると文字化けするので、適宜試しながら正しく通信できる速度を探ってください。

2. レシーバーとトランスミッターの有効化

レシーバーとトランスミッターの有効化はUSARTのコントロールレジスタを叩いてあげます。

/* Enable receiver and transmitter */
UCSR0B = (1 << RXEN0) | (1 << TXEN0);

3. フレームフォーマットの設定

シリアル通信では1本の信号線で時系列に0か1を送ることで通信を行います。
そのため、あらかじめどのようなフォーマットでデータを送るかを定義する必要があります。

シリアル通信のフレームフォーマットは以下の要素で構成されます。

名称 ビット数 意味
スタートビット 1 フレームの先頭であることを示すビット
データビット 5 ~ 9 送るデータ。5~9bitの範囲で自由に設定できる。
パリティビット 0 or 1 ビット誤りしていないかをチェックするビット。無くてもよい。
ストップビット 1 or 2 フレームの終わりであることを示すビット

スタートビットは常に1bitなので、残りの3項目のビット数を設定します。

/* Set frame format: 8data, 1stop bit : 8N1 */
UCSR0C = (0 << USBS0) | (3 << UCSZ00);

一般的には
データビット8bit、パリティビット無し、ストップビット1bit、の通称8N1という形式が多いです。

使い方

送信・受信ともにUDR0というレジスタを用いて1byteデータを操作します。
1度の操作で1byteしか扱えないため、
複数byte扱いたい場合は単純にその分同じ操作を繰り替えすことになります。

送信方法

送信バッファが空くまで待機し、UDR0レジスタに1byteデータを書き込みます。

void Uart::Transmit1Byte(char data)
{
    /* Wait for empty transmit buffer */
    while ( !(UCSR0A & (1 << UDRE0)))
    {
        /* Do Nothing */
    }

    /* Put data into buffer, sends the data */
    UDR0 = data;
}

受信方法

データを受信するまで待機(ポーリング)し、UDR0レジスタを読み取ります。

char Uart::Receive(void)
{
    /* Wait for data to be received */
    while ( !(UCSR0A & (1 << RXC0)) )
    {
        /* Do Nothing */
    }

    /* Get and return received data from buffer */
    return UDR0;
}

最後に

簡単ではありますが、AVRマイコンでUART通信をするための設定方法と使い方を記述しました。

今回は割り込みを使った記述をしていませんが、受信割り込みを使うこともできるので
受信するまでは他の処理をしておき、受信したらデータを読み取るといったプログラムも作れます。

基本的にはデータシートに使い方は全て記載されているので、興味あれば是非試してください。

リファレンス

ATmega328p Datasheet
http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf