応用情報技術者 2011年 春期 午後 問07
LEDを使用したディジタル時計の設計に関する次の記述を読んで、設問1~3に答えよ。
Z社では、6個の7セグメントLEDで年月日及び時分秒を表示するディジタル時計の設計を行っている。
〔ディジタル時計の機器構成〕
ディジタル時計のブロック図を、図1に示す。このディジタル時計は、LED、MPU、クロックカウンタ、リアルタイムクロック(以下、RTCという)、機械的な押ボタン式スイッチ(以下、SWという)、及びプログラムで入出力を設定できるプログラマブル入出力装置(以下、PIOという)で構成される。

〔ディジタル時計の動作〕
(1) 電源を入れると、初期化プログラムによってRTC、クロックカウンタ、PIOにそれぞれ初期設定データを書き込み、初期化する。SWを押しているときは年月日を表示し、押していないときは時分秒を表示する。
(2) RTCは年月日、時分秒データ(以下、時刻データという)を保持し、RTC自身が時刻を更新する。RTCは1秒ごとにMPUに割込みを行い、RTC割込みハンドラを起動する。RTC割込みハンドラは、RTCから時刻データを読み込む。読み込んだデータは、配列Dateに、西暦年の下2けた、月、日が格納され、配列Timeに、時、分、秒が格納される。例えば、読み込んだ時刻データが2011年4月17日、12時34分56秒ならば、Date[0]〜Date[5]に1, 1, 0, 4, 1, 7が、Time[0]〜Time[5]に1, 2, 3, 4, 5, 6が格納される。
(3) クロックカウンタは、クロックをカウントし、1ミリ秒ごとにMPUに割込みを行い、クロックカウンタ割込みハンドラを起動する。
〔PIO〕
PIOの構成を図2に示す。PIOは、それぞれ16ビットで構成される入出力制御レジスタ(以下、PIO_Rという)とデータレジスタ(以下、PIO_Dという)から成る。PIOには16個の入力又は出力の設定が可能な端子があり、それぞれPIO_Dの1ビットに割り当てられる。
(1) PIO_Rは、PIO_Dの各ビットを入力にするか出力にするかを決める。PIO_RのビットRiを1にするとPIO_DのビットDiは出力に指定され、0にすると入力に指定される。
(2) PIO_Dにデータを書き込むと、PIO_Rによって出力に指定されたビットのデータだけが端子から出力される。一方、PIO_Dのデータを読み込むと、PIO_Rによって入力に指定された端子のデータだけが読み込まれる。入力に指定されていないビットのデータを読み込むと不定の値となる。

(3) PIO_Dのに割り当てられた端子には、SWが接続される。SWを押している間はオンとなり、そのときPIO_Dを読み込むとそのビットは1、SWがオフのときそのビットは0となる。PIO_Dを読み込むとそのときのの値がSWの状態となる。
〔ダイナミック点灯方式〕
このディジタル時計で使用しているLEDの表示方法は、ダイナミック点灯方式である。ダイナミック点灯方式は、短時間に一つのLEDだけを点灯し、点灯するLEDを順に切り替え、あたかも全体が点灯しているかのように見せる方式である。
図3にLEDのセグメント割当てを、図4にLED表示部の構成を示す。
(1) PIO_Dの下位8ビット〜のうち、〜にはLEDのセグメントa〜gを割り当てて、には小数点dpを割り当てる。具体的には、をLEDのセグメントaに、をbに、…、をgに割り当てる。
(2) PIO_Dの上位8ビット〜のうち、〜にはLED0〜LED5を割り当て、にはSWを割り当てる(は使用しない)。具体的には、をLED5に、をLED4に、…、をLED0に割り当てる。
(3) LEDを点灯するためには、点灯するセグメントに対応するビット〜に1を書き込み、点灯するLEDに対応するビット〜に1を書き込む。例えば、表示する時分秒のうち、“分”の10分台の数字はLED3、1分台の数字はLED2である。LED3に4を表示させるためには、PIO_Dに16進数0866を書き込む。

