応用情報技術者 2021年 秋期 午前2 問23
問題文
マイコンの汎用入出力ポートに接続された LED1 を、LED2の状態を変化させずに点灯したい。汎用入出力ポートに書き込む値として、適切なものはどれか。ここで、使用されている汎用入出力ポートのビットは全て出力モードに設定されていて、出力値の読出しが可能で、この操作の間に汎用入出力ポートに対する他の操作は行われないものとする。

選択肢
ア:汎用入出力ポートから読み出した値と16進数の 08 との論理積
イ:汎用入出力ポートから読み出した値と16進数の 08 との論理和(正解)
ウ:汎用入出力ポートから読み出した値と16進数の48との論理積
エ:汎用入出力ポートから読み出した値と16進数の48との論理和
🔒 解説は解答すると表示されます
ビット演算によるピン制御【午前2解説】
正解の理由
LED1 はポートのビット3に接続されており、LED2 はビット6に接続されています。既存の他ビット(特にビット6=LED2)の状態を変えずにLED1を「点灯(ビット3を1に)」したいので、ポートから現在の値を読み出してビット3だけを1にする操作が必要です。ビット3を1にするには論理和(OR)で対応ビットだけを1にすればよく、この操作を表す選択肢が イ です。
具体的には の2進表現は であり、元のポート値 X に対して を行うとビット3が必ず1になり、他のビットは元のまま保持されます。したがってLED1は点灯し、LED2(ビット6)の状態は変化しません。
解法ステップ
- 現在のポート出力値を読み出す(読み出し可能である条件が満たされているため実行可能)。
- 読み出した値に対してビット3だけを1にするマスク を論理和(OR)で合成する:
new = old | 0x08。 - 合成した値をポートに書き込む。これでLED1が点灯し、LED2 のビット6は書き換えられない。
簡単なコード例(イメージ):
uint8_t v = GPIO_PORT; // ポート読み出し
v |= 0x08; // ビット3を1にする
GPIO_PORT = v; // ポートへ書き戻し
選択肢別の誤答解説
-
ア: 汎用入出力ポートから読み出した値と16進数の 08 との論理積
- AND演算(論理積)で と演算すると、ビット3以外は0にされるため、元の他ビットの状態が失われるかもしれません。また、AND はビットを1にすることはできないため、元々ビット3が0ならLED1を点灯できません。よって不適切です。
-
イ: 汎用入出力ポートから読み出した値と16進数の 08 との論理和
- 正答。上記の通り、OR によってビット3だけを確実に1にし、他ビット(ビット6=LED2 を含む)はそのままにできます。
-
ウ: 汎用入出力ポートから読み出した値と16進数の48との論理積
- は (=ビット6とビット3が1)です。AND(論理積)でこれを使うと、ビット6とビット3以外が0になり、元の他ビットの情報が失われます。さらに AND は 0 を 1 に変えることはできないため、元々ビット3が0であればLED1は点灯しません。したがって目的を満たしません。
-
エ: 汎用入出力ポートから読み出した値と16進数の48との論理和
- OR で を使うと、ビット3だけでなくビット6も強制的に1にされます( のため)。元々のLED2(ビット6)の状態が0だった場合にそれを1にしてしまい、LED2 の状態を変えてしまう可能性があるため不適切です。
よくある誤解
- 「AND(論理積)でマスクすれば目的のビットだけ取り出せる」
- AND は取り出し(抽出)には使えるが、0 を 1 にすることはできないため「確実に点灯させる」目的には使えません。点灯(ビットを1にする)には OR を使います。
- 「どのビットがどの値かは16進数の桁で誤解しやすい」
- 16進数のビット対応を正確に把握すること。例: はビット3、 はビット6、 はビット6と3が1です。
補足コラム
この問題は典型的な「リード・モディファイ・ライト(read-modify-write)」のパターンです。割り込みや並行して別のタスクが同じポートを操作する可能性がある環境では、単純な read/modify/write が競合を生み、他のビットが意図せず変わることがあります。そうした場合は排他制御(割り込み禁止やミューテックス)、あるいはハードウェアのビット単位操作レジスタ(ビットセット/ビットクリア機能)を使うと安全です。
また、回路的にLEDが「アクティブロー」になっている(0で点灯)場合は論理が逆転するため、問題文のビットの意味(1が点灯か0が点灯か)を先に確認することが重要です。
FAQ
Q: 読み出さずに単にポートに 0x08 を書けばよくないか?
A: その場合、ポートの他ビットは 0x08 に上書きされ、LED2(ビット6)などの状態が消えてしまいます。既存の状態を保持したいなら読み出してマスク処理する必要があります。
A: その場合、ポートの他ビットは 0x08 に上書きされ、LED2(ビット6)などの状態が消えてしまいます。既存の状態を保持したいなら読み出してマスク処理する必要があります。
Q: AND と OR のどちらが「ビットを切る/立てる」役割か?
A: AND(論理積)は対象ビットを 0 にでき、1 にすることはできない(マスクに 0 を含めればクリアする)。OR(論理和)は対象ビットを 1 にでき、0 にすることはできない(マスクに 1 を含めればセットする)。
A: AND(論理積)は対象ビットを 0 にでき、1 にすることはできない(マスクに 0 を含めればクリアする)。OR(論理和)は対象ビットを 1 にでき、0 にすることはできない(マスクに 1 を含めればセットする)。
Q: の値が以前の解説と違うがどれが正しい?
A: 正しくは です。これによりビット6とビット3が1になります(0x40 がビット6、0x08 がビット3)。
A: 正しくは です。これによりビット6とビット3が1になります(0x40 がビット6、0x08 がビット3)。
関連キーワード: ビット演算、論理和(OR)、論理積(AND)、マスク、リード・モディファイ・ライト、GPIO、LED制御

\ せっかくなら /
応用情報技術者を
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

