07.09.2017, 22:31
|
#121
|
Прописка
Регистрация: 02.03.2010
Сообщений: 139
Сказал спасибо: 12
Сказали Спасибо 49 раз(а) в 26 сообщении(ях)
|
Re: Оцените алгоритм опроса матричной клавы
Всегда из входов можно сделать выходы и наоборот и считать нажатыми кнопки после двойной проверки. Я правда не знаю, зачем это. Проще миниклаву подключить готовую.
Если с точки зрения безопасности - игнорировать тройные нажатия и все.
Последний раз редактировалось 6ap6oc; 07.09.2017 в 22:41.
|
|
|
|
07.09.2017, 23:52
|
#122
|
Вид на жительство
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
|
Re: Оцените алгоритм опроса матричной клавы
Сообщение от 6ap6oc
|
Всегда из входов можно сделать выходы и наоборот и считать нажатыми кнопки после двойной проверки. Я правда не знаю, зачем это.
|
Вот именно что незачем, так как в данном случае это не поможет. Игнорировать достаточно больше трёх одновременных, но можно и больше двух или больше одного, смотря какая задача.
А вообще над алгоритмом игнорирования можно подумать... Проверил на стареньком клоподаве nokia - реагирует на одновременное нажатие "123", "456", "147", "753" и т.п. А вот если зажимать "785" или "463" и т.п., то третья цифра игнорируется пока не будет отпущена любая из первых двух. А на новом дешёвом клоподаве alcatel реагирует только на одну кнопку, но на нём так и написано: "onetouch" ))
|
|
|
|
08.09.2017, 16:32
|
#123
|
Прописка
Регистрация: 02.03.2010
Сообщений: 139
Сказал спасибо: 12
Сказали Спасибо 49 раз(а) в 26 сообщении(ях)
|
Re: Оцените алгоритм опроса матричной клавы
Чего так сразу, не поможет? =)
Очень надо будет - поможет , вы можете вообще все выводы кроме одного сделать входами. Но, опять же, вряд ли это кому то нужно.
|
|
|
|
08.09.2017, 16:46
|
#124
|
Вид на жительство
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
|
Re: Оцените алгоритм опроса матричной клавы
6ap6oc, это тоже не поможет определить, даже если очень надо будет - какая именно из четырёх кнопок в "квадрате" не нажата (или нажаты все 4). Если считаете, что поможет - хотелось бы узнать - как?
Нужно или не нужно - это уже другой вопрос (например в нокии сделали блокировку "больше трёх", а в алкателе сделали блокировку "больше одного").
|
|
|
|
19.09.2017, 22:25
|
#125
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Оцените алгоритм опроса матричной клавы
Итак, здравствуйте! Выношу на суд очередную версию. Коротко: сделал как сказали, ставим ряд в 1 - уходим - читаем колонки - уходим - ставим сл. ряд - уходим - читаем колонки и так далее. Пауза между вот этими установками и чтениями - 1 мс. Сделано по счетчику без прерываний. Клава впринципе выполняет все нужные мне ф-ии, а именно: Может вывести код хоть всех нажатых клавиш одновременно. Вобщем фул тач)). Определяет долгое нажатие кнопки, время - 1 секунда. В примере находит одновременное нажатие 1 и *. Ниже помещу код и картинку с алгоритмом, для наглядности. Но мне кажется что эта вся штука, не смотря на то что работает шустро, - не идеальна. Мне все кажется что можно сделать проще, короче, но снова просматривая алгоритм, думаю - да ладно, все норм. Вобщем оцените. Я не программер по образованию, так что можете критиковать. Я люблю адекватную критику.
keyboard.c
Нажмите, чтобы открыть спойлер
Код:
|
#include "keyboard.h"
#include "delay.h"
uint8_t old_key = 0, find_key = 0, find_hold_key = 0;
//uint8_t key = 0, old_key = 0, find_key = 0, find_hold_key = 0;//test
//uint8_t state = 0, count_row = 0;//test
//uint16_t count_scan = 0;//test
uint16_t debounce = 10 * KEY_SCAN_DELAY;
GPIO_TypeDef * row_port[ROWS] = {KEY_ROW1_PORT, KEY_ROW2_PORT, KEY_ROW3_PORT, KEY_ROW4_PORT}; //Запихиваем названия портов рядов в массив
uint8_t row_pin[ROWS] = {KEY_ROW_PIN1, KEY_ROW_PIN2, KEY_ROW_PIN3, KEY_ROW_PIN4}; //Запихиваем номера пинов рядов в массив
GPIO_TypeDef * col_port[COLS] = {KEY_COL1_PORT, KEY_COL2_PORT, KEY_COL3_PORT}; //Запихиваем названия портов колонок в массив
uint8_t col_pin[COLS] = {KEY_COL_PIN1, KEY_COL_PIN2, KEY_COL_PIN3}; //Запихиваем номера пинов колонок в массив
char keytable[][2] = {
{0x11,'1'},
{0x12,'2'},
{0x14,'3'},
{0x21,'4'},
{0x22,'5'},
{0x24,'6'},
{0x41,'7'},
{0x42,'8'},
{0x44,'9'},
{0x81,'*'},
{0x82,'0'},
{0x84,'#'},
{0x91,0xB}// 1,*
};
void keyboard_ini(void){
uint8_t i;
//GPIO
for(i = 0; i ‹ ROWS; i++){
port_cmd(row_port[i]); //Включаем тактирование порта ряда
gpio_setup(row_port[i], row_pin[i], 0x01, 0, 0x01, 0x02); //настройка рядов выходов. Порт, пин, MODER, OTYPER, OSPEEDR, PUPDR
row_port[i]-›BSRRL = (1 ‹‹ row_pin[i]); //устанавливаем на всех строках - 1
}
for(i = 0; i ‹ COLS; i++){
port_cmd(col_port[i]); //Включаем тактирование порта столбца
gpio_setup(col_port[i], col_pin[i], 0x00, 0, 0x01, 0x02); //настройка рядов выходов. Порт, пин, MODER, OTYPER, OSPEEDR, PUPDR
}
//test led
GPIOB-›MODER &= ~(GPIO_MODER_MODER0 ‹‹ (14*2));//PB14 (35)
GPIOB-›MODER |= (1 ‹‹ (14*2));
GPIOB-›OTYPER &= ~((GPIO_OTYPER_OT_0) ‹‹ 14);
GPIOB-›OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 ‹‹ (14*2));
GPIOB-›PUPDR &= ~(GPIO_PUPDR_PUPDR0 ‹‹ (14*2));
GPIOB-›PUPDR |= (0x02 ‹‹ (14*2));
//TIM6
RCC-›APB1ENR |= RCC_APB1ENR_TIM6EN;
TIM6-›PSC |= 8399; //F = 10 kHz; Fmax TIM6 = 84 mHz
TIM6-›ARR = 65535;
TIM6-›EGR |= TIM_EGR_UG;
__NOP();
__NOP();
TIM6-›SR &= ~(TIM_SR_UIF);
}
void port_cmd(GPIO_TypeDef * port){ //функция для включения тактирования портов клавиатуры
if(port == GPIOA){
RCC-›AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
}
if(port == GPIOB){
RCC-›AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
}
if(port == GPIOC){
RCC-›AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
}
if(port == GPIOD){
RCC-›AHB1ENR |= RCC_AHB1ENR_GPIODEN;
}
if(port == GPIOE){
RCC-›AHB1ENR |= RCC_AHB1ENR_GPIOEEN;
}
if(port == GPIOF){
RCC-›AHB1ENR |= RCC_AHB1ENR_GPIOFEN;
}
if(port == GPIOG){
RCC-›AHB1ENR |= RCC_AHB1ENR_GPIOGEN;
}
if(port == GPIOH){
RCC-›AHB1ENR |= RCC_AHB1ENR_GPIOHEN;
}
if(port == GPIOI){
RCC-›AHB1ENR |= RCC_AHB1ENR_GPIOIEN;
}
}
void gpio_setup(GPIO_TypeDef * port, uint8_t pin, uint8_t moder, uint8_t otyper, uint8_t ospeedr, uint8_t pupdr){
port-›MODER &= ~(GPIO_MODER_MODER0 ‹‹ (pin*2));
port-›MODER |= (moder ‹‹ (pin*2));
if(moder & 0x03){ //Если настроено как выход
port-›OTYPER &= ~((GPIO_OTYPER_OT_0) ‹‹ pin);
port-›OTYPER |= (otyper ‹‹ pin);
port-›OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 ‹‹ (pin*2));
port-›OSPEEDR |= (ospeedr ‹‹ (pin*2));
}
port-›PUPDR &= ~(GPIO_PUPDR_PUPDR0 ‹‹ (pin*2));
port-›PUPDR |= (pupdr ‹‹ (pin*2));
}
int keyboard_any_key(void){
int i;
for(i = 0; i ‹ COLS; i++){
if(col_port[i]-›IDR & (1 ‹‹ col_pin[i])){
return 1;
}
}
return 0;
}
char keyboard_find_key(uint8_t get_key){
uint8_t i;
char key_value;
for(i = 0; i ‹ sizeof(keytable); i++){
if(keytable[i][0] == get_key) {
key_value = keytable[i][1];
return key_value;
}
}
return 0;
}
void keyboard_handler(void){
static uint8_t state = 0, count_row = 0, key = 0;
static uint16_t count_scan = 0;
uint8_t i = 0;
switch(state){
case 0: //Ничего не нажато
if(keyboard_any_key()){
for(i = 0; i ‹ ROWS; i++){
row_port[i]-›BSRRH = (1 ‹‹ row_pin[i]); //устанавливаем на всех строках - 0
}
state = 1;
TIM6-›CR1 |= TIM_CR1_CEN;
}
break;
case 1: //Обнаружили какое-то нажатие
if(TIM6-›CNT ›= debounce){
state = 2;
debounce = 10 * KEY_SCAN_PERIOD; // 1ms
row_port[count_row]-›BSRRL = (1 ‹‹ row_pin[count_row]); //первый ряд установка в 1
TIM6-›CNT = 0;
}
break;
case 2: //Скан !!!! CNT = 0 не забыть
if(TIM6-›CNT ›= debounce){
for(i = 0; i ‹ COLS; i++){
if(col_port[i]-›IDR & (1 ‹‹ col_pin[i])){
key |= (1 ‹‹ i)|(1 ‹‹ 4 ‹‹ count_row);
}
}
row_port[count_row]-›BSRRH = (1 ‹‹ row_pin[count_row]); //0
count_row++;
if(ROWS != count_row){
row_port[count_row]-›BSRRL = (1 ‹‹ row_pin[count_row]); //1
}else{
if(!key){
TIM6-›CR1 &= ~TIM_CR1_CEN;
for(i = 0; i ‹ ROWS; i++){
row_port[i]-›BSRRL = (1 ‹‹ row_pin[i]); //устанавливаем на всех строках - 1
}
state = 0;
key = 0;
count_row = 0;
count_scan = 0;
old_key = 0;
debounce = 10 * KEY_SCAN_DELAY; // debounce delay 20 ms
}else{
if(!old_key){
old_key = key;
count_row = 0;
key = 0;
row_port[count_row]-›BSRRL = (1 ‹‹ row_pin[count_row]); //1
}else{
if(key != old_key){
TIM6-›CR1 &= ~TIM_CR1_CEN;
for(i = 0; i ‹ ROWS; i++){
row_port[i]-›BSRRL = (1 ‹‹ row_pin[i]); //устанавливаем на всех строках - 1
}
state = 0;
key = 0;
count_row = 0;
count_scan = 0;
old_key = 0;
debounce = 10 * KEY_SCAN_DELAY; // debounce delay 20 ms
}else{
if(count_scan == KEY_COUNT_SCAN){
count_scan = 0;
find_key = key;
key = 0;
state = 3;
count_row = 0;
row_port[count_row]-›BSRRL = (1 ‹‹ row_pin[count_row]); //1
}else{
key = 0;
count_scan++;
count_row = 0;
row_port[count_row]-›BSRRL = (1 ‹‹ row_pin[count_row]); //1
}
}
}
}
}
TIM6-›CNT = 0;
}
break;
case 3: //Удержание кнопки + отпускание
if(TIM6-›CNT ›= debounce){
for(i = 0; i ‹ COLS; i++){
if(col_port[i]-›IDR & (1 ‹‹ col_pin[i])){
key |= (1 ‹‹ i)|(1 ‹‹ 4 ‹‹ count_row);
}
}
row_port[count_row]-›BSRRH = (1 ‹‹ row_pin[count_row]); //0
count_row++;
if(ROWS != count_row){
row_port[count_row]-›BSRRL = (1 ‹‹ row_pin[count_row]); //1
}else{
if(key != old_key){
TIM6-›CR1 &= ~TIM_CR1_CEN;
for(i = 0; i ‹ ROWS; i++){
row_port[i]-›BSRRL = (1 ‹‹ row_pin[i]); //устанавливаем на всех строках - 1
}
state = 0;
key = 0;
count_row = 0;
count_scan = 0;
old_key = 0;
debounce = 10 * KEY_SCAN_DELAY; // debounce delay 20 ms
}else{
count_scan++;
if(count_scan == (KEY_HOLD_PERIOD / 3)){
find_hold_key = key;
}
count_row = 0;
row_port[count_row]-›BSRRL = (1 ‹‹ row_pin[count_row]); //1
key = 0;
}
}
TIM6-›CNT = 0;
}
break;
}
} |
keyboard.h
Нажмите, чтобы открыть спойлер
Код:
|
#ifndef KEYOARD_H
#define KEYOARD_H
#include "stm32f4xx.h"
#define ROWS 4 //Объявляем, что на клаве 4 ряда кнопок
#define COLS 3 //Объявляем, что на клаве 3 колонки кнопок
#define KEY_COUNT_SCAN 5 //Количество полных сканирований клавы, после которых принимается решение, что нажатие и отпускание кнопки засчитано.
#define KEY_SCAN_PERIOD 1 //полный прогон клавиатуры каждые.... мс
#define KEY_SCAN_DELAY 20 //Задержка в ms, перед началом сканирования (пропуск дребезга контактов)
#define KEY_HOLD_PERIOD 1000 //ms Продолжительность времени, за которое засчитываем удержание кнопки. Т.е. Длительное нажатие.
#define KEY_LED 0 //Если объявлен этот дефайн, то используется светодоид подтверждения нажатия клавиш. Если не используется, закомментировать строку. 0 - если светодиод включается подачей нуля на пин, 1 - если подачей единицы на пин
#define KEY_BUZZER 1 //Если объявлен этот дефайн, то используется буззер подтверждения нажатия клавиш. Если не используется, закомментировать строку. 0 - если буззер включается подачей нуля на пин, 1 - если подачей единицы на пин
#define KEY_ROW1_PORT GPIOB //Порт 1 ряда
#define KEY_ROW2_PORT GPIOB //Порт 2 ряда
#define KEY_ROW3_PORT GPIOB //Порт 3 ряда
#define KEY_ROW4_PORT GPIOB //Порт 4 ряда
#define KEY_ROW_PIN1 5 //Пин 1 ряда
#define KEY_ROW_PIN2 6 //Пин 2 ряда
#define KEY_ROW_PIN3 7 //Пин 3 ряда
#define KEY_ROW_PIN4 8 //Пин 4 ряда
#define KEY_COL1_PORT GPIOC //Порт 1 колонки
#define KEY_COL2_PORT GPIOC //Порт 2 колонки
#define KEY_COL3_PORT GPIOC //Порт 3 колонки
//#define KEY_COL4_PORT GPIOx //Порт 4 колонки
#define KEY_COL_PIN1 10 //Пин 1 колонки
#define KEY_COL_PIN2 11 //Пин 2 колонки
#define KEY_COL_PIN3 12 //Пин 3 колонки
//#define KEY_COL_PIN4 X //Пин 4 колонки
//#define KEY_HOLD_COUNTER_PERIOD (KEY_HOLD_PERIOD / KEY_SCAN_PERIOD)
extern uint8_t find_key, find_hold_key;
void keyboard_ini(void);
void port_cmd(GPIO_TypeDef * port);
void gpio_setup(GPIO_TypeDef * port, uint8_t pin, uint8_t moder, uint8_t otyper, uint8_t ospeedr, uint8_t pupdr);
int keyboard_any_key(void);
char keyboard_find_key(uint8_t);
void keyboard_handler(void);
#endif |
[IMG]/attachment.php?attachmentid=118840&d=1505845320[/IMG]
|
|
|
|
20.09.2017, 04:24
|
#126
|
Вид на жительство
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
|
Re: Оцените алгоритм опроса матричной клавы
Сообщение от supercelt
|
Может вывести код хоть всех нажатых клавиш одновременно.
|
А подробнее о железе - без диодов на кнопках или с ними? Да и всех нажатых одновременно вывести не проблема, проблема(без диодов) не выводить те, которые на самом деле не нажаты. Но если "фулл тач" не нужен, то и проблемы почти нет.
Сообщение от supercelt
|
Я не программер по образованию, так что можете критиковать. Я люблю адекватную критику.
|
Я тоже не программер, и до своей версии всё руки не доходят, хотя у меня и физической матричной клавы нет. Адекватная критика - это хорошо.
|
|
|
|
20.09.2017, 16:50
|
#127
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Оцените алгоритм опроса матричной клавы
Щас с диодами. Стоят на строках 4 штуки. Но это потому что у меня с открытым коллектором не получалось. Вот я и решил плюнуть и ловить единицу, а не ноль. А вот на этом новом алгоритме без диодов я не пробовал еще
|
|
|
|
20.09.2017, 21:11
|
#128
|
Вид на жительство
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
|
Re: Оцените алгоритм опроса матричной клавы
supercelt, это не те диоды, они не помогут сделать "фул тач". А я имел ввиду диоды последовательно с каждой кнопкой (и если они есть, то на строках или столбцах диоды уже не нужны). Чтобы проверить на "фул тач" зажмите все кнопки в одной любой строке и все кнопки в одном любом столбце и посмотрите число нажатых кнопок, которое выдаст программа - должно быть только 7 при любой комбинации строка-столбец.
|
|
|
|
21.09.2017, 00:19
|
#129
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Оцените алгоритм опроса матричной клавы
Диоды у меня стоят от КЗ. Нажал кнопки 1,2,3,6,9,#. Вывел код именно этих кнопок. Ну как бы код вместе всех нажатых.
|
|
|
|
21.09.2017, 15:16
|
#130
|
Вид на жительство
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
|
Re: Оцените алгоритм опроса матричной клавы
supercelt, как именно и что вывел код? Хотелось бы посмотреть именно этот код - что там действительно выводится, а не как-бы (выводилось find_hold_key?). И не будет ли он выводить этот же код вместе нажатых кнопок и при других сочетаниях вместе нажатых кнопок...
Посмотрел новую версию, что выложена немного выше и мне непонятен один момент - там у Вас 3 колонки и 4 ряда, значит всего кнопок 12 - соответственно надо 12 бит - для каждой кнопки свой бит. При этом переменные key, old_key, find_key и find_hold_key объявлены как uint8_t, т.е. всего 8 бит. Как так?
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 03:00.
|
|