Использование прерываний для обработки нажатий матричной клавиатуры
- Войдите на сайт для отправки комментариев
Пт, 06/05/2022 - 12:12
Пример для клавиатуры 4 столбца, 5 строк.
На столбцах высокий уровень, на строках - низкий.
К пинам, на которые подключены столбцы, приаттачены прерывания по спаду. При нажатии на кнопку столбец замыкается со строкой и на столбце уровень меняется на низкий - срабатывает прерывание.
В прерывании запоминается номер столбца и после вызывается процедура определения строки. В этой процедуре на строках последовательно устанавливается высокий уровень и проверяется уровень на выбранном столбце. Если он стал высокий - то значит строка найдена. Возвращаем уровни в исходное состояние и ждем следующего нажатия на кнопку.
#include <UTFT.h> UTFT myGLCD(CTE32HR, 38, 39, 40, 41); // инициализация TFT (старого) int TFTW = 480, TFTH = 320; // разрешение экранчика (старого) #define clrp VGA_FUCHSIA #define SerialUSB Serial #define digitalread digitalRead int i,j,k; extern uint8_t BigFont[]; #define RGB24TOLCD(val) (((val & 0x00f80000) >> 8 ) | ((val & 0x0000fc00) >> 5) |((val & 0x000000f8) >> 3)) static String btnName; volatile static byte kbcol=0,kbrow=0, irqres=0;//'! col pin 5-8, row pin 9-13 const byte ROWS = 5; //число строк клавиатуры const byte COLS = 4; //число столбцов клавиатуры char* hexaKeys[ROWS][COLS] = {// названия клавиш, как на клавиатуре {"F1","F2","#","*"}, //13 0 {"1","2","3","^"}, //12 1 {"4","5","6","v"}, //11 2 {"7","8","9","Esc"},//10 3 {"<","0",">","Ent"}//9 4 }; byte rowPins[ROWS] = {9, 10, 11, 12, 13}; //к каким пинам подключаем строки byte colPins[COLS] = {5, 6, 7, 8}; //к каким пинам подключаем столбцы //****************** void irqkb5 () {kbcol=5;} void irqkb6 () {kbcol=6;} void irqkb7 () {kbcol=7;} void irqkb8 () {kbcol=8;} //****************** void kbdcheck (byte kbcol) { detachInterrupt(kbcol); // int zzz=LOW; btnName="---"; irqres=0; do //------------------- { zzz=digitalread(kbcol);//' проверяем что на kbcol столбце // с него пришло прерывание - должен быть низкий уровень if (zzz == LOW) //' все норм { break; //'выходим } irqres++; myGLCD.print("84: wrong "+String(kbcol)+"=" + String(irqres), 190, 80); if (irqres >20 ) //' { return ; //если так и не стал низким, то вообще выходим } } while (zzz==HIGH );// если уровень почему-то высокий, читаем еще до 20 раз for (i = 0; i < 5; i++) //перебираем по строкам, последовательно устанавливаем их в высокий и смотрим //стал ли на столбце высокий уровень { //'rowPins[ROWS] = {9, 10, 11, 12, 13}; digitalWrite(rowPins[i], HIGH);pinMode(rowPins[i], INPUT);digitalWrite(rowPins[i], HIGH); //'устанавливаем строку c pin i в высокий zzz=digitalread(kbcol); //' проверяем что стало на kbcol столбце (5 6 7 8) if (zzz == HIGH) //' если он стал высоким, значит нажата кнопка kbcol,rowPins[i] { btnName=hexaKeys[4-i][kbcol-5]; //'! "<-"; kbrow=5-i; //goto kbdcheckExit; //'выходим break; } } //****** kbdcheckExit: myGLCD.print("161:btnName=" + btnName+" ", 20, 30); pinMode(13, OUTPUT); digitalWrite(13, LOW); pinMode(12, OUTPUT); digitalWrite(12, LOW); pinMode(11, OUTPUT); digitalWrite(11, LOW); pinMode(10, OUTPUT); digitalWrite(10, LOW); pinMode(9, OUTPUT); digitalWrite(9, LOW); irqres=0; //detachInterrupt(kbcol); // // 'ждем отпускания кнопки - пропускаеи дребезг do //------------------- { zzz=digitalread(kbcol); irqres=irqres+zzz; delay (1); } while (irqres < 20);// пока не будет 20 раз высокий ------------------- } //******************************************************************************** void setup() { // 'rows pinMode(13, OUTPUT); digitalWrite(13, LOW); pinMode(12, OUTPUT); digitalWrite(12, LOW); pinMode(11, OUTPUT); digitalWrite(11, LOW); pinMode(10, OUTPUT); digitalWrite(10, LOW); pinMode(9, OUTPUT); digitalWrite(9, LOW); //'cols pinMode(5, INPUT); digitalWrite(5, HIGH); pinMode(6, INPUT); digitalWrite(6, HIGH); pinMode(7, INPUT); digitalWrite(7, HIGH); pinMode(8, INPUT); digitalWrite(8, HIGH); attachInterrupt(5, irqkb5, FALLING); // 'setup() attachInterrupt(6, irqkb6, FALLING); //RISING attachInterrupt(7, irqkb7, FALLING); //RISING attachInterrupt(8, irqkb8, FALLING); //RISING myGLCD.InitLCD(3); // Setup the LCD //SerialUSB.begin(115200); // initialize the serial communication: } //*************************************************************** void loop() { myGLCD.setFont(BigFont); myGLCD.setColor(VGA_WHITE); myGLCD.clrScr(); // Clear the screen and draw the frame // Цикл измерения и отрисовки =============================================== while (1) { beginizm: pinMode(13, OUTPUT); digitalWrite(13, LOW); pinMode(12, OUTPUT); digitalWrite(12, LOW); pinMode(11, OUTPUT); digitalWrite(11, LOW); pinMode(10, OUTPUT); digitalWrite(10, LOW); pinMode(9, OUTPUT); digitalWrite(9, LOW); kbcol = 0; do //------------------- { if (kbcol>0 ) { detachInterrupt(5); // detachInterrupt(6); // detachInterrupt(7); // detachInterrupt(8); // break; // } } while (kbcol == 0);//------------------- kbdcheck (kbcol) ; attachInterrupt(5, irqkb5, FALLING); // 'setup() attachInterrupt(6, irqkb6, FALLING); //RISING attachInterrupt(7, irqkb7, FALLING); //RISING attachInterrupt(8, irqkb8, FALLING); //RISING myGLCD.print("252 kbcol=" + String(kbcol), 20, 150); myGLCD.print("252 kbrow=" + String(kbrow), 20, 170); myGLCD.print("255:btnName=" + btnName+" ", 20, 30); // 'delay (10); } //' end while (1) }
Бесполезное усложнение
Мне даже страшно увидеть цифру - длительность нахождения в прерывании ....
Слишком долго в прерывании, да и витиевато как-то.
diakin, ну и наворотили... обращение к дисплею и делеи тоже в прерывании?
Эмм..
ISR - это вот это
а какова была изначальная цель, что требуется связать?
Ну.. не надо в loop опрашивать состояние пинов клавиатуры
Можно прерывать длинные циклы по нажатию кнопки
Что-то типа
Ну да, не совсем точно выразился )
>В прерывании запоминается номер столбца (и больше ничего). После вызывается процедура определения строки.