〔クロックカウンタ割込みハンドラ〕
クロックカウンタ割込みハンドラは、ダイナミック点灯の制御及びSWの入力の判定を行う。その流れ図を図5に示す。
配列Pattern[0]〜[9]はそれぞれ16ビットの符号なし整数で、LEDに0〜9を表示するための点灯セグメントの情報を格納する。例えば、Pattern[4]はLEDに4を表示するため、16進数0066を格納している。
iはLEDを示すカウンタ、cntはSWの切替え時に状態が安定するまで待ち合わせるためのカウンタで、それぞれ16ビットの符号なし整数であり、初期値はいずれも0である。
swStateはSWの状態を表す1ビットの変数であり、prevは直前の割込み処理で検出したSWの値を表す1ビットの変数である。初期値はいずれも0である。
work及びpworkは、16ビット符号なし整数であり、作業用の変数である。
図5中の①の処理は、SWの状態が変化したときに、状態が安定するまで待ち合わせる処理である。
設問1:
問題文を見る初期化プログラムによって、PIO_Rを初期化する設定値を16進数4けたで答えよ。ただし、PIO_Dの未使用のビットは入力として設定すること。
模範解答
3FFF
解説
解答の論理構成
- 出力と入力を分ける規則を確認
引用:
・「PIO_RのビットRiを1にするとPIO_DのビットDiは出力に指定され、0にすると入力に指定される。」 - どのビットがLED用かを整理
引用:
・「〜にはLEDのセグメントa〜gを割り当てて、には小数点dpを割り当てる。」
・「〜にはLED0〜LED5を割り当て、にはSWを割り当てる(は使用しない)。」
よって
• 出力にすべきビット … 〜(合計14ビット)
• 入力にすべきビット … (SW)、(未使用) - PIO_Rのビット列を決定
RビットはDと同番号対応。
• R0~R13: 出力 →1
• R14, R15: 入力 →0
ビット15側から並べると
0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 16進数へ変換
4ビットずつ区切ると
0011 1111 1111 1111 → 3 F F F
従って初期化値は「3FFF」。
誤りやすいポイント
- 「 にはSW」とあるため、誤ってR14を1にしてしまう
- 「 は使用しない」を見落とし、R15を1にしてしまう
- ビット番号と16進数桁の上下関係を逆に読み取る
- LED6個=6ビットと勘違いし、下位8ビットのセグメント分を忘れる
FAQ
Q: 「未使用ビットは出力にしても動きませんか?」
A: 要求は「PIO_Dの未使用のビットは入力として設定」と明示されているので、仕様どおり入力にします。
A: 要求は「PIO_Dの未使用のビットは入力として設定」と明示されているので、仕様どおり入力にします。
Q: SWを押している間だけ入力にすれば良いですか?
A: ハード的には常にSWが端子に接続されているため、初期化時点でR14を0(入力)に固定します。
A: ハード的には常にSWが端子に接続されているため、初期化時点でR14を0(入力)に固定します。
Q: 3FFFの先頭3がどこから来たのか覚えにくいのですが?
A: 先頭2ビット(R15, R14)が0、続く14ビットが1なので、 → 0x3FFFと覚えると確認しやすいです。
A: 先頭2ビット(R15, R14)が0、続く14ビットが1なので、 → 0x3FFFと覚えると確認しやすいです。
関連キーワード: PIO, ビットマップ, レジスタ設定, 出力制御, セグメントLED
(1)a、bに入れる適切な配列名を答えよ。
模範解答
a:Time
b:Date
解説
解答の論理構成
-
表示内容とSWの関係を確認します。問題文には
「SWを押しているときは年月日を表示し、押していないときは時分秒を表示する。」
とあります。したがって
• SWオフ(swState = 0)→ 時分秒を表示
• SWオン(swState = 1)→ 年月日を表示 -
RTCから読み取った時刻データの格納先は次のとおりです。
「読み込んだデータは、配列Dateに、西暦年の下2けた、月、日が格納され、配列Timeに、時、分、秒が格納される。」 -
図5のフローでは(判定) swState = 0
├─ Yes → work ← a[i]
└─ No → work ← b[i]という処理が示されています。
• swState = 0のときは時分秒を表示するのでTime配列を参照する必要があります。
• 逆にswState ≠ 0(SWを押下)では年月日を表示するのでDate配列を参照します。 -
よって a にはTime、b にはDateが入ります。
誤りやすいポイント
- swStateの0/1を逆に覚えてしまい配列名を取り違える。SWオフ=0=時分秒です。
- DateとTimeの要素順を混同し「年・月・日」「時・分・秒」のどちらがどちらの配列かを勘違いする。
- 表示用カウンタiが共通であることから「どちらの配列でも同じ桁を指す」と理解できず、配列切替えの意味を見落とす。
FAQ
Q: DateとTimeに格納されるのは文字列ですか、数値ですか?
A: 問題文にあるとおり「配列Dateに…1, 1, 0, 4, 1, 7が、配列Timeに…1, 2, 3, 4, 5, 6が格納」となっており、各要素は1桁ずつの数値です。
A: 問題文にあるとおり「配列Dateに…1, 1, 0, 4, 1, 7が、配列Timeに…1, 2, 3, 4, 5, 6が格納」となっており、各要素は1桁ずつの数値です。
Q: swStateはなぜ1ビット変数なのですか?
A: SWのオン/オフを判定するだけなので0/1の1ビットで十分だからです。
A: SWのオン/オフを判定するだけなので0/1の1ビットで十分だからです。
Q: iが0にリセットされる条件 d とは何ですか?
A: 図5内の判定は「i = 5か?」など6個のLEDを巡回し終えたかを確認する部分です。本問では a[i] と b[i] の配列名を問うているため詳細は設問外です。
A: 図5内の判定は「i = 5か?」など6個のLEDを巡回し終えたかを確認する部分です。本問では a[i] と b[i] の配列名を問うているため詳細は設問外です。
関連キーワード: 7セグメントLED, ダイナミック点灯, 割込み処理, 入出力制御, デバウンス
(2)c、dに入れる適切な式を答えよ。
模範解答
c:13-i
d:i=6又は i>=6 又は i>5
解説
解答の論理構成
-
LEDとPIOビットの対応を確認
【問題文】では、上位8ビットについて
「具体的には、をLED5に、をLED4に、…、をLED0に割り当てる。」
とあります。よって
• LED5 → ビット13
• LED4 → ビット12
• …
• LED0 → ビット8 -
iの意味
クロックカウンタ割込みハンドラでは「iはLEDを示すカウンタ」と明記されています。
初期値が0なので、
• i=0で LED5
• i=1で LED4
• …
• i=5で LED0
を順に駆動します。 -
c(ビット位置)の導出
LED5を点灯させるときはビット13、LED4のときは12…となるので、
点灯させたいビット番号 = 13 − i
です。従って
c = 13-i -
d(ループ終了判定)の導出
LEDは全部で6個ですから、iを0→1→…→5まで使った後、次はリセットする必要があります。
・iを1増やした直後に6になったらリセット
・あるいは「6以上になったら」でも同義
したがって d には
i=6、i>=6、i>5
のいずれかで条件を満たします。
誤りやすいポイント
- LEDとビットの対応方向を逆に読む
がLED0で がLED5です。左端(LED5)が最上位ビット側になる点に注意してください。 - iのカウント開始位置を勘違いする
i=0がLED0だと誤解すると「8+i」としてしまい不正解になります。 - 6個なのに「7になったらリセット」としてしまう
i++ の直後の値を考慮しない典型的なoff-by-oneミスです。
FAQ
Q: ビット番号は0‒15のどちら側から数えますか?
A: 【問題文】に示されたように、 が最下位ビット、 が最上位ビットです。したがって「ビット13」は に相当します。
A: 【問題文】に示されたように、 が最下位ビット、 が最上位ビットです。したがって「ビット13」は に相当します。
Q: d に「i==5」では駄目ですか?
A: i++ が行われた直後の判定なので、LED0(i=5)を表示した後にiは6になります。その時点でリセットするのが正しいため、i==5では1つ早く終了してしまいます。
A: i++ が行われた直後の判定なので、LED0(i=5)を表示した後にiは6になります。その時点でリセットするのが正しいため、i==5では1つ早く終了してしまいます。
関連キーワード: ダイナミック点灯, 7セグメント, 割込みハンドラ, ビット演算, オフバイワン
設問3:
問題文を見る図5中の①の処理で、SWの状態を直ちに反映しない理由を、30字以内で述べよ。
模範解答
「スイッチオン・オフ時は不安定な状態になるので」
または
「SWの状態が不安定なので」
または
「チャタリングによって、状態が不安定なので」
解説
解答の論理構成
- SWの接続
問題文では「PIO_Dのに割り当てられた端子には、SWが接続される。SWを押している間はオンとなり、そのときPIO_Dを読み込むとそのビットは1、SWがオフのときそのビットは0となる。」とあり、機械式SWが直接PIOに入力されます。 - ①の処理の目的
さらに「図5中の①の処理は、SWの状態が変化したときに、状態が安定するまで待ち合わせる処理である。」と明示されています。 - 機械式SWの物理的特性
機械接点はオン・オフの瞬間に複数回の接点振動(チャタリング)が発生し、短時間で0/1が高速に入れ替わります。 - 直ちに反映するとどうなるか
チャタリング期間中に読み取った値をそのまま表示切替に用いると、表示が点滅したり誤動作します。 - そこでカウンタcntによる待ち時間を設け、連続して同じ値が得られるまでSWの状態を確定させています。
- 以上より、①で「SWの状態を直ちに反映しない理由」は「チャタリングによる不安定を避けるため」であると論理的に導けます。
誤りやすいポイント
- 「CPU負荷を下げるための遅延」と誤解し、物理的ノイズ対策であることを見落とす。
- cntが単なるタイマの例外処理と考え、チャタリング抑止の“連続同値判定”である点を説明に盛り込めない。
- SWの状態が不安定になるのは押下時だけと思い込み、離す瞬間のチャタリングを忘れる。
FAQ
Q: cnt = 10はどの程度の時間を想定していますか?
A: クロックカウンタ割込みは「1ミリ秒ごと」と明示されているので、cntが10だと約10msのデバウンス時間になります。
A: クロックカウンタ割込みは「1ミリ秒ごと」と明示されているので、cntが10だと約10msのデバウンス時間になります。
Q: ソフトウェアでなくハードウェアでチャタリング対策をしても良いのですか?
A: はい。RCフィルタやシュミットトリガ入力で行う方法もありますが、本設計では汎用PIOを使うためソフトウェアで処理しています。
A: はい。RCフィルタやシュミットトリガ入力で行う方法もありますが、本設計では汎用PIOを使うためソフトウェアで処理しています。
Q: prevとswStateの2種類を用意しているのはなぜですか?
A: prevは「直前に読み取った生値」、swStateは「デバウンス後に確定した論理状態」を保持し、両者を分離することでチャタリング判定ロジックを簡潔にしています。
A: prevは「直前に読み取った生値」、swStateは「デバウンス後に確定した論理状態」を保持し、両者を分離することでチャタリング判定ロジックを簡潔にしています。
関連キーワード: チャタリング, デバウンス, 機械式スイッチ, 割込みハンドラ, PIO




