応用情報技術者 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を割り当てる。具体的には、をLED0のセグメントaに、をbに、…、をgに割り当てる。
(2) PIO_Dの上位8ビット〜のうち、〜にはLED0〜LED5を割り当て、にはSWを割り当てる(は使用しない)。具体的には、をLED5に、をLED4に、…、をLED0に割り当てる。
(3) LEDを点灯するためには、点灯するセグメントに対応するビット〜に1を書き込み、点灯するLEDに対応するビット〜に1を書き込む。例えば、表示する時分のうち、“4”の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
設問2:図5中のa〜dについて、(1)、(2)に答えよ。
(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:図5中のa〜dについて、(1)、(2)に答えよ。
(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


