組み込み

シリアル通信の一種、UART、CSI(SPI)、I2Cとは?

シリアル通信でよく使用されるUART、CSI(SPI)、I2Cについて、概要を説明します。

今後、シリアル通信に関連した実装についてまとめていきたいと考えていますので、今回はまず前座としてどういうものかをまとめていきたいと思います。

シリアル通信とは?

シリアル通信とパラレル通信

まず最初に、シリアル通信とは何か、ということを確認しましょう。

シリアル通信とは、1本の通信線でデータを1bitずつ送る通信のことです。
シリアル通信の対称となるパラレル通信では、複数の通信線を使ってまとめて数bitのデータを送ることができます。

そう説明するとパラレル通信の方が優秀なもののように思いますが、組み込みの業界で一般的に普及しているのはシリアル通信の方です。

なぜシリアル通信の方が普及しているかというと、シリアル通信には以下のメリットがあるからです。

  • 配線の本数が少ないので低コスト
  • 配線の本数が少ないので、配線をするのが楽
  • 通信線が少ないので同期が楽 (パラレル通信では高速になればなるほど同期が難しくなる)

シリアル通信の方が全般的に低コストで実装がしやすいから使用されているということですね。

同期式と非同期式(調歩同期式)

シリアル通信では一定間隔でデータを1bitずつ送信していくのですが、送信側がいきなりデータを送り始めることになるので、データがどこからどこまでなのか、一定間隔とはどうやって決まるのか、というルールを決める必要があります。
このルールによってUARTやSPIなどの名称が決まることになるのですが、大きく分けると同期式と非同期式(調歩同期式)に分かれます。

同期式とは、データ線とは別に定周期信号であるクロックを送る線を用意し、データ線のデータをクロックに同期させて送る方式です。
受信側もクロック信号のタイミングで読み取るだけで済みます。
データとクロック信号が同期しているので、同期式と呼ばれます。

非同期式(調歩同期式)では、クロック信号がありません。
送信側と受信側であらかじめどういった周期でデータを送るのかを決めておく必要があります。
そのうえで、送信側は最初にスタートbitを送り、そのスタートbitから決められた周期でデータを送るという約束のもと、受信側はデータを読み取ることになります。

同期式と非同期式はどちらが良いというものではなく、それぞれにメリット/デメリットがあります。

同期式:

  • メリット:同期のタイミングが明確なので高速化しやすい
  • デメリット:クロック線だけ通信線が増える

非同期式:

  • メリット:データ線だけでOK
  • デメリット:送信側と受信側でタイミングがずれる可能性がある
  • デメリット:スタートbitなどが必要なので1byteのサイズが大きくなり、転送効率が落ちる

UARTの概要

UARTの使用用途

UARTは非同期式の通信です。
データ線だけで通信ができることがメリットですので、組み込み機器から外部に出力される通信として使用されることが多いです。
とはいえ、UARTのまま外部配線するとノイズの影響を受けやすいので、RS-232CやRS-485などに変換して使用されることが多いです。

UARTの配線

UARTの端子には、送信用のTXと受信用のRXがあり、送信側のTXと受信側のRXを接続します。

上の図を見ていただければわかるように、デバイスAからBへの送信とBからAの送信が完全に独立しているので、両方のデバイスからの送信を同時に行うことができます。
これを全二重通信と呼びます。

全二重通信に対して、どちらか片方からのみしか送信できないものを半二重通信と呼びます。
UARTは全二重通信ですが、実際に通信するときは片方からのRequestに対してResponseするプロトコルが多いので、半二重の動作になることが多いです。

UARTの通信方法

UARTの1byte当たりの通信は以下の図のようになります。

UARTのポイントは以下の通りです。

  • 通信が発生していないときはHigh
  • 送信開始時、スタートbit(Low)から始まる
  • 送信終了時、ストップbit(High)で終わる
  • データbit数は、7bitか8bitを選択できる
    (通常は1byte=8bitなので、8bitを選択する)
  • パリティbitは、なし、Odd、Evenから選択できる
    なし以外を選択すると、誤り検出としてパリティエラーを検出できる

上の図のように、データbit数が8bit、パリティbitがなし以外の場合、UARTの1byteは11bitになることに注意が必要です。送信時間を見積もるときには11bitとして見積もる必要があります。

例として、UARTで100byteのデータを9600bpsで送る場合にかかる時間は、
100byte×11bit/9600bps=0.114583・・・≒114.6ms
となります。

フロー制御

UARTにはフロー制御と呼ばれる機能を付けることができます。
フロー制御とは、通信準備が整ってから通信相手に対して通信許可を出すことによって、データの取りこぼしを防ぐシステムです。
送信側は通信許可が出ているときしか送信することができません。

フロー制御は、なし、ハードウェアフロー制御、ソフトウェアフロー制御から選ぶことができます。

なしの場合はフロー制御をしませんので、上で説明した通りの動作となります。

ハードウェアフロー制御の場合は、TX・RXの通信線とは別に、制御用のRTS(Request To Send)とCTS(Clear To Send)の制御線が必要になります。
受信側が受信可能な場合はRTSでLowを出力し、送信側がCTSでLowを入力されたときは送信が可能となります。

