pp.614ff.
前回はヒステリシス特性を持たせてディバウンスしたが、ディバウンス回数そのものも0~7回の範囲で設定できる。
#define F_CPU 8000000UL #include <avr/io.h> #include <avr/interrupt.h> #include "USARTClass.h" #include "MPR121Class.h" MPR121Class pad(0x5A); // (I2Cスレーブアドレス)で実体化する。 ISR(INT1_vect){ usart.printString("touch status (bit[3:0]): "); usart.printBinaryNibble(pad.get_touch_status() & 0xF); usart.printString("\n"); usart.printString("filtered data : "); for(int i=0; i<4; i++){ usart.printNibble(i); usart.printString("ch:"); usart.printByte(pad.get_filtered_data(i)); usart.printString(", "); } usart.printString("\n"); usart.printString("baseline val : "); for(int i=0; i<4; i++){ usart.printNibble(i); usart.printString("ch:"); usart.printByte(pad.get_baseline_val(i)); usart.printString(", "); } usart.printString("\n"); usart.printString("touch threshold : "); for(int i=0; i<4; i++){ usart.printNibble(i); usart.printString("ch:"); usart.printByte(pad.get_touch_threshold(i)); usart.printString(", "); } usart.printString("\n"); usart.printString("release threshold: "); for(int i=0; i<4; i++){ usart.printNibble(i); usart.printString("ch:"); usart.printByte(pad.get_release_threshold(i)); usart.printString(", "); } usart.printString("\n"); usart.printString("touch debounce#: "); usart.printByte(pad.get_touch_debounce_num()); usart.printString("\n"); usart.printString("release debounce#: "); usart.printByte(pad.get_release_debounce_num()); usart.printString("\n\n"); } int main(){ usart.init(); EIMSK |= (1 << INT1); // INT1 (外部割り込み要求1)を有効化する。 EICRA |= (1 << ISC11); // falling edgeで割り込む。 sei(); pad.soft_reset(); // ソフトリセットをかける。 pad.enable_touch(4); // (n)本の電極をタッチセンサーにする。 for(int i=0; i<4; i++){pad.set_touch_threshold(i, 0x10);} // ch0~3にタッチ閾値をセットする。 pad.set_touch_debounce_num(7); // タッチ時のディバウンス回数(0~7)をセットする。全チャンネル共通。 pad.set_release_debounce_num(3); // リリース時のディバウンス回数(0~7)をセットする。全チャンネル共通。 while(1); return 0; }
#ifndef MPR121CLASS_H_ #define MPR121CLASS_H_ #include <avr/io.h> #include "I2CClass.h" // register addresses and others const uint8_t ECR = 0x5E; const uint8_t SOFT_RESET = 0x80; const uint8_t SOFT_RESET_VAl = 0x63; const uint8_t FILTERED_DATA = 0x04; const uint8_t BASELINE_VALUE = 0x1E; const uint8_t TOUCH_THRESHOLD = 0x41; const uint8_t RELEASE_THRESHOLD = 0x42; const uint8_t DEBOUNCE = 0x5B; class MPR121Class{ private: uint8_t _SLA; // スレーブアドレス。 uint8_t get_ECR(); // ECRを読み出す。 public: void soft_reset(); // ソフトリセットをかける。 uint16_t get_touch_status(); // 12本ぶん(12ビット)のタッチ状態を取得する。 void enable_touch(uint8_t ele_n); // (n)本の電極をタッチセンサーにする。0~12本。 void enable_prox(uint8_t ele_n); // (n)本の電極を近接センサーにする。0,2,4,12本。 void enter_stop_mode(); // STOPモードに移行する。 uint16_t get_filtered_data(uint8_t ch); // (チャンネル)ごとのフィルター処理後データ(10ビット)を取得する。 uint16_t get_baseline_val(uint8_t ch); // (チャンネル)ごとのベースライン値(10ビット、下2ビットは無効)を取得する。 uint8_t get_touch_threshold(uint8_t ch); // (チャンネル)ごとのタッチ閾値を取得する。 void set_touch_threshold(uint8_t ch, uint8_t val); // (チャンネル)ごとのタッチ閾値をセットする。 uint8_t get_release_threshold(uint8_t ch); // (チャンネル)ごとのリリース閾値を取得する。 void set_release_threshold(uint8_t ch, uint8_t val); // (チャンネル)ごとのリリース閾値をセットする。 uint8_t get_touch_debounce_num(); // タッチディバウンス回数を取得する。全チャンネル共通。 uint8_t get_release_debounce_num(); // リリースディバウンス回数を取得する。全チャンネル共通。 void set_touch_debounce_num(uint8_t num); // タッチディバウンス回数(0~7)をセットする。全チャンネル共通。 void set_release_debounce_num(uint8_t num); // リリースディバウンス回数(0~7)をセットする。全チャンネル共通。 // コンストラクタ MPR121Class(uint8_t slave_addr); }; #endif
#include "MPR121Class.h" void MPR121Class::soft_reset(){ i2c.write(_SLA, SOFT_RESET, SOFT_RESET_VAl); // (どのスレーブの, どのレジスタに, 1バイトを)書き込む。 } uint16_t MPR121Class::get_touch_status(){ uint8_t buff[2]; i2c.read(_SLA, 0x00, 2, buff); // (どのスレーブの, どのレジスタから, nバイトを, どのバッファに)読み出す。 return ((uint16_t)(buff[1] & 0x0F) << 8) | buff[0]; // 上位4ビット + 下位8ビットに並べ換えて返す。 } uint8_t MPR121Class::get_ECR(){ return i2c.read(_SLA, ECR); // (どのスレーブの, どのレジスタから) 1バイトを読み出す。 } void MPR121Class::enable_touch(uint8_t ele_n){ uint8_t sute = (get_ECR() & 0xF0) | ele_n; // ECRを読み出して下4ビットを消してそこだけ書き換える。 i2c.write(_SLA, ECR, sute); // (どのスレーブの, どのレジスタに, 1バイトを)書き込む。 } void MPR121Class::enable_prox(uint8_t ele_en){ uint8_t n; switch(ele_en){ case 0: n = 0; break; case 2: n = 1; break; case 4: n = 2; break; case 12: n = 3; break; default: n = 3; break; } uint8_t sute = (get_ECR() & ~(0b11 << 4)) | (n << 4); i2c.write(_SLA, ECR, sute); } void MPR121Class::enter_stop_mode(){ enable_touch(0); enable_prox(0); } uint16_t MPR121Class::get_filtered_data(uint8_t ch){ uint8_t buff[2]; i2c.read(_SLA, FILTERED_DATA + 2 * ch, 2, buff); return ((uint16_t)(buff[1] & 0b11) << 8) | buff[0]; // 上位2ビット + 下位8ビットに並べ換えて返す。 } uint16_t MPR121Class::get_baseline_val(uint8_t ch){ return (uint16_t)i2c.read(_SLA, BASELINE_VALUE + ch) << 2; // 電極データと比較しやすいよう10ビットにして返す。 } uint8_t MPR121Class::get_touch_threshold(uint8_t ch){ return i2c.read(_SLA, TOUCH_THRESHOLD + 2 * ch); } void MPR121Class::set_touch_threshold(uint8_t ch, uint8_t val){ uint8_t ecr = get_ECR(); // ECRの内容を取っておいて、 enter_stop_mode(); // STOPモードにして、 i2c.write(_SLA, TOUCH_THRESHOLD + 2 * ch, val); // タッチ閾値を書き換えて、 i2c.write(_SLA, ECR, ecr); // ECRを書き戻してRUNモードに戻す。 } uint8_t MPR121Class::get_release_threshold(uint8_t ch){ return i2c.read(_SLA, RELEASE_THRESHOLD + 2 * ch); } void MPR121Class::set_release_threshold(uint8_t ch, uint8_t val){ uint8_t ecr = get_ECR(); // ECRの内容を取っておいて、 enter_stop_mode(); // STOPモードにして、 i2c.write(_SLA, RELEASE_THRESHOLD + 2 * ch, val); // リリース閾値を書き換えて、 i2c.write(_SLA, ECR, ecr); // ECRを書き戻してRUNモードに戻す。 } uint8_t MPR121Class::get_touch_debounce_num(){ return i2c.read(_SLA, DEBOUNCE) & 0b111; } uint8_t MPR121Class::get_release_debounce_num(){ return (i2c.read(_SLA, DEBOUNCE) >> 4) & 0b111; } void MPR121Class::set_touch_debounce_num(uint8_t num){ uint8_t ecr = get_ECR(); // ECRの内容を取っておいて、 enter_stop_mode(); // STOPモードにして、 uint8_t dt = (i2c.read(_SLA, DEBOUNCE) & ~0b111) | num; // ディバウンスレジスタの下3ビットだけを i2c.write(_SLA, DEBOUNCE, dt); // 書き換えて、 i2c.write(_SLA, ECR, ecr); // ECRを書き戻してRUNモードに戻す。 } void MPR121Class::set_release_debounce_num(uint8_t num){ uint8_t ecr = get_ECR(); // ECRの内容を取っておいて、 enter_stop_mode(); // STOPモードにして、 uint8_t dr = (i2c.read(_SLA, DEBOUNCE) & ~(0b111 << 4)) | (num <<4); // ディバウンスレジスタのビット[6:4]だけを i2c.write(_SLA, DEBOUNCE, dr); // 書き換えて、 i2c.write(_SLA, ECR, ecr); // ECRを書き戻してRUNモードに戻す。 } MPR121Class::MPR121Class(uint8_t slave_addr){ _SLA = slave_addr; i2c.init(); }