組み込みの通信規格"きほんのき"

## はじめに

この記事は株式会社ビットキー Advent Calendar 2022 1日目の記事です。
本日(初日！！)は @hu11911が担当します。よろしくお願いたします。

(この記事は主に組み込みエンジニア向け記事です。
しかし、基本的な内容ですのでそれ以外の方も読みやすいかと思います。)


最後まで楽しく読んでいただければ幸いです。

## 自己紹介

まずは私の自己紹介から。

現職では**組み込みソフトの設計開発**を行っています。C言語を使って設計しています。
その中でも、市場リリース済みの既存製品の保守や機能追加が主な担当です。
(周りを見渡す。どうやら組み込みソフトエンジニアはQiitaではあまり生息していないようだ。)

前職は**半導体製造装置メーカー**で制御ソフトエンジニアでした。
そこから約4年半、半導体製造装置業界という、何やら不可思議な業界に身を置いておりました。
ロジックやメモリメーカー様向けに商売をしてまして、世に言う**半導体不足**の一端を担っておりました。
半導体不足すぎて、お客様の**半導体部品**を作るための装置が、そのお客様の**半導体部品**が納品されないため製造が進まないという一種の**デッドロック状態**に陥ったりしておりました。(社員個人個人はベストを尽くしておりました)
前職ではC++やC、UI設計もやっていたのでJavaScriptとHTML/CSSなんかも。あと、VBAですね。
Windowsアプリケーション開発が主な業務で、あとはマイコン上の会社独自OSにおけるアプリケーション設計とか行なっていました。

1992年千葉県生まれです。
と言いつつ、思春期は学校生活を含めてほとんどの生活を東京で過ごしてきました。
しかし、大学時代ぐらいからやっと千葉県の良さを感じることができました。
おすすめの観光地は**養老渓谷**と**東京ディズニーシー**です。

前置きが長くなってしまいましたが、いよいよ本題に移ります。

## 組み込みの通信規格"きほんのき" の前に...

早速本題。と思ったのですが、その前にこの記事を書こうと思った背景をお話しします。

## 組み込みの通信規格知らない

これは問題です。
今までの経験からも通信規格の基本を理解をしないと**痛い目**にあうのはわかっています。

自己紹介にも書いた通り、前職では制御ソフトの設計開発を行なっていました。
入社当時はこう思っていました、ソフトの知識とプラスアルファでモータやバルブの理解さえとかしてれば良いか、と。
しかし、いろいろな**痛い目**にあう中でそれは勘違いということがわかります。
モータやバルブの知識とさらに通信の知識も**必須**でした。

まず、PC同士の通信は**TCP/IP**。
その**TCP/IP**上で実装された会社独自のプロトコルでプロセス同士がメッセージのやり取りをしていました。
**TCP/IP**の理解はもちろん、**ソケット通信**、**プロセス間通信**そして会社独自プロトコルの理解が必須でした。
あとは、UIとしてWEBブラウザを採用していたので**WEBソケット**の理解。
モータ制御に最適化されたリアルタイム性重視の**産業用通信プロトコル**の理解も必要です。例としてEtherCAT、RTEXなどです。
あとは、**RS-485**、**RS-232C**などのシリアル通信のインターフェースとその上に実装された独自プロトコルなど。
通信まみれ。それだけレイヤーが多く存在していたということです。

現職になってから、これらの通信知識が直接活かせる場面はまだありません。
(今まで仲良くしてきたのでちょっともの寂しいような。)

とはいえ入社から数ヶ月、やはり組み込みソフトでも通信規格の理解は重要だ、とひしひしと感じてきました。

人は過ちを繰り返す。同じ轍を踏みたくない。転ばぬ先の杖。
良い機会なので組み込み領域における通信規格を"**きほんのき**"から調べてみました。
(初心を忘れず。全力投球！オー！)

# 組み込み領域の通信規格"きほんのき" 