ソフトウェアフロー制御の場合、通信線はTX・RXの2本のままですが、TX信号に通信許可や通信禁止の信号を送ることになります。
ただし、通信許可や通信禁止として使用する信号をメインの信号送信で使用してはいけないという制約が発生するので、CPUの負荷が大きくなったり伝送効率が落ちたりするデメリットがあります。

CSIの概要

CSIの使用用途

CSIは同期式の通信方法です。

UARTとは違い、同じ基板上にあるデバイスと通信するために使用することが多いです。
もちろん、同じ基板上だけに限らず、短距離であれば別基板上にあるデバイスにアクセスすることもあります。

CSIの配線と通信方法

CSIの端子は、CS(チップセレクト)、SCK(クロック)、SO(データ出力)、SI(データ入力)の4端子です。
MasterとSlaveのデバイス間において、SCKとCSはそのまま接続し、送信側のSOと受信側のSIが対応するように接続します。

CSはMaster側が操作し、Slave側はCSがLowになっているときのみシリアル通信の操作を実施します。
Slaveを複数接続することも可能で、その場合は今から通信をするデバイスのみCSをLowにすることによって、目的のデバイスと通信することができます。

SCKを操作するのもMaster側です。
MasterはSCKを操作しながらSOでの出力やSIでの入力を制御し、SlaveはMasterによって操作されるSCKに合わせてSIでの入力やSOの出力を実施します。

実は、CSI通信の場合、受信と送信の区別が明確ではありません。
動作としては、MasterもSlaveもクロックに合わせて受信も送信も同時に行います。
Slave側が決めたルールに従って受信か送信かが決まり、不要な方のデータは捨てることになります。
ルールによっては、Masterから見て上位4bitは送信、下位4bitは受信という場合もあります。

Master側の実装の都合としてクロックが動作する条件が送信をすることとなっているので、クロックを動作させるためには送信をする必要があります。
したがって、Masterがデータの受信をする場合、クロックを動作させるために任意のデータを送信し、代わりに入ってきたデータを受信データとして使用する、という実装をする必要があります。

CSIの位相

デバイスによってCSIのクロックの位相が異なる可能性があるので、データシートをきちんと読んでデバイスに合わせた設定にする必要があります。

位相は以下の2つの組み合わせにより、4パターンあります。

  • データ検知のタイミングがクロックの立ち上がりか立ち下がりか
  • クロックがHighから始まるかLowから始まるか

上の図の例では、クロックがHighから始まっており、データ検知はクロックの立ち上がりのタイミングとなっています。

I2Cの概要

I2Cの使用用途

こちらもSPIと同様に同期式の通信です。
ですので、SPI同様、同じ基板上にあるデバイスとの通信という用途が多いです。

なお、I2Cの正確な書き方は、I2Cと2を上付き文字にする書き方です。毎回2を上付きにするのは大変なのと、I2CやIICとも表記されることがあるので、ここではI2Cと記載させていただきます。
読み方は、I-squared-Cと読むのが正式らしいですが、「アイ・ツー・シー」と呼ばれることも多く、私はこちらで呼んでいます。

また、もともとはフィリップス・セミコンダクターズ社によって開発されたもので特許が取得されていましたが、2004年8月に失効しているので、現在はロイヤリティフリーで使用できます。

I2Cの配線と通信方法

I2Cの配線は以下の図のようになります。

データ線(SDA)とクロック線(SCL)の2本で接続することができます。
Master側がクロックを操作し、Slave側がクロックに合わせてデータを送受信します。

CSIと同様に1つのMasterに対して複数のSlaveを接続することができますが、CSIがCSで送信先を選択していたのに対し、I2Cでは最初の1byte目でアドレスを送信することで送信先を選択できます。

では、I2Cでどのようにデータを送るのかというと、少し複雑ですが、以下のようなルールで通信します。

1byte目は、一番最初にMasterからの通信開始合図となるスタートコンディションを出します。(図のS)
その後、図のA0~A6で7bitのアドレスを指定し、RWのbitでこれからのコマンドがReadなのかWriteなのかを指定します。(Read:1、Write:0)
最後に、Slave側がこの1byteのデータを受け取ったらACK(図のA)を返します。このACKは1byteごとにきちんと受信できていることを知らせるために必ず送ることになります。

2byte目~後ろから2byte目は、データの送信になります。
上の図はWriteの例となっており、Master側が8bitのデータを送信したあと、Slave側が1bitのACKを返します。
Readの場合は送信する側が反転し、Slave側が8bitのデータを送信したあと、Master側が1bitのACKを返します。

最後の1byteは、その直前までとほとんど変わらないのですが、最後に送信データ終了を示すストップコンディション(図のP)がMasterから送信されます。
最初のスタートコンディションからストップコンディションまでが一連の送信データであることを示しています。

まとめ

以上、組み込みでよく使用されるシリアル通信のうち、UARTとCSIとI2Cの用途や通信方法について説明してきました。

それぞれの特徴をよく理解して、適切に使い分けていきたいですね。

COMMENT

メールアドレスが公開されることはありません。

CAPTCHA