RustでSTM32ベアメタル [4桁7セグメントLED]（概要編）

***<font color="#0080FF">Rust</font>***という言語で***STM32F3Discovery***というマイコンを動かし，***4桁7セグメントLED***を***ダイナミック点灯方式***で光らせるっていう記事です．
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264330/285beced-2702-6e44-0939-382dcda6b508.gif" width=320px>
成果物はこちら．↓
<a href="https://github.com/lenna-kun/stm32f3discovery-7_seg_led"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/lenna-kun/stm32f3discovery-7_seg_led.png" width="400px"></a>

#はじめに
***Rust***で組み込みをやってみよう！そう思ったきっかけは，***Googleのセキュリティキー***．
これについて調べていくうちに，***<font color="#0080FF">Tock</font>***という***Rust***で書かれた組み込みOSの存在を知りました．
最近趣味で***Rust***を使うようになった私は，この***Tock***にとても興味を持ちました．
そして，とりあえず***Rust***で簡単な自作組み込みOSを作ることと，***Tock***の中身の理解を最終目的として，***Rust***でベアメタルを始めることにしました．

しかし組み込み初心者の私には，どうやって始めればいいのかさっぱりわかりませんでした．

そんな時に出会ったのが[こちらの記事](https://tomo-wait-for-it-yuki.hatenablog.com/entry/2019/05/02/140855)．

というわけでこの方が和訳してくださった[Discovery(日本語版)](https://tomoyuki-nakabayashi.github.io/discovery/index.html)というドキュメントを手を動かしながら読み進めることにしました．
これが本当に***神資料***!

このドキュメントでは[f3](https://docs.rs/f3/0.6.1/f3/)という高レベルなクレートを使いますが，初心者にとって，これが勉強にならないなんてことは全くありません．
時々ちょっと細かく説明してくれたりする部分があり，かなり感覚が掴みやすくなります．

ちょっと掴めてきたら，今使ってるモジュールのソース読んだり，試しにそのモジュールを使わずに書いてみたりして，またわからなくなったらちょっと立ち止まって調べる．

自分はこれを繰り返してちょっとずつ下に降りていくという勉強方法をとりました．

はい，ここら辺でまえおきは終わりにして，本題に入ります．

#7セグメントLED（ダイナミック接続）

ここからは***カソードコモン***の7セグメントLEDを使用してる前提で話します．

<div style="float:left;">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264330/dccffb9f-f456-0db3-5afd-8113c1d3084a.png"  width="320px">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264330/1e5adbac-2ad5-5d47-44d9-c3443fedd96a.png" width="200px">
</div>


7セグメントLED(4桁)って，（ドット入れて）$8\times4=32$個のLEDからできてるのに，一般的な4桁の7セグメントLED（ダイナミック接続）はピンが12個しかついていない．
なので，まずはどうやって32個のLEDを制御するのかについて説明します．

まず12本のうち4本（図の$\rm {D1}$~$\rm {D4}$）が，どこの桁を表示させるかっていう信号を入力するためのピン．それぞれの桁に接続されている***コモン端子***を*`Low`*にすると，その桁を光らせることができる．
残りの8本（図の$\rm {A}$~$\rm {F}$と$\rm {decimal}$）は，その桁の，どのLEDを光らせるかっていうピンです．光らせたいLEDに接続されているピンに電圧を与えれば，LEDが光る．

>え，でも待って，この方法だと4桁いっぺんに表示できなくない？

その通り．なので，表示させる桁と表示させるLEDの信号を高速に切り替えることで，人間の目には同時に光ってるように見えるようにする．
だから**ダイナミック**っていうんですね．

この方式を使うことによって，LEDを制御するために使わないといけないマイコンのピンを32ピンから12ピンに節約できるというわけですね！

#8ビットシフトレジスタ（74HC595）

上記の説明で，この***ダイナミック点灯方式***によってすでに20ピンくらい節約できてるということがわかったと思います．

ここからは，もっとピンを節約する方法について話します．

使うのは***<font color="#0080FF">8ビットシフトレジスタ</font>***．
どこを節約するかというと，どのLEDを光らせるかっていう8本のピン．
8ビットの***シフトレジスタ***を使うのは，光らせるLEDがドット入れて8個だからですね．

8本のピンから別々に信号を送るんじゃなくて，1本のピンから8ビットのデータを送信して，その各ビットでLEDを制御できたら便利だと思いませんか？
それを可能にするのがこの***シフトレジスタ***．

仕組みはおいといて，とりあえずこの***シフトレジスタ***がどんなことをしてくれるかについて説明します．

***シフトレジスタ***の主な役割は，***<font color="#0080FF">シリアル</font>***な信号を***<font color="#0080FF">パラレル</font>***に変換するということ．
もう少しわかりやすくいうと，順番に直列に受け取った複数のデータを，同時に並列に送信する形に変換するということ．
つまり，1本のピンから8ビットのデータを受信したら，その各ビットの値を，それぞれ8本の違うピンから同時に出力するわけです．

マイコンの1ピンを，8ピン分として***拡張***して使えるってことです！

##使い方

>え，じゃあマイコンに割り当てるのは桁選択の4ピンと，あとLEDの情報を送信する1ピンの，合計5本だけでいいの？

っていうと，残念ながらそういう訳ではない．

***シフトレジスタ***は内部で8個の***<font color="#0080FF">Dフリップフロップ</font>***を使っていて，クロック信号の立ち上がりで次の***フリップフロップ***に論理信号が移動するっていう仕組みになっているので，そのためのクロック信号を送る必要がある．

また，***フリップフロップ***に記憶された値を常時出力していては出力が乱れてしまうので，***シフトレジスタ***の内部では，***フリップフロップ***と出力の間に***<font color="#0080FF">ラッチ回路</font>***をかませてある．なので，この***ラッチ回路***用のクロック信号も送る必要がある．

<div style="float:left;">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264330/d1bd31c3-4261-b6a2-2c98-d8dd75fd1e2c.png" width="300px"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264330/7ef03ccc-0516-166d-f518-fcbee4a12724.gif" width="500px">
</div>
回路図は[こちらの記事](http://hello.world.coocan.jp/ARDUINO/arduino_4.html)がわかりやすい．

という訳で，使うのは$4+3=7$ピン．

#SPIモジュールの利用
***stm32f3Discovery***ボードには，***<font color="#0080FF">SPI</font>***モジュールというものが搭載されています．
前項の内容を，そのまま自分で実装しても良いのですが，***SPI***モジュールを利用すると，実装をより容易に行うことができます．

##SPI（Serial Peripheral Interface）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264330/23955f48-775f-b81e-eee9-df581b5d5801.png" width="320px">

>SPIとは，コンピュータ内部で使われるデバイス同士を接続するバスである．
SPIバスは、単一のマスタと、1つ以上のスレーブの装置で操作することができる．
[Wikibedia](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%AB%E3%83%BB%E3%83%9A%E3%83%AA%E3%83%95%E3%82%A7%E3%83%A9%E3%83%AB%E3%83%BB%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9)

ここでは***SPI***についてこれ以上詳しくは述べません．
マスタは，該当するスレーブの*`SS`*線を*`Low`*にすることで、通信する***スレーブ***を選択する．

##どう使うのか

*`MISO`*線は，***スレーブ***からデータを送るためのものなので，今回は使わない．
残りの3線を，以下の表のように割り当てれば，***SPI***を使って***シフトレジスタ***を制御することができる．

|シフトレジスタ|SPI|
|:-:|:-:|
|SER|MOSI|
|SCK|SCLK|
|RCK|SS|

###SPIモード

***SPI***には4つのモードがある．
それらを表と図で示します．（図は[リファレンスマニュアル](https://www.st.com/resource/en/reference_manual/dm00043574-stm32f303xb-c-d-e-stm32f303x6-8-stm32f328x8-stm32f358xc-stm32f398xe-advanced-arm-based-mcus-stmicroelectronics.pdf)から）
図の*`MISO`*線の部分は今回は関係ありません．

|SPIモード|CPOL|アイドル状態の<br>クロックの極性|CPHA|データのサンプリングに<br>使われるクロックの位相|
|:-:|:-:|:-:|:-:|:-:|
|0|0|LOW|0|立上がり|
|1|0|LOW|1|立下がり|
|2|1|HIGH|1|立下がり|
|3|1|HIGH|0|立上がり|
<img width="592" alt="スクリーンショット 2020-04-30 18.38.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264330/bd42b818-ab64-28a5-2c0d-3975a61bc737.png">
さて，***シフトレジスタ***を制御する上では，これら4つのモードのうち，どれを使えばいいのでしょうか．

###シフトレジスタのタイミングチャート

ここで[シフトレジスタのデータシート](http://akizukidenshi.com/download/ds/unisonic/u74hc595.pdf)を見てみましょう．
<img width="580" alt="スクリーンショット 2020-04-30 20.02.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264330/27167adb-d598-c796-a997-a128fddee64d.png">
*`CPOL=0`*，*`CPHA=0`*の時の図が書いてありますね．
***SPI***の*`モード0`*を使えば***シフトレジスタ***が制御できるということがわかりました．

#実装編へ続く
実装編では，実際の***Rust***のコードとかも載せながら説明していきます．