09.09.2016, 20:38
|
#11
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Оцените алгоритм опроса матричной клавы
Короче сделал ). Нажатия обрабатываются вроде быстро, по крайней мере на глаз тормозов нет. Правда пришлось отказаться от внешних прерываний, подумал, фиг с ним, пусть таймер постоянно тикает. С прерываниями работало медленно + не сбрасывался флаг UIF таймера, хотя дебаггер по нему проходился. Можно посчитать удержание. И символ не печатается повторно при зажатии кнопки. Как-то так
Код:
|
#include "keyboard.h"
uint8_t timer_flag = 0;
uint8_t count_scan = 0;
uint8_t count_up = 0;
uint8_t count_down = 0;
uint16_t key = 0;
uint16_t old_key = 0;
uint16_t find_key = 0;
unsigned char cols[] = {5,6,7,8};
void TIM2_IRQHandler(void){
TIM2-›SR = 0;
timer_flag = 1;
}
void KEYBOARD_INI(void){
RCC-›APB2ENR |= RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN; //CMD PORT B. cmd alt func
GPIOB-›CRH &= ~(GPIO_CRH_CNF11_0 | GPIO_CRH_CNF12_0 | GPIO_CRH_CNF13_0 | GPIO_CRH_CNF14_0); //Scan Pins: PB11, PB12, PB13, PB14.
GPIOB-›CRH |= GPIO_CRH_CNF11_1 | GPIO_CRH_CNF12_1 | GPIO_CRH_CNF13_1 | GPIO_CRH_CNF14_1; //Input Push-down.
GPIOB-›CRL &= ~(GPIO_CRL_CNF5_0 | GPIO_CRL_CNF6_0 | GPIO_CRL_CNF7_0); //Generate Pins: PB5, PB6, PB7, PB8.
GPIOB-›CRH &= ~GPIO_CRH_CNF8_0;
GPIOB-›CRL |= GPIO_CRL_MODE5_1 | GPIO_CRL_MODE6_1 | GPIO_CRL_MODE7_1; //Output Push-pull.
GPIOB-›CRH |= GPIO_CRH_MODE8_1;
GPIOB-›BSRR = 0x1E0;
//--------Setup TIMER 2---------------------------
RCC-›APB1ENR |= RCC_APB1ENR_TIM2EN; //Enable TIMER 2
TIM2-›PSC = 0x95F; //Prescaler 2400 - 1/ Clock timer 1 kHz
TIM2-›CR1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD); //Count up, clock division, mode selection
TIM2-›ARR = 0x32; //0xC8; //0x2710; //Count up to 200/ Interrupt/20ms
NVIC_EnableIRQ(TIM2_IRQn); //Enable interrupt for timer2
TIM2-›DIER |= TIM_DIER_UIE; //Interrupt update counter/ perepolnenie
TIM2-›SR = 0;
TIM2-›CR1 |= TIM_CR1_CEN;
//------------------------------------------------
//test led pc8
GPIOC-›CRH &= ~GPIO_CRH_CNF8_0;//TEST LED EXTI
GPIOC-›CRH |= GPIO_CRH_MODE8_1;
GPIOC-›BSRR = 0x100;
//
}
void KEYBOARD_SCAN(void){
timer_flag = 0;
if(!GPIOB-›IDR & 0x7800){return;}
for(count_scan = 0; count_scan ‹ 4; count_scan++){
GPIOB-›BRR = 0x1E0;
GPIOB-›BSRR = (1 ‹‹ cols[count_scan]);
if(count_down ›= 10){
if(GPIOB-›IDR & 0x7800){
count_up = 0;
return;
} else {
count_up++;
}
if(count_up == 10){
count_up = 0;
count_down = 0;
find_key = 0;
return;
}
} else {
if(GPIOB-›IDR & 0x7800){
key = (GPIOB-›IDR & 0x79E0);
if(key == old_key){
count_down++;
} else {
old_key = key;
}
}
if(count_down == 10){
old_key = 0;
find_key = READ_KEY(key);
return;
}
}
}
}
char READ_KEY(uint16_t k){
char c;
switch(k){
case 0x820:
c = '1';
break;
case 0x840:
c = '2';
break;
case 0x880:
c = '3';
break;
case 0x900:
c = 'A';
break;
case 0x1020:
c = '4';
break;
case 0x1040:
c = '5';
break;
case 0x1080:
c = '6';
break;
case 0x1100:
c = 'B';
break;
case 0x2020:
c = '7';
break;
case 0x2040:
c = '8';
break;
case 0x2080:
c = '9';
break;
case 0x2100:
c = 'C';
break;
case 0x4020:
c = '*';
break;
case 0x4040:
c = '0';
break;
case 0x4080:
c = '#';
break;
case 0x4100:
c = 'D';
break;
default:
c = 'E';
break;
}
return c;
}
//Ne uspevaet otrabotat/ count_down ne doschitivaet/ Tolko kogda derzhish knopku podolshe/ Uskorit opros/ Zamenil 0x32 na 0xA/ Poeksperimentirovat |
|
|
|
|
04.03.2017, 22:00
|
#12
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Оцените алгоритм опроса матричной клавы
Сообщение от NewWriter
|
А благодаря выходам Open drain и входам pullup, никаких запредельных токов и без дополнительных элементов, клавиатура подключается непосредственно на порты МК.
|
Я сделал так и теперь при нажатии кнопки у меня блёкнут символы на LCD дисплее. Это конечно не критично, но на глаз заметно. Запредельных токов нет, но походу идёт просадка напруги через этот Open Drain
|
|
|
|
23.08.2017, 18:10
|
#13
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Опрос матричной клавы. Часть2
Всем привет. Помогите пожалуйста разобраться. Код который ниже успешно работал на stm32f100. Теперь я его перенес на f4, естественно поменяв все что нужно. Но работать нормально отказывается. Кто не видел поста раньше, - это опросник матричной клавы 3х4 (оригинал кода немного отличается от того что в прошлом посте). Мне советовали сделать строки в открытый коллектор, перевести выводы в высокоомку и потом при сканировании гонять 0. А строки сделать на вход с подтяжкой к питанию. И на строках ловить ноль, когда нажимаю кнопку. Вобщем логика такая. Сначала идут настройки. Немного а автомате, что бы при смене пинов и портов много не переписывать. Так, значит в начальном состоянии строки настроены как открытый коллектор и я подтянул его к 0. Далее настроил все колонки на внешнее прерывание по спаду. По идее, когда нажмут любую кнопку сработает прерывание. Ну собсно оно так и происходит. Проверял. Значит щас будет таймлапс. Нажали кнопку. Сработало прерывание, вошли в вектор, сбросили флаги, потом выключили все внешние прерывания, что бы не сработало от дребезга. Далее перевели все строки в высокоомку. ну как бы в 1. Запустили таймер, который будет запускать сканирование каждые н милисекунд - указано в параметрах. Так, таймер начал тикать. Попал в прерывание по переполнению, установил start_scan. Далее эта штука ловится в мэйне и вызывает функцию скана. Теперь самое интересное. И так. Открываем цикл скана строк. переводим 1 строку в 0. и ещё циклом перебираем столбы, смотрим есть 0 или нет. Ну дальше идут всякие вычисления по подсчету нажатия кнопки, сколько держали, когда отпустили и расчет на удержание кнопки. В коде к строчкам есть пояснения.
Проблема то в чем, а в том, что на f4 это не работает, хотя должно. Точнее сказать почти работает. К слову я вывожу нажатую кнопку на lcd. Работает только самый нижний ряд клавиатуры, то есть *0#. Остальное не выводится, но в отладчике если смотреть, когда нажимаешь клавишу 1, переменная key будет 4. Если нажать 4, будет 7. То есть со смещением на 1 вниз. И причем на экран так и не выводит, то есть почему-то не засчитывает нажатие.
Далее поэкспериментировав я обнаружил интересную вещь. Если строки при настройках, подтянуть не к 0, а к 1, то начинает работать последний столбец - 3,6,9,#. ну и так же нижний ряд. Остальное не пашет. Потом я вернул подтяжку в 0, так как изначально для реагирования на прерывания по спаду, должен быть 0.
Закралась мне мысль, что эти мещения могут быть от того что кто-то что-то не успевает. И там где в цикле идет установка 0, я поставил задержку. Она закоменчена. И хм.мм.. да надо подержать кнопку подольше, но теперь работают все кнопки. То есть я так понял, что этот 0 на строке не успевает установиться? А я уже проверяю его....При это нижний ряд все так же исправно и быстро работает. Вобщем такая вот проблема.
Листинги:
keyboard.c
Нажмите, чтобы открыть спойлер
Код:
|
#include "keyboard.h"
#include "delay.h"
uint8_t start_scan = 0, counter_row_scan = 0, counter_col_scan = 0, counter_release = 0, counter_pressed = 0;
char key = 0, old_key = 0, find_key = 0, find_hold_key = 0;
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 keys[ROWS][COLS] = { //Массив кнопок 3х4
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
void TIM6_DAC_IRQHandler(void){
if(TIM6-›SR & TIM_SR_UIF){
TIM6-›SR &= ~TIM_SR_UIF;
start_scan = 1;
}
}
void EXTI15_10_IRQHandler(void){ //Обработчик внешних прерываний с 10 по 15 пинов (при смене пинов, дописать нужные обработчики. Этот не универсален)
uint8_t i;
if(EXTI-›PR & (1 ‹‹ 10)){
EXTI-›PR = (1 ‹‹ 10);
}
if(EXTI-›PR & (1 ‹‹ 11)){
EXTI-›PR = (1 ‹‹ 11);
}
if(EXTI-›PR & (1 ‹‹ 12)){
EXTI-›PR = (1 ‹‹ 12);
}
if(EXTI-›PR & (1 ‹‹ 13)){
EXTI-›PR = (1 ‹‹ 13);
}
if(EXTI-›PR & (1 ‹‹ 14)){
EXTI-›PR = (1 ‹‹ 14);
}
if(EXTI-›PR & (1 ‹‹ 15)){
EXTI-›PR = (1 ‹‹ 15);
}
for(i = 0; i ‹ COLS; i++){
EXTI-›FTSR &= ~(1 ‹‹ col_pin[i]); //Выкл прерывания путём откл условия срабатывания прерывания (по спаду фронта). Если откл разрешение прерывания, то потом при его вкл, почему-то сразу срабатывает прерывание
}
for(i = 0; i ‹ ROWS; i++){
row_port[i]-›BSRRL = (1 ‹‹ row_pin[i]); //Все пины в 1
}
TIM6-›CR1 |= TIM_CR1_CEN;
}
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, 1, 0x02, 0x02); //настройка рядов выходов. Порт, пин, MODER, OTYPER, OSPEEDR, PUPDR
}
for(i = 0; i ‹ COLS; i++){
port_cmd(col_port[i]); //Включаем тактирование порта столбца
gpio_setup(col_port[i], col_pin[i], 0x00, 0, 0x00, 0x01); //настройка рядов выходов. Порт, пин, MODER, OTYPER, OSPEEDR, PUPDR
}
//EXTI
RCC-›APB2ENR |= RCC_APB2ENR_SYSCFGEN; //Включить тактирование syscfg для доступа к записи в регистры exticr
for(i = 0; i ‹ COLS; i++){
exti_setup(col_port[i], col_pin[i]);
}
//TIM6
RCC-›APB1ENR |= RCC_APB1ENR_TIM6EN;
TIM6-›PSC |= 8399; //F = 10 kHz
TIM6-›ARR = (10*KEY_SCAN_PERIOD);
TIM6-›EGR |= TIM_EGR_UG;
__NOP();
__NOP();
TIM6-›SR &= ~(TIM_SR_UIF);
TIM6-›DIER |= TIM_DIER_UIE;
NVIC_EnableIRQ(TIM6_DAC_IRQn);
}
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));
}
void exti_setup(GPIO_TypeDef * port, uint8_t pin){
SYSCFG-›EXTICR[pin ›› 2] |= ((((uint32_t)port - AHB1PERIPH_BASE) ›› 10) ‹‹ ((pin%4) ‹‹ 2));
EXTI-›IMR |= (1 ‹‹ pin);
EXTI-›FTSR |= (1 ‹‹ pin);
switch(pin){
case 0:
NVIC_EnableIRQ(EXTI0_IRQn);
break;
case 1:
NVIC_EnableIRQ(EXTI1_IRQn);
break;
case 2:
NVIC_EnableIRQ(EXTI2_IRQn);
break;
case 3:
NVIC_EnableIRQ(EXTI3_IRQn);
break;
case 4:
NVIC_EnableIRQ(EXTI4_IRQn);
break;
case 5:
case 6:
case 7:
case 8:
case 9:
NVIC_EnableIRQ(EXTI9_5_IRQn);
break;
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
NVIC_EnableIRQ(EXTI15_10_IRQn);
break;
}
}
void keyboard_scan(void){
int i;
start_scan = 0; //Сбрасываем флаг, после вызова этой функции
for(counter_row_scan = 0; counter_row_scan ‹ ROWS; counter_row_scan++){ //Сканирование рядов
row_port[counter_row_scan]-›BSRRH = (1 ‹‹ row_pin[counter_row_scan]); //Выставляем 0 на текущем пине рядов
//delay_us(5);
for(counter_col_scan = 0; counter_col_scan ‹ COLS; counter_col_scan++){ //Сканирование колонок
if(!(col_port[counter_col_scan]-›IDR & (1 ‹‹ col_pin[counter_col_scan]))){ //Если на текущем пине колонок обнаружился 0
counter_release = 0; //Обнулить счётчик отпускания кнопки
key = keys[counter_row_scan][counter_col_scan]; //Записать текущеесостояние кнопки из массива
if(key == old_key){ //Если текущая кнопка равна кнопке с прошлого сканирования
if(KEY_COUNT_SCAN == counter_pressed++){ //Если кнопку нажимают в течении количества сканирований, указанных в параметрах, то засчитываем нажатие кнопки + увеличиваем счётчик нажатой кнопки
find_key = key; //Кнопка найдена
}
if(KEY_HOLD_COUNTER_PERIOD == counter_pressed){ //Срабатывание от длительного нажатия кнопки //Если кнопка нажата в течении указанного в параметрах количества секунд
find_hold_key = key; //Символ пустышка, для опознования, что сработало долгое нажатие определённой кнопки.
}
}else{
old_key = key; //В следующем сканировании, old key это будет значение кнопки просканенное в прошлый раз
}
}else{
if(counter_pressed › KEY_COUNT_SCAN){ //Если количество сканирований нажатой кнопки больше указанных в параметрах
if((COLS * KEY_COUNT_SCAN) == counter_release++){ //Если количество колонок умноженное на количество, заданное в параметрах, сканирований отпущенной кнопки равно количеству сканирований отпущенной кнопки + попутно сразу инкремент счётчика
counter_pressed = 0; //Сброс счётчика нажатой кнопки
counter_release = 0; //Сброс счётчика отпущенной кнопки
TIM6-›CR1 &= ~TIM_CR1_CEN; //Выключение таймера2
TIM6-›CNT = 0; //Обнуление счётчика таймера2
old_key = 0;
key = 0;
for(i = 0; i ‹ ROWS; i++){
row_port[i]-›BSRRH = (1 ‹‹ row_pin[i]); //Все пины рядов обратно в 0
EXTI-›FTSR |= (1 ‹‹ col_pin[i]); //Включаем прерывания путём вкл условия срабатывания прерывания (по спаду фронта)
}
return; //Кнопка отжата, всё выключили, больше в этой функции нечего делать, поэтому принудительно выходим
}
}
}
}
row_port[counter_row_scan]-›BSRRL = (1 ‹‹ row_pin[counter_row_scan]); //После скана всех колонок поднимаем лог уровень на текущем ряде в 1
}
} |
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 10 //Период сканирования, 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 start_scan;
extern char find_key, find_hold_key;
void keyboard_ini(void);
void keyboard_scan(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);
void exti_setup(GPIO_TypeDef * port, uint8_t pin);
#endif |
main.c
Нажмите, чтобы открыть спойлер
Код:
|
//Файлы должны быть в кодировке ANSI! Настройка кодировки Keil - win cp1251
#include "stm32f4xx.h"
#include "main.h"
int main(void){
SystemInit();
SystemCoreClockUpdate();
__enable_irq();
lcd_ini();
keyboard_ini();
//lcd_send_string_xy(0,0,"Тест. Ю Ы Ж");
while(1){
if(start_scan){
keyboard_scan();
}
if(find_key){
lcd_send_data(find_key);
find_key = 0;
}
if(find_hold_key){
lcd_send_string_xy(0,0,"HOLD");
find_hold_key = 0;
}
}
} |
Последний раз редактировалось supercelt; 23.08.2017 в 18:14.
|
|
|
|
23.08.2017, 23:01
|
#14
|
Гражданин KAZUS.RU
Регистрация: 01.09.2007
Сообщений: 898
Сказал спасибо: 278
Сказали Спасибо 57 раз(а) в 54 сообщении(ях)
|
Re: Опрос матричной клавы. Часть2
Странно, на чипе с более медленной тактовой частотой работает, на более мощном чипе не работает....
Хоть ссылку дайте на предыдущий пост, без схемотехники очень трудно что то понять в вашем коде....
|
|
|
|
24.08.2017, 16:10
|
#15
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Опрос матричной клавы. Часть2
Пытаюсь... кусок кода
Код:
|
void keyboard_scan(void){
int i;
static int ii;
start_scan = 0; //Сбрасываем флаг, после вызова этой функции
for(counter_row_scan = 0; counter_row_scan ‹ ROWS; counter_row_scan++){ //Сканирование рядов
row_port[counter_row_scan]-›BSRRH = (1 ‹‹ row_pin[counter_row_scan]); //Выставляем 0 на текущем пине рядов
//while((row_port[counter_row_scan]-›ODR & (1 ‹‹ row_pin[counter_row_scan])) == 1){}//test
for(counter_col_scan = 0; counter_col_scan ‹ COLS; counter_col_scan++){ //Сканирование колонок
if(!(col_port[counter_col_scan]-›IDR & (1 ‹‹ col_pin[counter_col_scan]))){ //Если на текущем пине колонок обнаружился 0
counter_release = 0; //Обнулить счётчик отпускания кнопки
key = keys[counter_row_scan][counter_col_scan]; //Записать текущеесостояние кнопки из массива
ke[ii++] = counter_row_scan;
if(key == old_key){ //Если текущая кнопка равна кнопке с прошлого сканирования
if(KEY_COUNT_SCAN == counter_pressed++){ //Если кнопку нажимают в течении количества сканирований, указанных в параметрах, то засчитываем нажатие кнопки + увеличиваем счётчик нажатой кнопки
find_key = key; //Кнопка найдена
} |
думал, 0 на рядах не успевает устанавливаться, ввел строчку while((row_port[counter_row_scan]-›ODR & (1 ‹‹ row_pin[counter_row_scan])) == 1){}//test
Не помогает. По прежнему работает только нижний ряд. Далее ввел массив ke. и просто заполняю его индексами рядов. То есть при сканировании если нажатие найдено, то индекс ряда к котором это произошло запишется в этот массив.
Результаты этого массива таковы: когда я нажимаю любую кнопку из нижнего 4 ряда, в массиве везде 3. Что и правильно. Но когда я жму любую другую кнопку, в массиве - 0,1,2,3,0,1,2,3,0,1,2,3.
То есть получается на столбце 0 всегда. Не зависимо от того что вообще-то по рядам единицы и 0 поочередно прогоняется. Мистика.
|
|
|
|
24.08.2017, 22:51
|
#16
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Оцените алгоритм опроса матричной клавы
Выкинул прерывания, теперь таймер работает постоянно. Скан клавы непрерывано. Тупо гоняем скан. Из кода для проверки выкинул все лишнее, просто посмотреть что записывается в key и ke.
Код:
|
void keyboard_scan(void){
//int i;
start_scan = 0; //Сбрасываем флаг, после вызова этой функции
for(counter_row_scan = 0; counter_row_scan ‹ ROWS; counter_row_scan++){ //Сканирование рядов
row_port[counter_row_scan]-›BSRRH = (1 ‹‹ row_pin[counter_row_scan]); //Выставляем 0 на текущем пине рядов
while((row_port[counter_row_scan]-›ODR & (1 ‹‹ row_pin[counter_row_scan])) == 1){}//test
for(counter_col_scan = 0; counter_col_scan ‹ COLS; counter_col_scan++){ //Сканирование колонок
if(!(col_port[counter_col_scan]-›IDR & (1 ‹‹ col_pin[counter_col_scan]))){ //Если на текущем пине колонок обнаружился 0
key = keys[counter_row_scan][counter_col_scan]; //Записать текущеесостояние кнопки из массива
ke[ii++] = counter_row_scan;
}
row_port[counter_row_scan]-›BSRRL = (1 ‹‹ row_pin[counter_row_scan]); //После скана всех колонок поднимаем лог уровень на текущем ряде в 1
while((row_port[counter_row_scan]-›ODR & (1 ‹‹ row_pin[counter_row_scan])) == 0){}//test
}
} |
Даже поставил вайлы для надежности. мало ли бит не успевает железо поставить. Вобщем если ставить точку останова к примеру на if(!(col_port[counter_col_scan]-›IDR & (1 ‹‹ col_pin... и запустить, то при нажатии на кнопку клавиатуры "1" и далее по шагам дойти до key, то оно будет 1. Но если убрать точку останова, запустить и нажать "1", то key будет "*". Опять последний ряд(((
|
|
|
|
25.08.2017, 08:58
|
#17
|
Прописка
Регистрация: 02.03.2010
Сообщений: 139
Сказал спасибо: 12
Сказали Спасибо 49 раз(а) в 26 сообщении(ях)
|
Re: Оцените алгоритм опроса матричной клавы
Вы работаете так: проверили состояние одного пина, прочитав порт, затем проверяете следующий, опять читая порт.
Пожалуй, правильнее будет так:
Установите ряд.
Прочитайте порт строк в переменную и "сканируйте" биты в ней.
Даже так:
Установив ряд, задайте небольшую задержку, емкости реальной схемы никто не отменял.
В вашем случае:
Считывайте значение по установленному в предыдущем такте таймера ряду, а затем меняйте его. Задержка будет не нужна.
Последний раз редактировалось 6ap6oc; 25.08.2017 в 09:06.
|
|
|
|
25.08.2017, 10:03
|
#18
|
Почётный гражданин KAZUS.RU
Регистрация: 12.02.2013
Сообщений: 1,038
Сказал спасибо: 43
Сказали Спасибо 273 раз(а) в 214 сообщении(ях)
|
Re: Оцените алгоритм опроса матричной клавы
Сообщение от supercelt
|
Код который ниже успешно работал на stm32f100
|
А опрашивать клавиатуру со скоростью несколько десятков мегагерц это хорошая идея ??
Про отсутствие защиты от дребезга контактов я уже молчу.
|
|
|
|
25.08.2017, 10:13
|
#19
|
Модератор
Регистрация: 04.08.2010
Адрес: Москва СЗАО
Сообщений: 11,257
Сказал спасибо: 11,170
Сказали Спасибо 3,858 раз(а) в 2,928 сообщении(ях)
|
Re: Оцените алгоритм опроса матричной клавы
supercelt, может посмотрите это решение на досуге?
В МК останется только код для инициализации, обработки прерывания и считывания результата. И ног гораздо меньше отнимет - всего 4.
А там уже и защита от дребезга, и все остальные плюшки .
Просто время, уже потраченное на изобретение велосипеда, явно гораздо дороже стоит чем комплект разработчика с мешочком чипов по ссылке…
__________________
rtfm forever должно быть основой для каждого. Альтернатива грустна, поскольку метод слепого щенка успешно работает при весьма малом числе вариантов…
|
|
|
|
25.08.2017, 14:13
|
#20
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Оцените алгоритм опроса матричной клавы
Сообщение от dgrishin
|
А опрашивать клавиатуру со скоростью несколько десятков мегагерц это хорошая идея ??
Про отсутствие защиты от дребезга контактов я уже молчу.
|
У меня таймер настроен на 10 килогерц. То есть функция которая сканит вызывается с этой частотой. Но вот сам скан из вот этих циклов и установок битов, там конечно все происходит со скоростью в мегагерцы. Можно по идее снизить частоту камня до той что у меня была в прошлом чипе, ну а ели мне понадобится полная мощность для чего-нибудь другого что я сюда же подцеплю?
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 04:44.
|
|