シリアル通信は、以下の手順で動作する。
(1) UDRレジスタにデータを書き込む。(UDRにデータを書き込む際は、TXC1ビットを確認してから行うこと)
(2) 書き込まれたデータ(8bit幅)は、シフトレジスタにコピーされる。この時、スタートビットとストップビットが前後に付加される。
(3) 通信速度(ボーレート ~ bit/sec)に従って、シフトレジスタの値が、1ビットずつ、信号線に押し出される。
(4) 受信側では、信号線を通じて受け取ったデータを、順番にシフトレジスタに挿入する。
(5) ストップビットまでデータを受け取ると、スタートビット・ストップビットを取り払ったデータをUDRにコピーする。
(6) UDRレジスタの値を読み取る。(RXC1ビットを確認してから読み取ること)
※1 ストップビットのビット長は、1 or 2 ビット。スタートビットのビット長は1ビット。
※2 ストップビットの直前に、パリティビットが付加される場合もある。パリティビットについては、後述。
UDRレジスタにデータを書き込む場合は、UCSR1AレジスタのRXC1ビットとTXC1ビットに注意すること。
送信が完了していない状態でUDRにデータを書き込むと、データが上書きされてしまう。
例えば、以下のように、0b10110001 → 0b11111101 → 0b00011101の順で連続してデータを送信する場合を考えてみると、
となり、問題が起こる。このような事態を避けるため、UCSR1Aレジスタのビットをチェックすることが重要となる。
シリアル通信に関連するレジスタ
1.通信速度の設定(UBRR1)
○非同期ノーマルモード(通常の通信)では、以下の計算式で求めた値をUBRR1レジスタに設定する。(UCSR1A:U2X1=0)
BAUD:通信速度(300、1200、2400、4800、9600、19200、38400、57600 ....)
○非同期倍速モードでは、以下の計算式で求めた値をUBRR1レジスタに設定する。(UCSR1A:U2X1=1)
BAUD:通信速度(300、1200、2400、4800、9600、19200、38400、57600 ....)
※foscはマイコンのクロック周波数。 ”CLKPR = 0x80; CLKPR = 0;
”の設定をしているなら、16MHzなので、16000000になる。
※UBRRnのnは、1に読み替える。
2.設定レジスタ
シリアル通信に係るレジスタは、UBRR1以外に、以下の3つがある。
(1) UCSR1A
bit7 | bit6 | bit5 | bit4 | but3 | bit2 | bit1 | bit0 | |
ビットの名前 | RXC1 | TXC1 | UDRE1 | FE1 | DOR1 | UPE1 | U2X1 | MPCM1 |
初期値 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
○RXC1:受信完了 ~ このビットが1になった時に、受信データがUDRレジスタにセットされる。
○TXC1:送信完了 ~ 送信側のシフトレジスタのデータについて送信が完了。
○UDRE1:送信バッファが空 ~ UDR1レジスタに送信データを書き込み可能。
○FE1:フレーミングエラー ~ 受信したデータにフレーミングエラー(壊れたデータを受け取った)場合に、ビットが1になる。
○DOR1:データオーバラン ~ 受信したデータを処理する前に、次のデータを受け取ってしまった場合に発生。ビットが1。
○UPE:パリティエラー ~ 受信データとパリティが不一致の場合に発生。ビットが1。
○U2X1:非同期ノーマルモード(= 0)、非同期倍速モード(= 1)の切り替え。通常はノーマルモード。
○MPCM1:マルチプロセッサ通信モード。(とりあえず、使わないかな)
(2) UCSR1B
bit7 | bit6 | bit5 | bit4 | but3 | bit2 | bit1 | bit0 | |
ビットの名前 | RXCIE1 | TXCIE1 | UDRIE1 | RXEN1 | TXEN1 | UCSZ12 | RXB81 | TXB81 |
初期値 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
○RXCIE1:このビットを1に設定すると、データ受信時に割り込みが発生。
○TXCIE1:このビットを1に設定すると、データ送信完了時に割り込みが発生。
○UDRIE1:このビットを1に設定すると、UDR1レジスタが空になった時に割り込みが発生。
○RXEN1:受信モジュールを開始
○TXEN1:送信モジュールを開始
○UCSZ12:UCSR1C:UCSZ11、UCSR1C:UCSZ10の3つのビットを使ってデータ長を設定する。
UCSR1B:UCSZ12 | UCSR1C:UCSZ11 | UCSR1C:UCSZ10 | データ長 |
0 | 0 | 0 | 5ビット |
0 | 0 | 1 | 6ビット |
0 | 1 | 0 | 7ビット |
0 | 1 | 1 | 8ビット |
1 | 0 | 0 | 予約 |
1 | 0 | 1 | 予約 |
○RXB81:9番目のビット(受信データの)を受け取る場合に1
○TXB81:9番目のビット(送信データの)を送信する場合に1
(3) UCSR1C:UCSZ11
bit7 | bit6 | bit5 | bit4 | but3 | bit2 | bit1 | bit0 | |
ビットの名前 | UMSEL11 | UMSEL10 | UPM11 | UPM10 | USBS1 | UCSZ11 | UCSZ00 | UCPOL1 |
初期値 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
○UMSEL1とUMSEL0の設定で、シリアル通信のモードを設定する。
UMSEL11 | UMSEL10 | モード |
0 | 0 | 非同期モード |
0 | 1 | 同期モード |
1 | 0 | 予約 |
1 | 1 | マスタSPIモード |
○UPM11とUPM10の設定で、パリティモードを設定する。
UPM11 | UPM10 | パリティモード |
0 | 0 | 無効 |
0 | 1 | 予約 |
1 | 0 | 偶数パリティ |
1 | 1 | 奇数パリティ |
○USBS1でストップビット長を設定する。 0でストップビット長が1ビット、1で2ビットになる。
○UCSZ11、UCSZ10: 前述
○UCPOL1:クロックの極性(同期モードでのみ有効) クロックの立ち上がり、立下りエッジのいずれかを選択する。
プログラミングの実際
プログラムの概略をフローチャートで書くと、以下の様になる。
受信側のフロー 送信側のフロー
※このフローチャートでは、それぞれに初期化処理があるが、送受信機能を1つのプログラムに実装するなら、どちらかは
省略できる。(逆に言うと、送信のデータ長を8bitで、受信のそれを7bitなんて設定は出来ないということ)
○実装例
/* #include < avr/io.h > // 一文字受信(PC → AVR) // 一文字送信(AVR → PC) // シリアル通信ユニット(USART)の初期化 // 送信ユニット、受信ユニットを有効にする // 通信モードの設定 int main() while(1) { |
※ _BV()とは、ビット演算を簡単にするための補助的関数で、引数の値で示されるビットを1にして返す関数。
char bit; |
PCとの接続
PCとの接続は、USB・シリアル変換ケーブルを用いて行う。ケーブルのUSBコネクタをPC前面のUSB端子に挿入する。また、反対側のプラスチックのモールド端子(下図参照)を、AVRマイコンの各ピンに接続する。
図 AVRマイコンのピン配置 図 ケーブルのピン配置
実際の接続は、以下の様に行う。
PCとの通信
WindowsメニューからTERA TERMを立ち上げ、「ファイル」→「新しい接続」を選択。以下のメニューが表示される。
「シリアル」 → 「COM?」: USB Serial Port(COM?)を選択する。
また、上図の様に「設定」→「シリアルポート」→「ボーレート」の順でメニューを選択し、通信速度を38400bpsに設定する。
これで、AVRマイコンと通信できる。