回答例
演習1
micro:bitの LEDの回路図 を見るとわかるように、ROW1,ROW2およびCOL1,COL4を動作させると、それらの信号線の交点に配置されたLED4個がすべて点灯してしまうため。
課題2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
#include "nrf.h" //LED状態を制御するための変数 int status = 0; extern "C" void TIMER2_IRQHandler(void) { NRF_TIMER2->EVENTS_COMPARE[0] = 0; // 割り込みイベントクリア if(status==0){ //左上のLEDオン digitalWrite(26, HIGH); digitalWrite(3, LOW); //2番目のLEDオフ digitalWrite(27, LOW); digitalWrite(23, HIGH); }else{ //左上のLEDオフ digitalWrite(26, LOW); digitalWrite(3, HIGH); //2番目のLEDオン digitalWrite(27, HIGH); digitalWrite(23, LOW); } status =! status; } void setup() { //左上のLEDを初期化 pinMode(26, OUTPUT); //ROW1 pinMode(3, OUTPUT); //COL1 //2番目のLED pinMode(27, OUTPUT); //ROW2 pinMode(23, OUTPUT); //COL4 //タイマ設定 NRF_TIMER2->TASKS_STOP = 1; // タイマストップ NRF_TIMER2->TASKS_CLEAR = 1; // カウンタクリア NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // モード設定:タイマモード NRF_TIMER2->PRESCALER = 8; // プリスケーラ設定:256分周(62.5kHz) NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit; // カウンタ長設定:16ビット長指定 NRF_TIMER2->CC[0] = 62500/2; // コンパレータ0の設定:0.5秒周期 NRF_TIMER2->INTENSET = // 割り込み設定:コンパレータ0と比較 (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos); NRF_TIMER2->SHORTS = // ショートカット設定:クリアタスク指定 (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos); // タイマ割り込み設定 NVIC_SetPriority(TIMER2_IRQn, 3); // 割り込み優先度設定 NVIC_ClearPendingIRQ(TIMER2_IRQn); // 保留割り込みクリア NVIC_EnableIRQ(TIMER2_IRQn); // 割り込み許可 NRF_TIMER2->TASKS_START = 1; // タイマスタート } void loop(){ } |
課題3
NRF_TIMER2->CC[0] = 62500/100; と変更するとタイマー割り込みが100分の1秒(10ms)毎に発生するようになる。目の残像減少によって、交互に点滅している2個のLEDが常に点灯しているように見える。
課題4
LED[5][5] の配列をメインプログラムで操作、それを割り込み関数の中で参照してLEDをオン/オフするサンプルプログラム。ROWLIST[][][] という3次元配列にLEDアレイの電気回路とLEDの物理的位置を保持しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
#include "nrf.h" // ROW,COLそれぞれGPIO番号を定義する #define ROW1 26 #define ROW2 27 #define ROW3 28 #define COL1 3 #define COL2 4 #define COL3 10 #define COL4 23 #define COL5 24 #define COL6 25 #define COL7 9 #define COL8 7 #define COL9 6 // ROW,COLのGPIO番号を配列に持つ signed char ROW[3] = {ROW1, ROW2, ROW3}; signed char COL[9] = {COL1, COL2, COL3, COL4, COL5, COL6, COL7, COL8, COL9 }; // ROW1/2/3それぞれに接続されるLEDの、y座標、x座標。"-1"の場所は無視。 signed char ROWLIST[3][9][2] = { { {0,0}, {0,2}, {0,4}, {3,4}, {3,3}, {3,2}, {3,1}, {3,0}, {2,1} }, { {2,4}, {2,0}, {2,2}, {0,1}, {0,3}, {4,3}, {4,1}, {-1,-1}, {-1,-1} }, { {4,2}, {4,4}, {4,0}, {1,0}, {1,1}, {1,2}, {1,3}, {1,4}, {2,3} } }; // 5x5のLEDアレイの、オン/オフ状態を示す配列 signed char LED[5][5]; // 制御するROWの番号 int row = 0; extern "C" void TIMER2_IRQHandler(void) { NRF_TIMER2->EVENTS_COMPARE[0] = 0; // 割り込みイベントクリア // 前回のROWをオフする digitalWrite(ROW[row], LOW); // COLも全部オフする for (int col=0; col<9; col++) { digitalWrite(COL[col], HIGH); } // 次のROWをオンする row++; if (row==3) row=0; digitalWrite(ROW[row], HIGH); for (int col=0; col<9; col++) { if (ROWLIST[row][col][0] == -1) continue; int y = ROWLIST[row][col][0]; int x = ROWLIST[row][col][1]; if (LED[y][x]) { digitalWrite(COL[col], LOW); } } } void setup() { Serial.begin(115200); while (!Serial); // 全てのピンを初期化 for (int i=0; i<3; i++) { pinMode(ROW[i], OUTPUT); digitalWrite(ROW[i], LOW); } for (int i=0; i<9; i++) { pinMode(COL[i], OUTPUT); digitalWrite(COL[i], HIGH); } // LED全てオフ状態とする for(int y=0; y<5; y++){ for(int x=0; x<5; x++){ LED[y][x] = 0; } } //タイマ設定 NRF_TIMER2->TASKS_STOP = 1; // タイマストップ NRF_TIMER2->TASKS_CLEAR = 1; // カウンタクリア NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // モード設定:タイマモード NRF_TIMER2->PRESCALER = 8; // プリスケーラ設定:256分周(62.5kHz) NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit; // カウンタ長設定:16ビット長指定 NRF_TIMER2->CC[0] = 62500/150; // コンパレータ0の設定:0.5秒周期 NRF_TIMER2->INTENSET = // 割り込み設定:コンパレータ0と比較 (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos); NRF_TIMER2->SHORTS = // ショートカット設定:クリアタスク指定 (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos); // タイマ割り込み設定 NVIC_SetPriority(TIMER2_IRQn, 3); // 割り込み優先度設定 NVIC_ClearPendingIRQ(TIMER2_IRQn); // 保留割り込みクリア NVIC_EnableIRQ(TIMER2_IRQn); // 割り込み許可 NRF_TIMER2->TASKS_START = 1; // タイマスタート } // 表示するデータの定義 char ICONS[4][5][5] = { {{1,1,1,1,1}, {1,1,1,1,1}, {1,1,1,1,1}, {1,1,1,1,1}, {1,1,1,1,1}}, {{0,1,0,1,0}, {1,0,1,0,1}, {1,0,0,0,1}, {0,1,0,1,0}, {0,0,1,0,0}}, {{1,0,0,0,1}, {0,1,0,1,0}, {0,0,1,0,0}, {0,1,0,1,0}, {1,0,0,0,1}}, {{0,0,0,0,0}, {0,1,0,1,0}, {0,0,0,0,0}, {1,0,0,0,1}, {0,1,1,1,0}}}; void loop(){ // LED全てオフ状態とする for(int y=0; y<5; y++){ for(int x=0; x<5; x++){ LED[y][x] = 0; } } for(int y=0; y<5; y++){ for(int x=0; x<5; x++){ LED[y][x] = 1; delay(50); LED[y][x] = 0; } } for(int i=0; i<4; i++){ for(int y=0; y<5; y++){ for(int x=0; x<5; x++){ LED[y][x] = ICONS[i][y][x]; } } delay(1000); } } |
全く同じ動作をする別の回答例です。LEDARRAY[][][] という3次元配列にLEDアレイの各LEDの接続されるROW・COLの番号を保持しています。上の回答例と比べると、少し無駄な処理が増えますがプログラムはこちらの方が理解しやすいかもしれません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
#include "nrf.h" // ROW,COLそれぞれGPIO番号を定義する #define ROW1 26 #define ROW2 27 #define ROW3 28 #define COL1 3 #define COL2 4 #define COL3 10 #define COL4 23 #define COL5 24 #define COL6 25 #define COL7 9 #define COL8 7 #define COL9 6 // ROW,COLのGPIO番号を配列に持つ signed char ROW[3] = {ROW1, ROW2, ROW3}; signed char COL[9] = {COL1, COL2, COL3, COL4, COL5, COL6, COL7, COL8, COL9 }; // 5x5のLEDアレイに対応してGPIO番号を配列で持つ char LEDARRAY[5][5][2] = { { {ROW1, COL1}, {ROW2, COL4}, {ROW1, COL2}, {ROW2, COL5}, {ROW1, COL3} }, { {ROW3, COL4}, {ROW3, COL5}, {ROW3, COL6}, {ROW3, COL7}, {ROW3, COL8} }, { {ROW2, COL2}, {ROW1, COL9}, {ROW2, COL3}, {ROW3, COL9}, {ROW2, COL1} }, { {ROW1, COL8}, {ROW1, COL7}, {ROW1, COL6}, {ROW1, COL5}, {ROW1, COL4} }, { {ROW3, COL3}, {ROW2, COL7}, {ROW3, COL1}, {ROW2, COL6}, {ROW3, COL2} } }; // 5x5のLEDアレイの、オン/オフ状態を示す配列 signed char LED[5][5]; // 制御するROWの番号 int row = 0; extern "C" void TIMER2_IRQHandler(void) { NRF_TIMER2->EVENTS_COMPARE[0] = 0; // 割り込みイベントクリア // 前回のROWをオフする digitalWrite(ROW[row], LOW); // COLも全部オフする for (int col=0; col<9; col++) { digitalWrite(COL[col], HIGH); } // 次のROWをオンする row++; if (row==3) row=0; digitalWrite(ROW[row], HIGH); for (int y=0; y<5; y++) { for (int x=0; x<5; x++) { if (LED[y][x]==1 && LEDARRAY[y][x][0] == ROW[row]) { digitalWrite(LEDARRAY[y][x][1], LOW); } } } } void setup() { Serial.begin(115200); while (!Serial); // 全てのピンを初期化 for (int i=0; i<3; i++) { pinMode(ROW[i], OUTPUT); digitalWrite(ROW[i], LOW); } for (int i=0; i<9; i++) { pinMode(COL[i], OUTPUT); digitalWrite(COL[i], HIGH); } // LED全てオフ状態とする for(int y=0; y<5; y++){ for(int x=0; x<5; x++){ LED[y][x] = 0; } } //タイマ設定 NRF_TIMER2->TASKS_STOP = 1; // タイマストップ NRF_TIMER2->TASKS_CLEAR = 1; // カウンタクリア NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // モード設定:タイマモード NRF_TIMER2->PRESCALER = 8; // プリスケーラ設定:256分周(62.5kHz) NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit; // カウンタ長設定:16ビット長指定 NRF_TIMER2->CC[0] = 62500/150; // コンパレータ0の設定:0.5秒周期 NRF_TIMER2->INTENSET = // 割り込み設定:コンパレータ0と比較 (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos); NRF_TIMER2->SHORTS = // ショートカット設定:クリアタスク指定 (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos); // タイマ割り込み設定 NVIC_SetPriority(TIMER2_IRQn, 3); // 割り込み優先度設定 NVIC_ClearPendingIRQ(TIMER2_IRQn); // 保留割り込みクリア NVIC_EnableIRQ(TIMER2_IRQn); // 割り込み許可 NRF_TIMER2->TASKS_START = 1; // タイマスタート } // 表示するデータの定義 char ICONS[4][5][5] = { {{1,1,1,1,1}, {1,1,1,1,1}, {1,1,1,1,1}, {1,1,1,1,1}, {1,1,1,1,1}}, {{0,1,0,1,0}, {1,0,1,0,1}, {1,0,0,0,1}, {0,1,0,1,0}, {0,0,1,0,0}}, {{1,0,0,0,1}, {0,1,0,1,0}, {0,0,1,0,0}, {0,1,0,1,0}, {1,0,0,0,1}}, {{0,0,0,0,0}, {0,1,0,1,0}, {0,0,0,0,0}, {1,0,0,0,1}, {0,1,1,1,0}}}; void loop(){ // LED全てオフ状態とする for(int y=0; y<5; y++){ for(int x=0; x<5; x++){ LED[y][x] = 0; } } for(int y=0; y<5; y++){ for(int x=0; x<5; x++){ LED[y][x] = 1; delay(50); LED[y][x] = 0; } } for(int i=0; i<4; i++){ for(int y=0; y<5; y++){ for(int x=0; x<5; x++){ LED[y][x] = ICONS[i][y][x]; } } delay(1000); } } |
課題5
回答省略
コメント