1. そもそもプロトコルって何？
1. シリアル通信とは？
1. よく使われる組み込み領域の通信規格
    * SPI
    * I2C
    * UART


### そもそもプロトコルって何？
呼吸をするように**プロトコル**と連呼しておりましたが、そもそものこいつ何者なのでしょう。

元々のプロトコルの意味は、儀礼や典礼、議定書だそう。

現在では、以下の意味で使われています。

>プロトコルとは、コンピュータでデータをやりとりするために定められた手順や規約、信号の電気的規則、通信における送受信の手順などを定めた規格を意味します。異なるメーカーのソフトウエアやハードウエア同士でも、共通のプロトコルに従うことによって、正しい通信が可能になります。
(https://www.keyence.co.jp/ss/general/iot-glossary/protocol.jsp より引用)


"通信プロトコル"とつけば、通信する上ので取り決めや約束事ということですね。
例として、ピンアサイン、データ形式、パケット構成、同期の取り方、エラー処理などがプロトコルとして取り決められます。
もちろん、レイヤーによってどこまでをプロトコルとして定めるのかは異なります。

プロトコルさえ守っていれば異なるメーカー同士がデバイス内部の詳細な仕様を知らなくてもデータのやり取りができるわけです。
これは便利!

なるほど、プロトコルについてはわかりました。(コーヒーをすする。)

次に通信について調べる中で、よく見た言葉が**シリアル通信**です。

### シリアル通信とは？
そもそも**シリアル通信**とはなんでしょう。

>シリアル通信：1つのデータ伝送路を使い。1ビットずつデータを送信する方式
>パラレル通信：複数の伝送路を使い、1度に複数のデータを送信する方式
(https://emb.macnica.co.jp/articles/8191/)より引用

1ビットずつ送ると聞くとなにやら原始的に見えます。
しかし、その単純さゆえパラレル通信と比べ線が**少なく**済みます。
この利点からノイズに**強く**、**同期**も取りやすく、それゆえ**長距離**通信もいける。

これらがシリアル通信が多くの規格で採用されている所以でしょう。

シリアル通信に関しては組み込み/制御関係なくよく耳にします。
例えばご存知のUSBなんかもUniversal Serial Busと読んで字の如く、シリアル通信を採用しています。
先の述べた規格の多くもシリアル通信です。(RS-485、Ethernetなど)
このことからも、**多くの規格がシリアル通信を採用**していることがわかります。

一方でパラレル通信は通信速度がシリアル通信よりも早いことが理論上の利点です。
これは、**1クロックで複数の線から同時**にデータが取れるためです。
が、技術の発展により最近ではシリアル通信の速度も速くなってきています。

悲しいかなパラレル通信の唯一の利点もあまり活かされなくなってきました。
パラレル通信の規格ってなんだっけ...というレベルで普及はしていないのが現状です。
(パラレル通信の規格を5つ答えよ、と問われても答えられない。)

完全に余談ですが、Serial(シリアル)は**連続**の意味ですが、Cereal(シリアル)は**穀物**です。
ホテルの朝食バイキングにあるとCOOLなのが**Cereal**食品ですね。ドライフルーツも入ってると尚良し。

基礎が固まったところで、具体的に組み込み領域でよく使われる通信規格を調べてみます。

### 組み込み領域の通信規格(SPI、I2C、UART)
手始めに社内ひいては世の中にあるデバイスの製品概要仕様書をまじまじと読んでみます。
すると、以下の３つの通信規格がよく出てくることがわかりました。

* SPI
* I2C
* UART

組み込み通信規格の御三家、三銃士です。
この三つさえ理解すれば"**きほんのき**"までは押さえられそうです。
一つづつ見ていきましょう。

#### SPI
SPIはシリアル通信の規格で、**S**erial **P**eripheral **I**nterfaceの略です。
SPIは**同期式**の**全二重**の**マスタスレーブ型**の通信です。はて、全二重？マスタスレーブ？
この辺りの説明を理解するために、SPIの通信線を見てみます。
SPIデバイスには４つの信号線があります。
・クロック（SPI CLK、SCLK）
・スレーブ・セレクト（SS）
・マスタ出力／スレーブ入力（MOSI）
・マスタ入力／スレーブ出力（MISO）

クロック生成する側を**マスタ**、クロックを受け取る側を**スレーブ**と呼びます。
上記の**マスタスレーブ型**というのはここからきています。
そして、クロックの立ち上がり/立ち下がりエッジによって**同期**をとっています。

全二重とは一つの通信路でデータを送る方向は**一方通行**の通信だけ、という方式です。
SPIでは出力と入力が二つに分かれているので**全二重**です。

スレーブ・セレクト（SS）はマスタからスレーブへデータを送る線で、マスタが通信したいスレーブに**LOW**を入力します。
送受信の対象から切り離す場合は**HIGH**を入力します。
このスレーブ・セレクトのラインにより、**単一のマスタ**と**複数のスレーブ**間でのデータの送受信が可能になります。
デバイスによっては**チップ・セレクト**(CS)と表記されている場合もあります。

内容は理解できましたが、これだけだとSPIの立ち位置がわかりません。
続いて、I2Cについて見てみます。

#### I2C
**I2C**はInter-Integrated Circuitの略で、**同期式**の**半二重**の**マスタスレーブ型**の通信。
名前からはわかりませんが、こちらもシリアル通信の一種です。
一部の仕様書では、**TWI**(**T**wo-**W**ire serial **I**nterface)とも言われています。
**TWI**の方がどんな通信か名前からわかりやすいですね。

I2Cの信号線は２つで、一つは**送受信**、もう一つは**クロック信号**です。

SPIと同じく、**クロック信号**の線がI2Cにもあります。
こちらも**マスタ/スレーブ**の概念があり、**SPI**と同じですね。

信号線の違いとしてはSPIでは**4本**だった信号線がI2Cでは**2つのみ**という点が挙げられます。(1/２倍です1/２倍)

まず、スレーブ・セレクトがありません。
その代わりにI2Cではマスタからのデータに**スレーブのアドレス**(7bit or 10bit)が含まれます。
スレーブは送られたアドレスと自分自身のアドレスを比較して、一致すればマスタとのデータの送受信を行います。
なので、I2CでもSPIと同じく**単一マスタ**と**複数スレーブ**のシステムを組めます。

さらにI2Cは**複数マスタ**と**複数スレーブ**のシステムにも対応しています。
マスタは送受信のラインを監視することで、マスタ同士のデータの衝突を防ぎます。
他のマスタが送受信中は、自身の送受信を行いません。
ただし、マスタにはアドレスがないので、マスタ同士の送受信には対応していません。

さらに**SPI**では送信受信で別々になっていた線も、I2Cでは送受信で**１つ**の線となっています。
このように送受信で一つの信号線で行う方式が**半二重方式**です。
トランシーバーをイメージしていただければわかりやすいですね。こちらは無線ですが、半二重という点では同じです。
通信路を送受信で共有しているため、一方が話している(=送信している)間は受信側は話すことができません。
「・・・です。どうぞ」と相手の応答を仰ぐのは、このためです。

I2Cの利点は、複雑な配線を**回避**して双方向のデータのやり取りを実現できることです。
SPIと比べても通信線が4→2となっているので、SPIより実装が容易です。
一方の欠点として、SPIと比べると通信速度は劣ります。先述の通り、**半二重**であることがこれに起因します。

少ない通信線が、**メリット**であり**デメリット**でもあるわけです。

#### UART
最後に**UART**です。
こちらは**U**niversal **A**synchronous **R**eceiver/**T**ransmitterの略。非同期の全二重方式です。

信号線は**送信**(Tx)と**受信**(Rx)の2本のみです。
送信受信が分かれているので**SPI**と同じく**全二重**ですね。

**送信**(Tx)と**受信**(Rx)・・・おや、何か足りない気がします。
**クロック信号**がありません！

先の**SPI**や**TWI**と異なり、クロック信号が**ない**ことが**UART**の特徴です。
それゆえU**A**RTは**A**synchronous（非同期）な通信規格なのです。

**UART**にはクロック信号がないため、通信する前に送受信デバイス**両方**で**同一のボーレート**を設定する必要があります。
ボーレートはいわゆる**bps**(bit per sec)で、1秒あたりの最大転送ビット数を表しています。
(厳密にはボーレートは一秒間に行われる変調レートを表していてbpsとは異なります。
が、シリアル通信では同義と捉えて差し支えないです。）
そして、送信開始/終了もクロック信号がないためデータラインの立ち下がり/立ち上がり**エッジ**で判定されます。

**UART**は**SPI**の**全二重方式**と**I2C**の信号線の**少なさ**をまさにいいとこ取りをした規格のように見えます。
しかし、ボーレートの設定が同一でなかった場合に送受信の**タイミングがずれてしまう**というデメリットがあります。
逆にいうと、ボーレートの設定さえ同一であれば信号線の少ない全二重を採用した通信としてその力を発揮してくれます。

さらに、マスタスレーブの関係が**ない**ため、単一のデバイス同士のやり取りのみ対応しています。

## 通信規格まとめ

ここまでの３つの規格のざっくりまとめです。

|  規格  |  SPI  |  I2C(TWI)  | UART |
| ---- | ---- | ---- | ---- |
| 信号線の本数 | 4 | 2 | 2 |
|    双方向通信   | 全二重  |  半二重      | 全二重 |
|  同期/非同期  |  同期 |  同期  | 非同期|
| クロック信号 | あり |  あり  | なし|
|  システム  |  単一マスタ/複数スレーブ  |  複数マスタ/複数スレーブ  | 単一デバイス/単一デバイス
|  特徴  |  I2Cよりも速い通信速度  |  複雑な配線の回避  | ボーレートの設定が必須


## おわりに
いかがだったでしょうか。
組み込み領域におけるシリアル通信規格の"き"を押さえられましたでしょうか。(コーヒカップをおく。)

この辺りの技術は当たり前すぎて読み飛ばしがちですが、今一度じっくりと調べてみると奥が深い。

立ち返ってあえて基本を深く掘っていくことは、新鮮な気持ちですね。
知っている**つもり**で、ずるずる社会人歴を積み重ねていくのなかなかにリスキーです。
むしろ「ああ、シリアル通信ね？知ってるけど知らないような気がします。」みたいな中途半端なのが一番**危険**です！
無常の風は時を選ばず。
ぜひ、ふとした時に業務の中で**きほんのき**の大切さを思い出していただければと思います。
(よし、まとまったな！とガッツポーズ。)

ここまでお読みいただきありがとうございます！

2日目は、@qiita-de-giidaが担当します。
引き続き株式会社ビットキー Advent Calendar 2022をお楽しみください！

参考資料

Analog-Dialogue SPIの基本を学ぶ
https://www.analog.com/jp/analog-dialogue/articles/introduction-to-spi-interface.html
Analog-Dialogue UART――多様な非同期通信に対応可能なハードウェア通信プロトコル
https://www.analog.com/jp/analog-dialogue/articles/uart-a-hardware-communication-protocol.html
IO-DATA Raspberry Pi 4 Model B（UD-RP4Bシリーズ） 仕様
https://www.iodata.jp/product/pc/raspberrypi/ud-rp4b/spec.htm
Macnica よく分かる！ シリアル通信基礎講座
https://emb.macnica.co.jp/articles/8191/
DENGYO 無線通信に必要な変調技術
https://www.den-gyo.com/labo/kouza/radio03.html
Rohm インターフェースの選び方
https://www.rohm.co.jp/electronics-basics/memory/memory_what7
Nordic semiconductor Products
https://www.nordicsemi.com/Products