Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту


 
Опции темы
Непрочитано 07.09.2017, 22:31  
6ap6oc
Прописка
 
Регистрация: 02.03.2010
Сообщений: 139
Сказал спасибо: 12
Сказали Спасибо 49 раз(а) в 26 сообщении(ях)
6ap6oc на пути к лучшему
По умолчанию Re: Оцените алгоритм опроса матричной клавы

Всегда из входов можно сделать выходы и наоборот и считать нажатыми кнопки после двойной проверки. Я правда не знаю, зачем это. Проще миниклаву подключить готовую.

Если с точки зрения безопасности - игнорировать тройные нажатия и все.
Реклама:

Последний раз редактировалось 6ap6oc; 07.09.2017 в 22:41.
6ap6oc вне форума  
Непрочитано 07.09.2017, 23:52  
H4LF
Вид на жительство
 
Аватар для H4LF
 
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
H4LF на пути к лучшему
По умолчанию Re: Оцените алгоритм опроса матричной клавы

Сообщение от 6ap6oc Посмотреть сообщение
Всегда из входов можно сделать выходы и наоборот и считать нажатыми кнопки после двойной проверки. Я правда не знаю, зачем это.
Вот именно что незачем, так как в данном случае это не поможет. Игнорировать достаточно больше трёх одновременных, но можно и больше двух или больше одного, смотря какая задача.

А вообще над алгоритмом игнорирования можно подумать... Проверил на стареньком клоподаве nokia - реагирует на одновременное нажатие "123", "456", "147", "753" и т.п. А вот если зажимать "785" или "463" и т.п., то третья цифра игнорируется пока не будет отпущена любая из первых двух. А на новом дешёвом клоподаве alcatel реагирует только на одну кнопку, но на нём так и написано: "onetouch" ))
H4LF вне форума  
Непрочитано 08.09.2017, 16:32  
6ap6oc
Прописка
 
Регистрация: 02.03.2010
Сообщений: 139
Сказал спасибо: 12
Сказали Спасибо 49 раз(а) в 26 сообщении(ях)
6ap6oc на пути к лучшему
По умолчанию Re: Оцените алгоритм опроса матричной клавы

Чего так сразу, не поможет? =)
Очень надо будет - поможет , вы можете вообще все выводы кроме одного сделать входами. Но, опять же, вряд ли это кому то нужно.
6ap6oc вне форума  
Непрочитано 08.09.2017, 16:46  
H4LF
Вид на жительство
 
Аватар для H4LF
 
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
H4LF на пути к лучшему
По умолчанию Re: Оцените алгоритм опроса матричной клавы

6ap6oc, это тоже не поможет определить, даже если очень надо будет - какая именно из четырёх кнопок в "квадрате" не нажата (или нажаты все 4). Если считаете, что поможет - хотелось бы узнать - как?
Нужно или не нужно - это уже другой вопрос (например в нокии сделали блокировку "больше трёх", а в алкателе сделали блокировку "больше одного").
H4LF вне форума  
Непрочитано 19.09.2017, 22:25  
supercelt
Прописка
 
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
supercelt на пути к лучшему
По умолчанию 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]
Миниатюры:
Нажмите на изображение для увеличения
Название: Алгоритм ф-ии scan. Вызов по прерыванию.jpg
Просмотров: 0
Размер:	214.4 Кб
ID:	118840  
supercelt вне форума  
Непрочитано 20.09.2017, 04:24  
H4LF
Вид на жительство
 
Аватар для H4LF
 
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
H4LF на пути к лучшему
По умолчанию Re: Оцените алгоритм опроса матричной клавы

Сообщение от supercelt Посмотреть сообщение
Может вывести код хоть всех нажатых клавиш одновременно.
А подробнее о железе - без диодов на кнопках или с ними? Да и всех нажатых одновременно вывести не проблема, проблема(без диодов) не выводить те, которые на самом деле не нажаты. Но если "фулл тач" не нужен, то и проблемы почти нет.
Сообщение от supercelt Посмотреть сообщение
Я не программер по образованию, так что можете критиковать. Я люблю адекватную критику.
Я тоже не программер, и до своей версии всё руки не доходят, хотя у меня и физической матричной клавы нет. Адекватная критика - это хорошо.
H4LF вне форума  
Непрочитано 20.09.2017, 16:50  
supercelt
Прописка
 
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
supercelt на пути к лучшему
По умолчанию Re: Оцените алгоритм опроса матричной клавы

Щас с диодами. Стоят на строках 4 штуки. Но это потому что у меня с открытым коллектором не получалось. Вот я и решил плюнуть и ловить единицу, а не ноль. А вот на этом новом алгоритме без диодов я не пробовал еще
supercelt вне форума  
Непрочитано 20.09.2017, 21:11  
H4LF
Вид на жительство
 
Аватар для H4LF
 
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
H4LF на пути к лучшему
По умолчанию Re: Оцените алгоритм опроса матричной клавы

supercelt, это не те диоды, они не помогут сделать "фул тач". А я имел ввиду диоды последовательно с каждой кнопкой (и если они есть, то на строках или столбцах диоды уже не нужны). Чтобы проверить на "фул тач" зажмите все кнопки в одной любой строке и все кнопки в одном любом столбце и посмотрите число нажатых кнопок, которое выдаст программа - должно быть только 7 при любой комбинации строка-столбец.
H4LF вне форума  
Непрочитано 21.09.2017, 00:19  
supercelt
Прописка
 
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
supercelt на пути к лучшему
По умолчанию Re: Оцените алгоритм опроса матричной клавы

Диоды у меня стоят от КЗ. Нажал кнопки 1,2,3,6,9,#. Вывел код именно этих кнопок. Ну как бы код вместе всех нажатых.
supercelt вне форума  
Непрочитано 21.09.2017, 15:16  
H4LF
Вид на жительство
 
Аватар для H4LF
 
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
H4LF на пути к лучшему
По умолчанию Re: Оцените алгоритм опроса матричной клавы

supercelt, как именно и что вывел код? Хотелось бы посмотреть именно этот код - что там действительно выводится, а не как-бы (выводилось find_hold_key?). И не будет ли он выводить этот же код вместе нажатых кнопок и при других сочетаниях вместе нажатых кнопок...

Посмотрел новую версию, что выложена немного выше и мне непонятен один момент - там у Вас 3 колонки и 4 ряда, значит всего кнопок 12 - соответственно надо 12 бит - для каждой кнопки свой бит. При этом переменные key, old_key, find_key и find_hold_key объявлены как uint8_t, т.е. всего 8 бит. Как так?
H4LF вне форума  
 

Закладки
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


Часовой пояс GMT +4, время: 19:04.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot