Использование прерываний для обработки нажатий матричной клавиатуры
- Войдите на сайт для отправки комментариев
Пт, 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 - это вот это
void irqkb5 () {kbcol=5;}а какова была изначальная цель, что требуется связать?
Ну.. не надо в loop опрашивать состояние пинов клавиатуры
Можно прерывать длинные циклы по нажатию кнопки
Что-то типа
kbd=0; // по прерыванию kbd=1 For (i=0; i<100500;i++) { if kbd>0 {break;} AnalogVal0[i] = analogRead(A0); }Ну да, не совсем точно выразился )
>В прерывании запоминается номер столбца (и больше ничего). После вызывается процедура определения строки.