ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
29 ноября
850871 Топик полностью
Petrovich (25.06.2018 15:47, просмотров: 1) ответил Make_Pic на Гуру - Подскажите pls чайнику (чтобы сильно не пинали меня здесь :) красивый компактный код опроса клавиатурной матрицы 4Х4 кнопок с защитой от дребезга на С (БЕЗ С++)?
Че, правда надо необычное? Вот выдрал, надеюсь, не убил идею и красоту  // Коды клавиш: 4x4=16 кодов одиночных нажатий. // При необходимости добавлять коды (до 4-х нажатий на каждую // scanLine), изменяя мл.тетраду кода клавиши. // Длительность дешифрации клавиш при этом не изменится. #define NO_PRESS ( 0xff ) #define KEY_1 ( 0xee ) /*тетрады: H-scan, L-ret*/ #define KEY_2 ( 0xed ) #define KEY_3 ( 0xeb ) #define KEY_4 ( 0xe7 ) #define KEY_5 ( 0xde ) #define KEY_6 ( 0xdd ) #define KEY_7 ( 0xdb ) #define KEY_8 ( 0xd7 ) #define KEY_9 ( 0xce ) #define KEY_10 ( 0xcd ) #define KEY_11 ( 0xcb ) #define KEY_12 ( 0xc7 ) #define KEY_13 ( 0xbe ) #define KEY_14 ( 0xbd ) #define KEY_15 ( 0xbb ) #define KEY_16 ( 0xb7 ) //----------------------------------- volatile uint8_t keyData = NO_PRESS; // keyData содержит текущий код //----------------------------------- // Обработчик прерывания таймера, например, каждые 5 мс, для опроса матрицы // Может вызываться и поллингом void keyHandler( void ) { static uint16_t stateMsk = (uint16_t)0xffffU; // Маска состояний, где 0 - нажатие static uint16_t changeFlagsMsk; // Изменения состояний static uint16_t cnt0, cnt1; uint16_t sampleMsk; // Конкатенация 4-х RET-тетрад uint16_t deltaMsk; // Побитовая разница с сэмплов uint8_t retMsk; // Сканирование матрицы активным 0 и формирование // 16-битного значения sampleMsk scanLine1(); // Активировать 0 на первой линии сканирования nopNopNop(); // Пауза retMsk=readRetLines(); // Чтение байта, где мл.тетр.-RET-линии scanLine2(); sampleMsk = (uint16_t)(retMsk & 0x0f); retMsk=readRetLines(); scanLine3(); sampleMsk < < = 4; // Сдвиг влево на 4 бита sampleMsk |= (uint16_t)(retMsk & 0x0f); retMsk=readRetLines(); scanLine4(); sampleMsk < < = 4; // Сдвиг влево на 4 бита sampleMsk |= (uint16_t)(retMsk & 0x0f); retMsk=readRetLines(); scanLineOff(); // Все 8 линий матрицы как pullup-входы. sampleMsk < < = 4; // Сдвиг влево на 4 бита sampleMsk |= (uint16_t)(retMsk & 0x0f); // Антидребезг 4-х проходный. deltaMsk = (sampleMsk ^ stateMsk); cnt1 = ((cnt1 ^ cnt0) & deltaMsk); cnt0 = ((~cnt0) & deltaMsk); changeFlagsMsk = (deltaMsk & (~(cnt0 | cnt1))); stateMsk ^= changeFlagsMsk; // Проверка изменения состояний клавиш if( !changeFlagsMsk ) { if( keyData != NO_PRESS ) { // Здесь возможен счетчик и обработка долгих нажатий, // например, для выключения или рестарта прибора долгим // нажатием клавиши (сочетания клавиш) //..... }else{ // Здесь возможен счетчик и обработка долгого // ненажатия клавиш, например, для самоотключения // батарейного прибора //..... } }else { // Было изменение! uint8_t u8_tmp; uint16_t tmpStateMsk; // Декодирование клавиш keyData = NO_PRESS; tmpStateMsk = stateMsk; u8_tmp = (uint8_t)(tmpStateMsk & 0x0f); if( u8_tmp != 0x0f ) { keyData=(0xe0 | u8_tmp); } tmpStateMsk > > = 4; // Сдвиг вправо на 4 бита u8_tmp = (uint8_t)(tmpStateMsk & 0x0f); if( u8_tmp != 0x0f ) { keyData=(0xd0 | u8_tmp ); } tmpStateMsk > > = 4; // Сдвиг вправо на 4 бита u8_tmp = (uint8_t)(tmpStateMsk & 0x0f); if( u8_tmp != 0x0f ) { keyData = ( 0xc0 | u8_tmp ); } tmpStateMsk > > = 4; // Сдвиг вправо на 4 бита u8_tmp = (uint8_t)(tmpStateMsk & 0x0f); if( u8_tmp != 0x0f ) { keyData = ( 0xb0 | u8_tmp ); } } } void getKey(void) { do{ /*keyHandler()*/ ; }while(keyData != NO_PRESS); do{ /*keyHandler()*/ ; }while(keyData == NO_PRESS); shortBell(); } void main(void){ scanLineOff(); keyData=NO_PRESS; setTimerMs(5); enable_interrupt(); while(1){ getKey(); //printf } }