Семисегментный индикатор и клавиатура
06.05.2016, 21:23
|
|
|
Прохожий
Регистрация: 06.05.2016
Адрес: г. Санкт-Петербург
Сообщений: 9
Сказал спасибо: 5
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Семисегментный индикатор и клавиатура
Сообщение от andron007
|
|
Не думаю что этот кусок кода вам поможет.
|
Не пойму в чём проблема:
|
Код:
|
#include ‹inttypes.h›
#include ‹avr/io.h›
#include ‹avr/interrupt.h›
#include ‹avr/sleep.h›
#include ‹util/delay.h›
// Массив значений для порта вывода
unsigned char key_tab[4] = {0xFE, 0xFD, 0xFB, 0xF7};
volatile int display = 0;
unsigned char segcounter = 0; //Переменная
// массив цифр для индикатора
unsigned char num[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
// Функция опроса клавиатуры
unsigned char scan_key(void)
{
unsigned char key_value = 0;
unsigned char i;
for(i = 0;i ‹ 4;i++)
{
PORTB = key_tab[i]; // выводим лог. 0 в порт вывода
asm("Nop");
switch (PINB & 0xF0)
{
case 0b11100000: key_value = 1 + i * 3; break;
case 0b11010000: key_value = 2 + i * 3; break;
case 0b10110000: key_value = 3 + i * 3; break;
default:
break;
}
}
return (key_value);
}
// Обработчик прерывания по переполнению таймера 2
ISR(TIMER2_OVF_vect)
{
PORTD = 0xFF; // Гасим все разряды
PORTC = (1 ‹‹ segcounter); // Выбираем следующий разряд
switch(segcounter)
{
case 0:
PORTA = ~(num[display % 10000 / 1000]); // Раскладываем число на разряды
break;
case 1:
PORTA = ~(num[display % 1000 / 100]);
break;
case 2:
PORTA = ~(num[display % 100 / 10]);
break;
case 3:
PORTA = ~(num[display % 10]);
break;
}
if(segcounter++ › 2) segcounter = 0;
}
int main(void)
{
DDRB |= (1 ‹‹ PB3)|(1 ‹‹ PB2)|(1 ‹‹ PB1)|(1 ‹‹ PB0); // Порт вывода
DDRB &= ~(1 ‹‹ PB7)|(1 ‹‹ PB6)|(1 ‹‹ PB5)|(1 ‹‹ PB4); // Порт ввода
PORTB|= (1 ‹‹ PB3)|(1 ‹‹ PB2)|(1 ‹‹ PB1)|(1 ‹‹ PB0); // Устанавливаем лог. 1 в порт ввода
DDRC |= (1 ‹‹ PC3)|(1 ‹‹ PC2)|(1 ‹‹ PC1)|(1 ‹‹ PC0); // Устанавливаем лог. 1 в порт вывода
PORTC=0xF0;
DDRA = 0xFF; // Выход на индикатор
PORTA = 0x3F; // Отображаем 0 на индикаторе
TCCR2 |= (1 ‹‹ CS21); // Предделитель на 8
TIMSK |= (1 ‹‹ TOIE2); // Разрешение прерывания по таймеру 2
sei(); // Глобально разрешаем прерывания
asm("Nop"); // Небольшая задержка
while(1)
{
// Выводим значение нажатой кнопки на индикатор
switch(scan_key()){
case 1: PORTA = num[1]; break;
case 2: PORTA = num[2]; break;
case 3: PORTA = num[3]; break;
case 4: PORTA = num[4]; break;
case 5: PORTA = num[5]; break;
case 6: PORTA = num[6]; break;
case 7: PORTA = num[7]; break;
case 8: PORTA = num[8]; break;
case 9: PORTA = num[9]; break;
case 11: PORTA = num[0]; break;
default:
break;
}
}
} |
Нажимаю кнопки, на доли секунд появляются цифры в том же виде. Опять что то перепутала
Последний раз редактировалось AlesyaS; 06.05.2016 в 21:26.
|
|
|
|
07.05.2016, 01:26
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 20.08.2010
Адрес: Днепр
Сообщений: 8,548
Сказал спасибо: 5,035
Сказали Спасибо 10,605 раз(а) в 3,594 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
Сообщение от AlesyaS
|
|
Начала учить микроконтроллеры и программирование на Си совсем не давно
|
А я и вовсе не начинал
Сообщение от AlesyaS
|
|
asm("Nop"); // Небольшая задержка
|
Если две полоски, даже если они обе косые - это уже не небольшая задержка, а конкретный залет!
Ну, а теперь по теме. Дело в том, что даже кратковременное нажатие кнопки длится достаточно долго, чтобы за это время процессор тысячу раз успел опросить состояние клавиатуры, и выдать столько же раз код нажатой клавиши на индикацию. Поэтому индикатор мгновенно заполняется одинаковыми цифрами. Чтобы этого избежать, надо использовать не "небольшую" задержку в один асмовский ноп, а конкретную, длительностью хотя бы 100...200 миллисекунд.
Алгоритм примерно такой:
1. Опросить состояние клавиатуры
2. Если ни одна клавиша не нажата - возврат на (1)
3. Есть нажатая. Определить код нажатой клавиши
4. Преобразовать код клавиши в 7-сегментный
5. Сдвинуть все цифры в области индикации влево
6. Поместить 7-сегм код новой цифры в самое правое знакоместо
7. А вот теперь - не надо торопиться! Задержка 200 миллисекунд. Чтобы за это время палец успел отпустить нажатую клавишу. Иначе она введется еще раз (или много раз)
8. Возврат на (1)
А динамическая индикация - по прерыванию таймера.
|
|
|
|
07.05.2016, 03:32
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 25.05.2010
Адрес: г. Королёв
Сообщений: 8,487
Сказал спасибо: 30
Сказали Спасибо 3,070 раз(а) в 2,011 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
Cтудент на нерест попёр - ВЕСНА! 
Как бы ещё заметили такое событие?!
Сообщение от Alex9797
|
|
это уже не небольшая задержка, а конкретный залет!
|
Это место для точки останова.
Алеся, прежде чем переходить к программе, позвольте указать Вам на одну серьёзную аппаратную ошибку и один недочёт:
1. у Вас отсутствуют в схеме развязывающие диоды на сканере кнопок. В Протеусе, конечно же, ничего фатального не случится, ну разве кроме ошибок в дешифрации кнопок, а вот в реальном устройстве рискуете налететь на выгоревший порт.
2. зачем дополнительно сканировать кнопки, если один сканер у Вас уже есть - сканер разрядов индикации?
Также есть вопрос по алгоритму индикации нажатых кнопок, ибо сюда подходят навскидку 4 варианта...
Распишите, пожалуйста, поподробнее.
|
|
|
|
07.05.2016, 08:01
|
|
|
Прохожий
Регистрация: 06.05.2016
Адрес: г. Санкт-Петербург
Сообщений: 9
Сказал спасибо: 5
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Семисегментный индикатор и клавиатура
Сообщение от omercury
|
, ибо сюда подходят навскидку 4 варианта...
Распишите, пожалуйста, поподробнее.
|
После подачи на микроконтроллер питания на 7 сегментном 4 разрядном индикаторе высвечивается 0000.
После того как я нажала цифру 1 на матричной клавиатуре на индикаторе 0001.
Затем нажимаю 2 и на индикаторе соответственно 0012.
Затем нажимаю 3 и на индикаторе соответственно 0123.
Затем нажимаю 4 и на индикаторе соответственно 1234.
Потом хочу сделать что бы при нажатии на # индикатор обнулялся снова на 0000, вдруг я набрала не те цифры...
Спасибо за подсказку про диоды.
|
|
|
|
07.05.2016, 08:24
|
|
|
Прописка
Регистрация: 17.11.2009
Сообщений: 134
Сказал спасибо: 15
Сказали Спасибо 30 раз(а) в 16 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
Если извилины прямые, то диоды там не нужны.))
|
|
|
|
07.05.2016, 08:49
|
|
|
Вид на жительство
Регистрация: 11.08.2015
Сообщений: 409
Сказал спасибо: 17
Сказали Спасибо 37 раз(а) в 28 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
Тут надо не код внедрять, а самому писать.
Последний раз редактировалось Signalshik2; 07.05.2016 в 08:58.
|
|
|
|
07.05.2016, 09:32
|
|
|
Частый гость
Регистрация: 24.11.2006
Сообщений: 27
Сказал спасибо: 0
Сказали Спасибо 4 раз(а) в 4 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
Сообщение от AlesyaS
|
|
...
|
Программирование - учебное заведение или хобби? Я могу примеры дать, но там: модульность, псевдопараллельность процессов, программные таймеры. автоматное программирование. Возможно вам эти термины покажутся страшными и сложными, но на самом деле тут ничего сложного нет. Модульность программ. Программа дробится на модули. Опрос кнопок - отдельный модуль. Вывод на семисегментный дисплей - отдельный модуль. Вывод информации - отдельный модуль.
Псевдопараллельность. Модули, задачи в свою очередь дробятся условиями, флагами, состояниями конечных автоматов. Никаких долгих зацикленностей. Итерация основного цикла должна впаковаться с запасом в системный тик (к примеру 1 мс).
Программные таймеры - аппаратный таймер настраивается на определенное время. Скажем 1 мс. В прерывании переменная-счетчик инкрементируется. Структура программного таймера: статус, счетчик. Подробнее позже распишу.
Конечные автоматы - поисковики.
Почитайте этот цикл статей. Там вы многое почерпнете.
Последний раз редактировалось Insector; 07.05.2016 в 09:53.
|
|
|
|
Сказали "Спасибо" Insector
|
|
|
07.05.2016, 12:36
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 25.05.2010
Адрес: г. Королёв
Сообщений: 8,487
Сказал спасибо: 30
Сказали Спасибо 3,070 раз(а) в 2,011 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
Сообщение от OKF
|
|
Если извилины прямые, то диоды там не нужны.))
|
Если извилины прямые, то уже дебил. Никакие диоды не помогут...
Сообщение от AlesyaS
|
|
После того как я нажала цифру 1 на матричной клавиатуре на индикаторе 0001.
|
Нажали и отпустили или удерживаете?
Нажимаете вторую, удерживая первую?
Что будет, если одновременно нажаты несколько кнопок?
Ну и так далее, вариантов масса.
Полагаю, что Ваш самый простой - нажал/отпустил.
Давайте по порядку.
1. Клавиатура
Чтоб не заморачиваться постоянным переключением порта В на вход/выход, поставьте диоды на выходы катодами к портам.
Чтобы кнопки работали, нужно в соответствующие входам биты порта В записать "1" и использовать внутреннюю подтяжку к питанию, либо поставить внешние резисторы.
Чтобы исключить ложные и многократные срабатывания нужно фильтровать сканирование кнопок по времени. Неплохо также зафиксировать отпускание предыдущей кнопки перед фиксацией нажатия следующей.
Как МК определяет, которая из строк клавиатуры в данный момент активна? Это про scan_key(), да.
2. Индикация
Динамическая индикация оттого и названа динамической, что в один момент времени может светиться только один индикатор из ряда (тут тоже возможны варианты, например чарлисэмплинг, но пока усложнять не стоит). То же, что и с клавиатурой - как МК определяет, в который разряд в данный момент выводится индикация и что ему туда выводить? У Вас четырёхразрядный индикатор, попробуйте использовать буфер индикатора длиной 4 байта и в каждый разряд выводить свой байт, должно получиться значительно лучше. 
3.Логика
Считаем, что здесь пока ничего нет. 
4. Говнокод
Вы сами ещё не запутались в своих нулях и единицах? Это ж ужос!  Программа абсолютно нечитаема. Например вот это case 0b11100000: Ну и что здесь закодировано? Column_0_pressed будет понятнее, как думаете? Вы совершенно спокойно пользуетесь волатилами, учитесь использовать дефайны и макросы. Вынесите их в отдельную секцию, а ещё лучше в отдельный заголовочный файл, туда же сбросьте и переменные - пусть лежат в одном месте и не мешаются в тексте основной программы. Хорошим тоном будет таким же образом поступать и с самой программой - делить её на функциональные блоки-модули и сохранять и использовать отдельно. Например та же динамическая индикация. Разобрались один раз и начали наполнять свою собственную библиотеку кодов.
Ну пока хватит.
Последний раз редактировалось omercury; 07.05.2016 в 12:41.
|
|
|
|
07.05.2016, 12:44
|
|
|
Частый гость
Регистрация: 24.11.2006
Сообщений: 27
Сказал спасибо: 0
Сказали Спасибо 4 раз(а) в 4 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
|
Код:
|
//================================================== ======================
#ifndef SEVEN_SEGM_LED_IND_H
#define SEVEN_SEGM_LED_IND_H
#include "seven_segm_led_ind.h"
//================================================== ======================
//================================================== ======================
#include "main_def_func.h"
//================================================== ======================
//================================================== ======================
#define ANODS_PORT PORTA
#define ANODS_PIN PINA
#define ANODS_DDR DDRA
//#define ANODS_2_PORT PORTA
//#define ANODS_2_PIN PINA
//#define ANODS_2_DDR DDRA
#define KATODS_PORT PORTC
#define KATODS_PIN PINC
#define KATODS_DDR DDRC
//================================================== ======================
//================================================== ======================
#define ANOD_1 1‹‹2
#define ANOD_2 1‹‹3
#define ANOD_3 1‹‹4
#define ANOD_4 1‹‹5
#define ANOD_5 1‹‹6
#define ANOD_6 1‹‹7
//------------------------------------------------------------------------
#define A 1‹‹6
#define B 1‹‹7 // A
#define C 1‹‹3 // F B
#define D 1‹‹2 // G
#define E 1‹‹1 // E C
#define F 1‹‹5 // D
#define G 1‹‹4
#define H 1‹‹0
//------------------------------------------------------------------------
#define ZERO (A | B | C | D | E | F)
#define ONE (B | C)
#define TWO (A | B | D | E | G)
#define THREE (A | B | C | D | G)
#define FOUR (B | C | F | G)
#define FIVE (A | C | D | F | G)
#define SIX (A | C | D | E | F | G)
#define SEVEN (A | B | C)
#define EIGHT (A | B | C | D | E | F | G)
#define NINE (A | B | C | D | F | G)
#define SPACE 0
#define CHAR_SPACE 10
//================================================== ======================
//================================================== ======================
#define MAX_LED_INDS 6
#define ANODS_MASK (ANOD_1 | ANOD_2 | ANOD_3 | ANOD_4 | ANOD_5 | ANOD_6)
#define KATODS_MASK (A | B | C | D | E | F | G)
//================================================== ======================
//================================================== ======================
extern u08 dsp_buf [];
void clr_dsp_buf (void);
//================================================== ======================
//================================================== ======================
void _print_val_xxx (u08 x, u08 a);
#define print_val_xxx(x, a) _print_val_xxx(((x)-1), (a))
//================================================== ======================
//================================================== ======================
typedef struct index_anods
{
u08 i;
u08 anod;
} index_anods;
//================================================== ======================
//================================================== ======================
void set_proc_7_segm_ind_on (void);
void set_proc_7_segm_ind_off (void);
void proc_7_segm_ind (void);
//================================================== ======================
//================================================== ======================
#endif
//================================================== ====================== |
|
Код:
|
//================================================== ======================
#include "seven_segm_led_ind.h"
//================================================== ======================
//================================================== ======================
struct index_anods __flash tab_index_anods [] =
{
{0x01, ANOD_2},
{0x02, ANOD_3},
{0x03, ANOD_4},
{0x04, ANOD_5},
{0x05, ANOD_6},
{0x00, ANOD_1},
};
u08 __flash table_7_segm_char [11] =
{
ZERO, ONE,
TWO, THREE,
FOUR, FIVE,
SIX, SEVEN,
EIGHT, NINE,
SPACE,
};
//================================================== ======================
//================================================== ======================
soft_timer ST_PROC_7_SEGM_IND;
//------------------------------------------------------------------------
u08 dsp_buf [MAX_LED_INDS];
//------------------------------------------------------------------------
// Î÷èñòêà áóôåðà äèñïëåÿ.
u08 dsp_buf [MAX_LED_INDS];
void clr_dsp_buf (void)
{
for (u08 i = 0; i ‹ MAX_LED_INDS; i++)
dsp_buf [i] = CHAR_SPACE;
}
//================================================== ======================
//================================================== ======================
void _print_val_xxx (u08 x, u08 a) // Âûâîä ÷èñëà â ôîðìàòå xx,x.
{
char *ptr = num_str_buf + 7;
char_to_str (a);
dsp_buf[x] = *ptr; // Âûâîä ñîòåí.
dsp_buf[x++];
ptr++;
dsp_buf[x] = *ptr;
dsp_buf[x++];
ptr++;
dsp_buf[x] = *ptr; // Âûâîä åäèíèö.
}
//================================================== ======================
//================================================== ======================
static u08 _proc_7_segm_ind;
void set_proc_7_segm_ind_on (void)
{
_proc_7_segm_ind = 1;
}
void set_proc_7_segm_ind_off (void)
{
ANODS_DDR = 0;
ANODS_PORT = 0;
KATODS_DDR = 0;
_proc_7_segm_ind = 0;
}
void proc_7_segm_ind (void)
{
static u08 cnt_7_segm_ind;
switch (_proc_7_segm_ind)
{
case 0:
break;
case 1:
ANODS_DDR = 0xFF;
cnt_7_segm_ind = 0;
set_soft_timer (ST_PROC_7_SEGM_IND, 1, 1);
_proc_7_segm_ind = 2;
break;
case 2:
if (handle_soft_timer (ST_PROC_7_SEGM_IND))
{
u08 cnt = cnt_7_segm_ind;
u08 anods;
u08 katods;
ANODS_PORT = 0;
KATODS_DDR = 0;
cnt_7_segm_ind = tab_index_anods [cnt].i;
anods = tab_index_anods [cnt].anod;
katods = table_7_segm_char [dsp_buf [cnt_7_segm_ind]];
ANODS_PORT = anods;
KATODS_DDR = katods;
}
break;
default:
break;
}
}
//================================================== ====================== |
|
Код:
|
#ifndef KBD_DRV_H
#define KBD_DRV_H
#include "kbd_drv.h"
#include ‹ioavr.h›
#include "avrlibtypes.h"
#include "macros.h"
#include "main_def_func.h"
#include "sys_timer.h"
//================================================== ======================
#define DEBOUNCE_DELAY 20
#define HOLD_DELAY 1500
#define REPEAT_DELAY 125
//#define HOLD YES
//================================================== ======================
//================================================== ======================
#define TYPE_KEYS MATRIX
#define BUTTONS 0
#define MATRIX 1
//================================================== ======================
#if (TYPE_KEYS==BUTTONS)
//================================================== ======================
#define KEYS_PIN PINA
#define KEYS_DDR DDRA
#define KEYS_PORT PORTA
//================================================== ======================
#define KEYS_DDR_ESC DDRA
#define KEYS_DDR_ENTER DDRA
#define KEYS_DDR_UP DDRA
#define KEYS_DDR_DOWN DDRA
#define KEYS_DDR_PLUS DDRA
#define KEYS_DDR_MINUS DDRA
#define KEYS_DDR_6 DDRA
#define KEYS_DDR_7 DDRA
//------------------------------------------------------------------------
#define KEYS_PORT_ESC PORTA
#define KEYS_PORT_ENTER PORTA
#define KEYS_PORT_UP PORTA
#define KEYS_PORT_DOWN PORTA
#define KEYS_PORT_PLUS PORTA
#define KEYS_PORT_MINUS PORTA
#define KEYS_PORT_6 PORTA
#define KEYS_PORT_7 PORTA
//------------------------------------------------------------------------
#define KEYS_PIN_ESC PINA
#define KEYS_PIN_ENTER PINA
#define KEYS_PIN_UP PINA
#define KEYS_PIN_DOWN PINA
#define KEYS_PIN_PLUS PINA
#define KEYS_PIN_MINUS PINA
#define KEYS_PIN_6 PINA
#define KEYS_PIN_7 PINA
//------------------------------------------------------------------------
#define KEY_ESC_PIN 0
#define KEY_ENTER_PIN 1
#define KEY_UP_PIN 2
#define KEY_DOWN_PIN 3
#define KEY_PLUS_PIN 4
#define KEY_MINUS_PIN 5
//------------------------------------------------------------------------
#define KEY_ESC_BIT 1‹‹KEY_ESC_PIN
#define KEY_ENTER_BIT 1‹‹KEY_ENTER_PIN
#define KEY_UP_BIT 1‹‹KEY_UP_PIN
#define KEY_DOWN_BIT 1‹‹KEY_DOWN_PIN
#define KEY_PLUS_BIT 1‹‹KEY_PLUS_PIN
#define KEY_MINUS_BIT 1‹‹KEY_MINUS_PIN
#define KEY_ESC_COD 0
#define KEY_ENTER_COD 1
#define KEY_UP_COD 2
#define KEY_DOWN_COD 3
#define KEY_PLUS_COD 4
#define KEY_MINUS_COD 5
//================================================== ======================
//================================================== ======================
#define KEYS_MASK (KEY_ESC_BIT | KEY_ENTER_BIT | KEY_UP_BIT | KEY_DOWN_BIT | KEY_PLUS_BIT | KEY_MINUS_BIT)
//================================================== ======================
#elif (TYPE_KEYS==MATRIX)
//================================================== ======================
#define COL_DDR DDRC
#define ROW_DDR DDRC
#define COL_PIN PINC
#define ROW_PIN PINC
//------------------------------------------------------------------------
#define COL_MASK (1‹‹COL_1)+(1‹‹COL_2)+(1‹‹COL_3)+(1‹‹COL_4)
#define ROW_MASK (1‹‹ROW_1)+(1‹‹ROW_2)+(1‹‹ROW_3)+(1‹‹ROW_4)
//------------------------------------------------------------------------
/*
// STK-500
#define COL_1 3
#define COL_2 2
#define COL_3 1
#define COL_4 0
#define ROW_1 7
#define ROW_2 6
#define ROW_3 5
#define ROW_4 4
*/
// Плата управления.
#define COL_1 4
#define COL_2 5
#define COL_3 6
#define COL_4 7
#define ROW_1 0
#define ROW_2 1
#define ROW_3 2
#define ROW_4 3
//------------------------------------------------------------------------
#define KEY_ONE 0xEE // 1
#define KEY_TWO 0xED // 2
#define KEY_THREE 0xEB // 3
#define KEY_FOUR 0xDE // 4
#define KEY_FIVE 0xDD // 5
#define KEY_SIX 0xDB // 6
#define KEY_SEVEN 0xBE // 7
#define KEY_EIGHT 0xBD // 8
#define KEY_NINE 0xBB // 8
#define KEY_ZERO 0x7D // 0
#define KEY_A 0xE7 // A
#define KEY_ESC KEY_A
#define KEY_B 0xD7 // B
#define KEY_ENTER KEY_B
#define KEY_C 0xB7 // C
#define KEY_PREV KEY_C
#define KEY_D 0x77 // D
#define KEY_NEXT KEY_D
#define KEY_STAR 0x7E // *
#define KEY_PLUS KEY_STAR
#define KEY_LATTICE 0x7B // #
#define KEY_MINUS KEY_LATTICE
//------------------------------------------------------------------------
typedef enum kbd_codes
{
KEY_ZERO_COD = 0,
KEY_ONE_COD, // 1
KEY_TWO_COD, // 2
KEY_THREE_COD, // 3
KEY_FOUR_COD, // 4
KEY_FIVE_COD, // 5
KEY_SIX_COD, // 6
KEY_SEVEN_COD, // 7
KEY_EIGHT_COD, // 8
KEY_NINE_COD, // 9
KEY_ESC_COD, // 10, 0x0A
KEY_ENTER_COD, // 11, 0x0B
KEY_PREV_COD, // 12, 0x0C
KEY_NEXT_COD, // 13, 0x0D
KEY_PLUS_COD, // 14, 0x0E
KEY_MINUS_COD, // 15, 0x0F
} kbd_codes;
//================================================== ======================
#endif
//================================================== ======================
//#define KEY1_PRESSED() ((KEYS1_PIN & (1‹‹BIT_KEY1) == 0)
//#define KEY1_UNPRESSED() ((KEYS1_PIN & (1‹‹BIT_KEY1) == 1)
//================================================== ======================
//================================================== ======================
extern u08 _kbd_drv;
//------------------------------------------------------------------------
typedef enum kbd_states
{
KBD_DRV_INIT = 0,
KBD_DRV_NONE,
KBD_DRV_DOWN,
KBD_DRV_HOLD,
KBD_DRV_REPEAT,
KBD_DRV_WAIT_UP,
KBD_DRV_UP,
} kbd_states;
//================================================== ======================
enum
{
KEYS_PRESSED_FLG = 0,
};
//extern u08 keys_buf;
void scan_keys (void);
void kbd_drv (void);
extern struct tab_key_cod __flash tab_kbd_drv_keys_cod [];
extern u08 GetKeyCode (void);
#endif |
|
Код:
|
//================================================== ======================
#include "kbd_drv.h"
//================================================== ======================
//================================================== ======================
u08 _kbd_drv;
static u08 keys_flags;
static u08 keys_prev;
static u08 keys_curr;
static u08 keys_buf;
//================================================== ======================
#if (TYPE_KEYS==BUTTONS)
//================================================== ======================
void scan_keys (void)
{
if (keys_flags & (1‹‹KBD_DRV_RUN_FLG))
{
clrb (keys_flags, KEYS_PRESSED_FLG);
u08 a;
a = ~KEYS_PIN;
a &= KEYS_MASK;
if (a != 0)
{
setb (keys_flags, KEYS_PRESSED_FLG);
}
keys_curr = a;
}
}
//------------------------------------------------------------------------
struct tab_keys_code __flash tab_kbd_drv_keys_code [] =
{
{KEY_ESC_BIT, KEY_ESC_COD},
{KEY_ENTER_BIT, KEY_ENTER_COD},
{KEY_UP_BIT, KEY_UP_COD},
{KEY_DOWN_BIT, KEY_DOWN_COD},
{KEY_PLUS_BIT, KEY_PLUS_COD},
{KEY_MINUS_BIT, KEY_MINUS_COD},
{0xFF, 0xFF},
};
//================================================== ======================
#elif (TYPE_KEYS==MATRIX)
//================================================== ======================
void scan_keys (void)
{
if (_kbd_drv != KBD_DRV_INIT)
{
clr_bit (keys_flags, KEYS_PRESSED_FLG);
u08 a = 0xFF;
COL_DDR = COL_MASK;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
if (!(ROW_PIN & (1‹‹ROW_1)))
a &= (~(1‹‹7));
if (!(ROW_PIN & (1‹‹ROW_2)))
a &= (~(1‹‹6));
if (!(ROW_PIN & (1‹‹ROW_3)))
a &= (~(1‹‹5));
if (!(ROW_PIN & (1‹‹ROW_4)))
a &= (~(1‹‹4));
ROW_DDR = ROW_MASK;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
if (!(COL_PIN & (1‹‹COL_1)))
a &= (~(1‹‹3));
if (!(COL_PIN & (1‹‹COL_2)))
a &= (~(1‹‹2));
if (!(COL_PIN & (1‹‹COL_3)))
a &= (~(1‹‹1));
if (!(COL_PIN & (1‹‹COL_4)))
a &= (~(1‹‹0));
if (a != 0xFF)
set_bit (keys_flags, KEYS_PRESSED_FLG);
keys_curr = a;
}
}
//------------------------------------------------------------------------
struct tab_key_cod __flash tab_kbd_drv_keys_cod [] =
{
{KEY_ONE, KEY_ONE_COD},
{KEY_TWO, KEY_TWO_COD},
{KEY_THREE, KEY_THREE_COD},
{KEY_FOUR, KEY_FOUR_COD},
{KEY_FIVE, KEY_FIVE_COD},
{KEY_SIX, KEY_SIX_COD},
{KEY_SEVEN, KEY_SEVEN_COD},
{KEY_EIGHT, KEY_EIGHT_COD},
{KEY_NINE, KEY_NINE_COD},
{KEY_ZERO, KEY_ZERO_COD},
{KEY_A, KEY_ESC_COD},
{KEY_B, KEY_ENTER_COD},
{KEY_C, KEY_PREV_COD},
{KEY_D, KEY_NEXT_COD},
{KEY_STAR, KEY_MINUS_COD},
{KEY_LATTICE, KEY_PLUS_COD},
{0xFF, 0xFF},
};
//================================================== ======================
#endif
//================================================== ======================
void kbd_drv (void)
{
scan_keys ();
switch (_kbd_drv)
{
case KBD_DRV_INIT:
#if (TYPE_KEYS==BUTTONS)
KEYS_PIN = KEYS_MASK;
#endif
keys_prev = 0xFF;
// keys_buf = 0xFF;
_kbd_drv = KBD_DRV_NONE;
break;
case KBD_DRV_NONE:
if (keys_flags & (1‹‹KEYS_PRESSED_FLG))
{
keys_prev = keys_curr;
set_timer (ST_KBD_1, NO_RERUN_TIMER, DEBOUNCE_DELAY);
_kbd_drv = KBD_DRV_DOWN;
}
break;
case KBD_DRV_DOWN:
if (wait (ST_KBD_1))
{
if (keys_flags & (1‹‹KEYS_PRESSED_FLG) && keys_prev == keys_curr)
{
if (define_key_cod (keys_curr, keys_buf, tab_kbd_drv_keys_cod))
Set_Event (EV_ID_KEY_PRESSED, SET_CLR_EVENT);
set_timer (ST_KBD_1, NO_RERUN_TIMER, HOLD_DELAY);
_kbd_drv = KBD_DRV_HOLD; // KBD_DRV_WAIT_UP;
}
else
_kbd_drv = KBD_DRV_NONE;
}
break;
case KBD_DRV_HOLD:
case KBD_DRV_REPEAT:
if (!(keys_flags & (1‹‹KEYS_PRESSED_FLG)))
{
_kbd_drv = KBD_DRV_WAIT_UP;
return;
}
if (keys_prev != keys_curr)
{
_kbd_drv = KBD_DRV_NONE;
return;
}
if (wait (ST_KBD_1))
{
if (define_key_cod (keys_curr, keys_buf, tab_kbd_drv_keys_cod))
Set_Event (EV_ID_KEY_PRESSED, SET_CLR_EVENT);
set_timer (ST_KBD_1, NO_RERUN_TIMER, REPEAT_DELAY);
_kbd_drv = KBD_DRV_REPEAT;
}
break;
case KBD_DRV_WAIT_UP:
if (!(keys_flags & (1‹‹KEYS_PRESSED_FLG)))
{
set_timer (ST_KBD_1, NO_RERUN_TIMER, DEBOUNCE_DELAY);
_kbd_drv = KBD_DRV_UP;
}
break;
case KBD_DRV_UP:
if (wait (ST_KBD_1))
{
if (!(keys_flags & (1‹‹KEYS_PRESSED_FLG)))
_kbd_drv = KBD_DRV_NONE;
else
_kbd_drv = KBD_DRV_WAIT_UP;
}
break;
default:
break;
}
}
//================================================== ======================
//================================================== ======================
/*
u08 get_key (u08 key)
{
u08 tmp_key = keys_buf;
if (tmp_key != 0xFF)
{
if (tmp_key == key)
{
keys_buf = 0xFF;
return 1;
}
}
return 0;
}
*/
u08 GetKeyCode (void)
{
return keys_buf;
}
//================================================== ====================== |
|
|
|
|
07.05.2016, 13:00
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 25.05.2010
Адрес: г. Королёв
Сообщений: 8,487
Сказал спасибо: 30
Сказали Спасибо 3,070 раз(а) в 2,011 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
Сообщение от Insector
|
|
Код:
|
Эпическая сила! 
Юнионы, дефайны, структуры, условная компиляция... 
И всё на День Радио.
Сообщение от AlesyaS
|
|
Начала учить микроконтроллеры и программирование на Си совсем не давно.
|
Читайте по буквам - А Л Е С Я
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 16:24.
|
|