「ATmega328でUART通信」の版間の差分

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動
編集の要約なし
(文字列「source lang」を「syntaxhighlight lang」に置換)
 
(同じ利用者による、間の1版が非表示)
17行目: 17行目:
BAUD : ボーレート<br>
BAUD : ボーレート<br>
Fosc : ATmega328のクロック周波数<br>
Fosc : ATmega328のクロック周波数<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  // Set baudrate parameter
  // Set baudrate parameter
  // RoundOff
  // RoundOff
  UBRR0 =  (U16)(((F32)F_CPU / (F32)BAUDRATE / 16.0) - 1.0 + 0.5);
  UBRR0 =  (U16)(((F32)F_CPU / (F32)BAUDRATE / 16.0) - 1.0 + 0.5);
  </source>
  </syntaxhighlight>
<br>
<br>
表と式が異なるが、そのまま計算すると整数切り捨てのための誤差が大きくなるため、四捨五入で誤差を小さくしている。<br>
表と式が異なるが、そのまま計算すると整数切り捨てのための誤差が大きくなるため、四捨五入で誤差を小さくしている。<br>
33行目: 33行目:
== レシーバとトランスミッタの有効化 ==
== レシーバとトランスミッタの有効化 ==
レシーバとトランスミッタの有効化は、USARTのコントロールレジスタを設定する。<br>
レシーバとトランスミッタの有効化は、USARTのコントロールレジスタを設定する。<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  // Enable receiver and transmitter
  // Enable receiver and transmitter
  UCSR0B = (1 << RXEN0) | (1 << TXEN0);
  UCSR0B = (1 << RXEN0) | (1 << TXEN0);
  </source>
  </syntaxhighlight>
<br><br>
<br><br>


60行目: 60行目:
<br>
<br>
上表において、スタートビットは常に1[bit]なので、残りの3項目のビット数を設定する。<br>
上表において、スタートビットは常に1[bit]なので、残りの3項目のビット数を設定する。<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  // Set frame format: 8data, 1stop bit : 8N1
  // Set frame format: 8data, 1stop bit : 8N1
  UCSR0C = (0 << USBS0) | (3 << UCSZ00);
  UCSR0C = (0 << USBS0) | (3 << UCSZ00);
  </source>
  </syntaxhighlight>
一般的には、データビット8[bit]、パリティビット無し、ストップビット1[bit]の通称8N1という形式が多い。<br>
一般的には、データビット8[bit]、パリティビット無し、ストップビット1[bit]の通称8N1という形式が多い。<br>
ここでも、8N1形式で送受信を行う。<br>
ここでも、8N1形式で送受信を行う。<br>
75行目: 75行目:
===== 送信方法 =====
===== 送信方法 =====
送信バッファが空になるまで待機し、UDR0レジスタに1[Byte]分のデータを書き込む。<br>
送信バッファが空になるまで待機し、UDR0レジスタに1[Byte]分のデータを書き込む。<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  void Transmit1Byte(char data)
  void Transmit1Byte(char data)
  {
  {
84行目: 84行目:
     UDR0 = data;
     UDR0 = data;
  }
  }
  </source>
  </syntaxhighlight>
<br>
<br>


===== 受信方法 =====
===== 受信方法 =====
1[Byte]分のデータを受信するまで待機(ポーリング)し、UDR0レジスタを読み取る。<br>
1[Byte]分のデータを受信するまで待機(ポーリング)し、UDR0レジスタを読み取る。<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  char Receive1Byte(void)
  char Receive1Byte(void)
  {
  {
98行目: 98行目:
     return UDR0;
     return UDR0;
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
<br><br>


__FORCETOC__
__FORCETOC__
[[カテゴリ:AVR]]
[[カテゴリ:AVR]]

2021年11月18日 (木) 10:25時点における最新版

概要

ATmega328に用意されているUSART機能を使用してシリアル通信を行う。
USARTはUniversal Synchronous Asynchronous Receiver Transmitterの略で、
非同期通信のUARTだけでなく、同期通信も可能とした機能のことである。

今回は、非同期通信のUARTについてのみ記述する。

AVRのマイコンでUARTを使うには、以下の3つの設定を行う必要がある。

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



ボーレートの設定

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

ATmega328 UART 1.jpg

BAUD : ボーレート
Fosc : ATmega328のクロック周波数

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


表と式が異なるが、そのまま計算すると整数切り捨てのための誤差が大きくなるため、四捨五入で誤差を小さくしている。
誤差が大きくなると文字化けするので、適宜試しながら正しく通信できる速度を探らなければならない。

UBRRレジスタのサンプル値もデータシートに記載されているので、そちらを参照して定数で指定してもよい。
例えば、ATmega328のクロック周波数が8[MHz]のとき、ボーレート19.2[kbps]に設定したければUBRRレジスタの値は25になる。

ATmega328 UART 2.jpg



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

レシーバとトランスミッタの有効化は、USARTのコントロールレジスタを設定する。

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



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

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

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

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


上表において、スタートビットは常に1[bit]なので、残りの3項目のビット数を設定する。

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

一般的には、データビット8[bit]、パリティビット無し、ストップビット1[bit]の通称8N1という形式が多い。
ここでも、8N1形式で送受信を行う。


サンプルコード

送信と受信ともにUDR0レジスタを用いて1[byte]データを操作する。
1度の操作で1[byte]しか扱えないため、数byteを送受信するときは単純に同じ操作を繰り返す。

送信方法

送信バッファが空になるまで待機し、UDR0レジスタに1[Byte]分のデータを書き込む。

 void Transmit1Byte(char data)
 {
    // Wait for empty transmit buffer
    while(!(UCSR0A & (1 << UDRE0)));

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


受信方法

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

 char Receive1Byte(void)
 {
    // Wait for data to be received
    while(!(UCSR0A & (1 << RXC0)));

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