Rustという言語でSTM32F3Discoveryというマイコンを動かし,4桁7セグメントLEDをダイナミック点灯方式で光らせるっていう記事です.
成果物はこちら.↓
はじめに
Rustで組み込みをやってみよう!そう思ったきっかけは,Googleのセキュリティキー.
これについて調べていくうちに,TockというRustで書かれた組み込みOSの存在を知りました.
最近趣味でRustを使うようになった私は,このTockにとても興味を持ちました.
そして,とりあえずRustで簡単な自作組み込みOSを作ることと,Tockの中身の理解を最終目的として,Rustでベアメタルを始めることにしました.
しかし組み込み初心者の私には,どうやって始めればいいのかさっぱりわかりませんでした.
そんな時に出会ったのがこちらの記事.
というわけでこの方が和訳してくださったDiscovery(日本語版)というドキュメントを手を動かしながら読み進めることにしました.
これが本当に神資料!
このドキュメントではf3という高レベルなクレートを使いますが,初心者にとって,これが勉強にならないなんてことは全くありません.
時々ちょっと細かく説明してくれたりする部分があり,かなり感覚が掴みやすくなります.
ちょっと掴めてきたら,今使ってるモジュールのソース読んだり,試しにそのモジュールを使わずに書いてみたりして,またわからなくなったらちょっと立ち止まって調べる.
自分はこれを繰り返してちょっとずつ下に降りていくという勉強方法をとりました.
はい,ここら辺でまえおきは終わりにして,本題に入ります.
7セグメントLED(ダイナミック接続)
ここからはカソードコモンの7セグメントLEDを使用してる前提で話します.
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ピンくらい節約できてるということがわかったと思います.
ここからは,もっとピンを節約する方法について話します.
使うのは***8ビットシフトレジスタ.
どこを節約するかというと,どのLEDを光らせるかっていう8本のピン.
8ビットのシフトレジスタ***を使うのは,光らせるLEDがドット入れて8個だからですね.
8本のピンから別々に信号を送るんじゃなくて,1本のピンから8ビットのデータを送信して,その各ビットでLEDを制御できたら便利だと思いませんか?
それを可能にするのがこのシフトレジスタ.
仕組みはおいといて,とりあえずこのシフトレジスタがどんなことをしてくれるかについて説明します.
シフトレジスタの主な役割は,***シリアルな信号をパラレル***に変換するということ.
もう少しわかりやすくいうと,順番に直列に受け取った複数のデータを,同時に並列に送信する形に変換するということ.
つまり,1本のピンから8ビットのデータを受信したら,その各ビットの値を,それぞれ8本の違うピンから同時に出力するわけです.
マイコンの1ピンを,8ピン分として拡張して使えるってことです!
使い方
え,じゃあマイコンに割り当てるのは桁選択の4ピンと,あとLEDの情報を送信する1ピンの,合計5本だけでいいの?
っていうと,残念ながらそういう訳ではない.
シフトレジスタは内部で8個の***Dフリップフロップを使っていて,クロック信号の立ち上がりで次のフリップフロップ***に論理信号が移動するっていう仕組みになっているので,そのためのクロック信号を送る必要がある.
また,フリップフロップに記憶された値を常時出力していては出力が乱れてしまうので,シフトレジスタの内部では,フリップフロップと出力の間に***ラッチ回路をかませてある.なので,このラッチ回路***用のクロック信号も送る必要がある.
回路図は[こちらの記事](http://hello.world.coocan.jp/ARDUINO/arduino_4.html)がわかりやすい.という訳で,使うのは$4+3=7$ピン.
SPIモジュールの利用
stm32f3Discoveryボードには,***SPI***モジュールというものが搭載されています.
前項の内容を,そのまま自分で実装しても良いのですが,SPIモジュールを利用すると,実装をより容易に行うことができます.
SPI(Serial Peripheral Interface)

SPIとは,コンピュータ内部で使われるデバイス同士を接続するバスである.
SPIバスは、単一のマスタと、1つ以上のスレーブの装置で操作することができる.
Wikibedia
ここではSPIについてこれ以上詳しくは述べません.
マスタは,該当するスレーブの*SS
線をLow
にすることで、通信するスレーブ*を選択する.
どう使うのか
MISO
線は,スレーブからデータを送るためのものなので,今回は使わない.
残りの3線を,以下の表のように割り当てれば,SPIを使ってシフトレジスタ**を制御することができる.
シフトレジスタ | SPI |
---|---|
SER | MOSI |
SCK | SCLK |
RCK | SS |
SPIモード
SPIには4つのモードがある.
それらを表と図で示します.(図はリファレンスマニュアルから)
図の*MISO
*線の部分は今回は関係ありません.
SPIモード | CPOL | アイドル状態の クロックの極性 |
CPHA | データのサンプリングに 使われるクロックの位相 |
---|---|---|---|---|
0 | 0 | LOW | 0 | 立上がり |
1 | 0 | LOW | 1 | 立下がり |
2 | 1 | HIGH | 1 | 立下がり |
3 | 1 | HIGH | 0 | 立上がり |

シフトレジスタのタイミングチャート
ここでシフトレジスタのデータシートを見てみましょう.
CPOL=0
,CPHA=0
の時の図が書いてありますね.
SPIのモード0
を使えばシフトレジスタ**が制御できるということがわかりました.
実装編へ続く
実装編では,実際のRustのコードとかも載せながら説明していきます.