pp.419-420
同じことを今度はCで記述する。
- サンプルファイル:
/* 下のように接続する。 ROW0 → PD7 ROW1 → PD6 ROW2 → PD5 ROW3 → PD4 COL3 → PD3 COL2 → PD2 COL1 → PD1 COL0 → PD0 */ #define F_CPU 8000000UL #include <avr/io.h> #include "MatKeyClass.h" const uint8_t KEYS[4][4] = {{ 0, 1, 2, 3}, { 4, 5, 6, 7}, { 8, 9,10,11}, {12,13,14,15}}; int main(){ DDRB = 0xFF; MatKeyClass keypad; keypad.init(); while(1){ keypad.detectKey(); PORTB = KEYS[keypad.getRow()][keypad.getCol()]; } return 0; }
- ライブラリーのヘッダーファイル:
/* 下のように接続する。 ROW0 → PD7 ROW1 → PD6 ROW2 → PD5 ROW3 → PD4 COL3 → PD3 COL2 → PD2 COL1 → PD1 COL0 → PD0 */ #ifndef MATKEYCLASS_H_ #define MATKEYCLASS_H_ #define F_CPU 8000000UL #include <avr/io.h> #include <util/delay.h> class MatKeyClass{ private: uint8_t row, col; void waitForRelease(); void waitForPress(); void searchRow(); public: void init(); void detectKey(); uint8_t getRow(); uint8_t getCol(); MatKeyClass(); }; #endif
- ライブラリーの実装:
#include "MatKeyClass.h" void MatKeyClass::init(){ DDRD = 0xF0; // ポートDの上位ニブルを行(OUT)に、下位ニブルを列(IN)に接続する。 } void MatKeyClass::waitForRelease(){ PORTD = 0x0F; // すべての行をLにして、 asm("NOP"); while((PIND & 0x0F) != 0x0F); // すべてのキーから指が離れるまで(すべての列がHになるまで)とどまる。 } void MatKeyClass::waitForPress(){ while((PIND & 0x0F) == 0x0F); // どれかキーが押されるまで(どれか列がLになるまで)とどまって、 _delay_ms(20); // どれかキーが押されたらバウンスの収まるのを待って、 for(uint8_t i=0; i<4; i++){ if((~(PIND & 0x0F) & 0x0F) == 1 << i){ // やはり押されていたら、 col = i; // 列番号を取得して、 break; // 抜ける。 } } } void MatKeyClass::searchRow(){ for(uint8_t i=0; i<4; i++){ PORTD = ~(1 << (7 - i)); // 0行目から1行ずつ順番にLにして、 asm("NOP"); if((PIND & 0x0F) != 0x0F){ // どれかキーの押下が見つかったら、 row = i; // 行番号を取得して、 break; // 抜ける。 } } } void MatKeyClass::detectKey(){ waitForRelease(); waitForPress(); searchRow(); } uint8_t MatKeyClass::getRow(){ return row; } uint8_t MatKeyClass::getCol(){ return col; } MatKeyClass::MatKeyClass(){}