Использование прерываний для обработки нажатий матричной клавиатуры

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

Пример для клавиатуры 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)
}

 

 

rkit
Offline
Зарегистрирован: 23.11.2016

Бесполезное усложнение

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Мне даже страшно увидеть цифру - длительность нахождения в прерывании ....

-NMi-
Offline
Зарегистрирован: 20.08.2018

Слишком долго в прерывании, да и витиевато как-то.

b707
Offline
Зарегистрирован: 26.05.2017

diakin, ну и наворотили... обращение к дисплею и делеи тоже в прерывании?

 

 

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

Эмм..
ISR - это вот это

void irqkb5 () {kbcol=5;}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

а какова была изначальная цель, что требуется связать?

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

Ну.. не надо в loop опрашивать состояние пинов клавиатуры
Можно прерывать длинные циклы по нажатию кнопки
Что-то типа

kbd=0; // по прерыванию kbd=1
For (i=0; i<100500;i++)
{
if kbd>0 {break;}
AnalogVal0[i] = analogRead(A0);
}

 

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

Ну да, не совсем точно выразился )
>В прерывании запоминается номер столбца (и больше ничего).  После вызывается процедура определения строки.