毎度毎度、馬鹿なバグがお約束になっておりますが、へい、今回もやってしまいました。もうデバイスを疑ったりしませんよ、みんな自分が悪いのです。自分で作ってしまうのだけれど、自分では予想していないもの、バグです。さて前回は一桁の7セグLEDでしたが、今回は四桁の7セグLEDです。タイマ割り込みでダイナミック駆動するという趣向。
※「部品屋根性」投稿順Indexはこちら
今回使用の4桁7セグLEDは、例の中華部品キットの中にあったアイキャッチ画像のものです。例によって付属CDの中の4桁7セグLEDのデータシートには会社名なく、あまつさえ、16ピンの結線図の横に12ピンの外形図があったりと、ツッコミどころはあるものの、その辺はもう慣れました。スルー。意外と使えるのが、若干残念な日本語の説明書であります。必要なのは、アノードコモンなのか、カソードコモンなのかの種別と、端子配置です。書いてありました。アノードコモンのタイプのようです。一応、Vf測って現物で確認、OKであります。
前回の1桁の7セグLEDはカソードコモンだったので、方向逆です。プラス、マイナス反転させる感じでブレッドボード上に回路を作ります。このタイプの4桁の7セグLEDの場合、
- 各桁毎、全セグメントのアノードが共通
- 4桁のaからdpまでの同一セグメントのカソードも共通
であります。というわけでスタティックに駆動したのでは4桁に異なる表示はできませぬ。各桁毎にまず表示すべきデータをカソード側に印加し、印加したタイミングでその桁のアノードだけを駆動する、と。すると1桁だけ所望の表示が光ります。素早く次の桁で同じことをやり、という塩梅で「素早く」各桁を駆動しつづければ、人の目にはちゃんと4桁表示されているように見える、という方式であります。
全てのセグメントに1対1で端子を割り振るのに比べたら遥かに結線数は少なくて済みます。信号数たかだか12本。しかし、ブレッドボード上、ジャンパ線はこんな感じになりました。
配線汚い。後で何とか綺麗にまとめたいところです。駆動するのは、例によってRISC-V搭載32ビットマイコンGD32VF103、seeed社製のボードです。GD32-SDK利用。カソード側は、74HC595を使いマイコンからはシリアルでセグメント毎の点灯データを送り、595でシリパラ変換して表示という「定番」な感じです。
既にGD32VF103のTIMER5を使って、1000分の1秒毎にタイマ割り込みがかかるようになっています。呼ばれる度に1桁ずつ表示することにしました。すると250分の1秒毎に全四桁表示されることになります。まあ、人の目には「とまらない」筈の速さ。
割り込みハンドラの中で呼んでいる表示ルーチンは以下のとおり。既にスタティック駆動の回で「実績」のある7セグの表示パタン点灯ルーチンを呼び出しております(実はそれがトラブルの元だった。。。)
void dynamicDisplay7Seg() { gpio_bit_reset(GPIOC, GPIO_PIN_0); gpio_bit_reset(GPIOC, GPIO_PIN_1); gpio_bit_reset(GPIOC, GPIO_PIN_2); gpio_bit_reset(GPIOC, GPIO_PIN_7); enableOE(LED7_OD); //DISABLE OUTPUT sendShiftRegister( displayData[ displayIndex++ ]); enableOE(LED7_OE); //ENABLE OUTPUT switch (displayIndex) { case 1: gpio_bit_set(GPIOC, GPIO_PIN_0); break; case 2: gpio_bit_set(GPIOC, GPIO_PIN_1); break; case 3: gpio_bit_set(GPIOC, GPIO_PIN_2); break; default: gpio_bit_set(GPIOC, GPIO_PIN_7); break; } displayIndex = (displayIndex > 3) ? 0 : displayIndex; }
割り込みハンドラ自体は、非常に簡単であります。以下のとおり。
void TIMER5_IRQHandler(void) { if(SET == timer_interrupt_flag_get(TIMER5, TIMER_INT_FLAG_UP)){ timer_interrupt_flag_clear(TIMER5, TIMER_INT_FLAG_UP); dynamicDisplay7Seg(); } }
こんな簡単なものなら、
一発で動く筈
と思ったら、お約束どおり駄目でした。何かね、変なパターンが表示されるのです。だから回路的には動いていそう。もうデバイスを疑ったりしませんよ。まずは「汚い」配線のチェックです。
でもね、大丈夫なんだこれが。よくこんな配線間違えないな、と悪態をついてもやったのは自分。はてさて。
結局のところ、またまた、お約束どおりでソフトでした。2つのバグが重なって、妙なパターンを表示していました。
スタティック駆動で「実績」のある筈の下位関数、カソードコモンのつもりで書いていました。用は点灯のとき1(ハイ)を出力するようにしていました。ところが、今回のデバイスはアノードコモンです。74HC595の側は0(ロー)を出力しないと点灯しません。まずこれでパターン反転。
さらに、自分で作った下位関数の仕様を忘れていました。4桁点灯のため、4桁分の数字を記録する配列を用意し、そこに表示する数値を格納しました。そして各桁を順番に読み出し、前回すでに準備済のLEDパターン用の配列に通してパターンに変換して下位関数に渡してました。ところが、自分で作った下位関数の中でもパターン変換していました。つまりパターン変換など不要。表示したい数値そのものを与えればよかったのです。2回パターン変換して反転、簡単ですが暗号化と言えなくもない。結果、不思議な表示が現れ、途方に暮れたと。
分かってしまえば何のことはない、上のコードは直した後のものです。
ようやく、所望のとおり点灯するようになりました。ちょっとピンボケですが、明るく写せた一枚。(見た目は明るいのだけれど、ダイナミック駆動のせいか、カメラの目だとなかなか明るく写せなかったです。カメラもしょぼい。)