「ATmega328でUART通信」の版間の差分
編集の要約なし |
細 (文字列「</source>」を「</syntaxhighlight>」に置換) |
||
21行目: | 21行目: | ||
// 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); | ||
</ | </syntaxhighlight> | ||
<br> | <br> | ||
表と式が異なるが、そのまま計算すると整数切り捨てのための誤差が大きくなるため、四捨五入で誤差を小さくしている。<br> | 表と式が異なるが、そのまま計算すると整数切り捨てのための誤差が大きくなるため、四捨五入で誤差を小さくしている。<br> | ||
36行目: | 36行目: | ||
// Enable receiver and transmitter | // Enable receiver and transmitter | ||
UCSR0B = (1 << RXEN0) | (1 << TXEN0); | UCSR0B = (1 << RXEN0) | (1 << TXEN0); | ||
</ | </syntaxhighlight> | ||
<br><br> | <br><br> | ||
63行目: | 63行目: | ||
// Set frame format: 8data, 1stop bit : 8N1 | // Set frame format: 8data, 1stop bit : 8N1 | ||
UCSR0C = (0 << USBS0) | (3 << UCSZ00); | UCSR0C = (0 << USBS0) | (3 << UCSZ00); | ||
</ | </syntaxhighlight> | ||
一般的には、データビット8[bit]、パリティビット無し、ストップビット1[bit]の通称8N1という形式が多い。<br> | 一般的には、データビット8[bit]、パリティビット無し、ストップビット1[bit]の通称8N1という形式が多い。<br> | ||
ここでも、8N1形式で送受信を行う。<br> | ここでも、8N1形式で送受信を行う。<br> | ||
84行目: | 84行目: | ||
UDR0 = data; | UDR0 = data; | ||
} | } | ||
</ | </syntaxhighlight> | ||
<br> | <br> | ||
98行目: | 98行目: | ||
return UDR0; | return UDR0; | ||
} | } | ||
</ | </syntaxhighlight> | ||
<br><br> | <br><br> | ||
__FORCETOC__ | __FORCETOC__ | ||
[[カテゴリ:AVR]] | [[カテゴリ:AVR]] |
2021年11月15日 (月) 01:08時点における版
概要
ATmega328に用意されているUSART機能を使用してシリアル通信を行う。
USARTはUniversal Synchronous Asynchronous Receiver Transmitterの略で、
非同期通信のUARTだけでなく、同期通信も可能とした機能のことである。
今回は、非同期通信のUARTについてのみ記述する。
AVRのマイコンでUARTを使うには、以下の3つの設定を行う必要がある。
- ボーレートの設定
- レシーバとトランスミッタの有効化
- フレームフォーマットの設定
ボーレートの設定
設定したいボーレート(通信速度)に合わせて通信用の内部クロックを生成するため、下表の式を元にUBRRレジスタの値を算出する。
BAUD : ボーレート
Fosc : ATmega328のクロック周波数
<source lang="c++"> // Set baudrate parameter // RoundOff UBRR0 = (U16)(((F32)F_CPU / (F32)BAUDRATE / 16.0) - 1.0 + 0.5); </syntaxhighlight>
表と式が異なるが、そのまま計算すると整数切り捨てのための誤差が大きくなるため、四捨五入で誤差を小さくしている。
誤差が大きくなると文字化けするので、適宜試しながら正しく通信できる速度を探らなければならない。
UBRRレジスタのサンプル値もデータシートに記載されているので、そちらを参照して定数で指定してもよい。
例えば、ATmega328のクロック周波数が8[MHz]のとき、ボーレート19.2[kbps]に設定したければUBRRレジスタの値は25になる。
レシーバとトランスミッタの有効化
レシーバとトランスミッタの有効化は、USARTのコントロールレジスタを設定する。
<source lang="c++"> // Enable receiver and transmitter UCSR0B = (1 << RXEN0) | (1 << TXEN0); </syntaxhighlight>
フレームフォーマットの設定
シリアル通信では1本の信号線で時系列に0または1を送信することで通信を行う。
そのため、予めどのようなフォーマットでデータを送信するかを定義する必要がある。
シリアル通信のフレームフォーマットは以下の要素で構成されます。
名称 | ビット数 | 説明 |
---|---|---|
スタートビット | 1 | フレームの先頭であることを示すビット |
データビット | 5 - 9 | 送信するデータ 5 - 9[bit]の範囲で自由に設定できる |
パリティビット | 0 or 1 | ビットの誤りをチェックするビット 設定しなくともよい |
ストップビット | 1 or 2 | フレームの終わりであることを示すビット |
上表において、スタートビットは常に1[bit]なので、残りの3項目のビット数を設定する。
<source lang="c++"> // Set frame format: 8data, 1stop bit : 8N1 UCSR0C = (0 << USBS0) | (3 << UCSZ00); </syntaxhighlight>
一般的には、データビット8[bit]、パリティビット無し、ストップビット1[bit]の通称8N1という形式が多い。
ここでも、8N1形式で送受信を行う。
サンプルコード
送信と受信ともにUDR0レジスタを用いて1[byte]データを操作する。
1度の操作で1[byte]しか扱えないため、数byteを送受信するときは単純に同じ操作を繰り返す。
送信方法
送信バッファが空になるまで待機し、UDR0レジスタに1[Byte]分のデータを書き込む。
<source lang="c++"> void Transmit1Byte(char data) { // Wait for empty transmit buffer while(!(UCSR0A & (1 << UDRE0)));
// Put data into buffer, sends the data UDR0 = data; } </syntaxhighlight>
受信方法
1[Byte]分のデータを受信するまで待機(ポーリング)し、UDR0レジスタを読み取る。
<source lang="c++"> char Receive1Byte(void) { // Wait for data to be received while(!(UCSR0A & (1 << RXC0)));
// Get and return received data from buffer return UDR0; } </syntaxhighlight>