реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Помогите с матричной клавиатурой!, битый час мучаюсь
coolibin
сообщение Feb 28 2008, 06:35
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 19-07-07
Пользователь №: 29 228



Помогите сделать матричную клаву. Моя не пашет(((беру готовую рабочую схему, пишу програмулину, всё вроде делаю по примеру, а она всё равно не пашет, прерывание не срабатывает. Кто нить может поделиться соображениями/кодом реализации матричной клавиатуры через прерывание. Поиском пользовался, кое что нашел, но это только подтвердило что всё должно работать, но...(((


--------------------
Нет повести печальнее на свете, чем повесть о хреновом интернете.
Go to the top of the page
 
+Quote Post
Nanobyte
сообщение Feb 28 2008, 06:57
Сообщение #2


За битами по регистрам гоняюсь
***

Группа: Свой
Сообщений: 457
Регистрация: 24-04-06
Из: Таганрог
Пользователь №: 16 446



А что за схема? Как соединены выводы? Можно поподробнее?


--------------------
Курсор влево, курсор вправо - считается хакерством. FORMAT C: производится без предупреждения
Go to the top of the page
 
+Quote Post
vet
сообщение Feb 28 2008, 08:34
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32



и зачем именно через прерывание?
клавиатура - весьма медленное устройство ввода, для её обслуживания прекрасно подходит периодический опрос её состояния.
или планируется, что устройство будет просыпаться по прерыванию от клавиатуры?


--------------------
Главная линия этого опуса ясна мне насквозь!
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Feb 28 2008, 19:58
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



И как вы вообще прерывание от клавы делаете? Завели все опросные линии на отдельные Int или объединили их каким нибудь способом?

И к чему всё это поясните? Я в библиотеки выкладывал рабочую библиотеку 3х4 с возможностью динамического ввода и даже с вводом букв по принципу сотового телефона. Возьмите - пользуйтесь.
Go to the top of the page
 
+Quote Post
fate
сообщение Feb 28 2008, 22:58
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 107
Регистрация: 12-01-05
Пользователь №: 1 915



по прерываниям smile.gif

CODE

#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#define byte uint8_t
#define word uint16_t

#define KEY_SHORT 10
#define KEY_LONG 6000

volatile byte scan = 0;
volatile byte scan_stop = 0;
volatile byte scan_code = 0;
volatile word key_age = 0;
volatile byte key_pressed = 0;
volatile byte key_long = 0;

ISR(TIMER1_COMPA_vect)
{
if (!scan_stop) PORTL = ~_BV(++scan & 7);
else {
key_age += (key_age == 0xFFFF) ? 0 : 1;
if (key_age == KEY_SHORT) key_pressed = 1;
else if (key_age == KEY_LONG) key_long = 1;
}
PCICR |= _BV(PCIE2);
}

ISR(PCINT2_vect)
{
register byte i, p;

if ((p = PINK) != 0xFF) { // key pressed
for (i = 0; i != 8; i++) if(!(p & _BV(i))) break;
scan_code = (scan << 3) + i;
PCMSK2 = _BV(i);
scan_stop = 1;
key_age = 0;
} else { // key released
PCMSK2 = 0xFF;
scan_stop = 0;
}
PCICR &= ~_BV(PCIE2);
}

word
getkey()
{
word key;

for (;;) {
if (key_pressed) {
key_pressed = 0;
//
// do something
//
break;
}
else if (key_long) {
key_long = 0;
//
// do something
//
break;
}
}
return (key);
}

void
init(void)
{
// timer initialization
PRR0 &= ~_BV(PRTIM1); // enable timer 1

TCCR1A = 0;
TCCR1B = _BV(WGM12) | _BV(CS11);
TIMSK1 = _BV(OCIE1A);
TCNT1 = 0;
OCR1A = 2000;

// setup button interrupts
PCMSK2 = 0xFF;

sei();
}

int
main(void)
{
word i;

init();

for (;;) {
i = getkey();
//
// do something
//
}
exit(0);
}
Причина редактирования: Уменьшение видимого размера цитаты исходника.
Go to the top of the page
 
+Quote Post
rezident
сообщение Feb 28 2008, 23:40
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Не вдаваясь в разбор вашего исходника, попробую пояснить на "пальцах".
Для обслуживания матричной клавиатуры нужно реализовать как минимум три функции.
Функция №1. Сканирование матрицы, устранение дребезга, определение нажатых/отпущенных клавиш, формирование соответствующих скан-кодов, помещение скан-кодов в буфер клавиатуры.
Функция №2. Выдача текущего скан-кода без извлечения его из буфера.
Функция №3. Выдача текущего скан-кода с извлечением его из буфера.
Функция №1 обычно вызывается по прерыванию от таймера с равномерным интервалом времени (от 5мс до 100мс). Чаще, чем 200 раз в секунду вызывать ее нет смысла: а) никакая супер-пупер-машинистка не сможет с такой частотой колотить по клавишам; б) дребезг многих кнопок как раз порядка 1мс...10мс. Реже 10 раз в секунду тоже вызывать не желательно, т.к. будет значительная задержка генерации скан-кодов, а пользователю придется довольно долго удерживать клавиши для устойчивого определения нажатия их в программе. Лично я использую период 10...20мс.
Буфер нужен в любом случае. Хотя бы даже из одного байта буфер. Потому, что процесс опроса матрицы клавиш и процесс использования полученного скан-кода в общем случае асинхронные. Асинхронные процессы синхронизируются с помощью буферов. Буфер для кодов клавиатуры может быть линейным или циклическим. В первом случае используются две переменных: счетчик количества скан-кодов, находящихся в буфере и указатель на текущий скан-код. Во-втором случае нужны три переменных: тоже счетчик скан-кодов, указатель на позицию скан-кода, предназначенного для извлечения из буфера и указатель на позицию для записи следующего скан-кода. В первом случае необходимо строго следить за атомарностью (одновременностью) обнуления счетчика и указателя при извлечении всех скан-кодов. Потому, что Функции №2, 3 (чтение/извлечение скан-кода из буфера) могут быть прерваны Функцией №1.
Попробуйте пока осознать хотя бы это краткое описание. И на его основе реализовать свою программу.
Go to the top of the page
 
+Quote Post
coolibin
сообщение Feb 29 2008, 08:15
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 19-07-07
Пользователь №: 29 228



На ATmega16, на асме, код коцаный перекоцаный:
CODE
.include "m16def.inc"

.equ LCD_RS = 5
.equ LCD_E = 7

.def temp = r16
.def argument= r17 ;argument for calling subroutines
.def return = r18 ;return value from subroutines

.CSEG
.org 0
jmp RESET ; Reset

jmp EXT_INT1
reti
jmp EXT_INT1
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop



RESET:
clr r16
out GICR, r16 ;Disable external interrupt
out DDRA, r16 ;All in
out DDRB, r16
out DDRC, r16
out DDRD, r16

out PORTA, r16 ; All Tri-state
out PORTB, r16
out PORTC, r16
out PORTD, r16

ldi r16, 0b00100000
out DDRA, r16 ; ????? out A
ldi r16, 0xFF
out DDRB, r16 ; ????? out B
ldi r16, 0xFF
out DDRC, r16 ; ????? out C
ldi r16, 0b10100000
out DDRD, r16 ; ????? out D


ldi r16, 0x00 ;PORTA5 is RS
out PORTA, r16
ldi r16, 0b00110000
out PORTB, r16
ldi r16, 0x00
out PORTC, r16
ldi r16, 0x00 ;PORTD7 is E
out PORTD, r16

ldi r16, LOW(RAMEND) ;Stack Pointer
out SPL, r16
ldi r16, HIGH(RAMEND)
out SPH, r16

ldi r16, 0x00
out SFIOR, r16
ldi r16, 0x0B
out MCUCR, r16
ldi r16, 0x10
out WDTCR, r16

rcall LCD_init
rcall LCD_delay



ldi r16, 0x80
out GICR, r16


;rcall text_out


LOOP:
sei
rjmp LOOP

EXT_INT1:
rcall text_out ;MUST WORK!(((((((((((((((
reti


lcd_command8: ;used for init (we need some 8-bit commands to switch to 4-bit mode!)
;in temp, DDRD ;we need to set the high nibble of DDRD while leaving
;the other bits untouched. Using temp for that.
;sbr temp, 0b11110000 ;set high nibble in temp
;out DDRD, temp ;write value to DDRD again
in temp, PortC ;then get the port value
andi temp, 0x0F
andi argument, 0xF0 ;then clear the low nibble of the argument
;so that no control line bits are overwritten
or temp, argument ;then set the data bits (from the argument) in the
;Port value
out PortC, temp ;and write the port value.
cbi PortA, LCD_RS
sbi PortD, LCD_E ;now strobe E
nop
nop
nop
nop
nop
nop
nop
nop
cbi PortD, LCD_E
;cbi PortA, LCD_RS

ret

lcd_putchar:
push argument ;save the argmuent (it's destroyed in between)

in temp, PortC ;then get the data from PortD
;push temp
andi temp, 0x0F ;clear ALL LCD lines (data and control!)
andi argument, 0xF0 ;we have to write the high nibble of our argument first
;so mask off the low nibble
or temp, argument ;now set the argument bits in the Port value
out PortC, temp ;and write the port value
sbi PortA, LCD_RS ;now take RS high for LCD char data register access
sbi PortD, LCD_E ;strobe Enable
nop
nop
nop
nop
nop
nop
nop
nop
cbi PortD, LCD_E

pop argument ;restore the argument, we need the low nibble now...
andi temp, 0x0F ;clear the data bits of our port value
swap argument ;we want to write the LOW nibble of the argument to
;the LCD data lines, which are the HIGH port nibble!
andi argument, 0xF0 ;clear unused bits in argument
or temp, argument ;and set the required argument bits in the port value
out PortC, temp ;and write the port value
sbi PortA, LCD_RS ;now take RS high for LCD char data register access
sbi PortD, LCD_E ;strobe Enable
nop
nop
nop
nop
nop
nop
nop
nop
cbi PortD, LCD_E
;pop temp
;out PortC, temp
ret

lcd_command: ;same as LCD_putchar, but with RS low!
push argument ;save the argmuent (it's destroyed in between)

in temp, PortC ;then get the data from PortD
andi temp, 0x0F ;clear ALL LCD lines (data and control!)
andi argument, 0xF0 ;we have to write the high nibble of our argument first
;so mask off the low nibble
or temp, argument ;now set the argument bits in the Port value
out PortC, temp ;and write the port value
cbi PortA, LCD_RS ;now take RS high for LCD char data register access
sbi PortD, LCD_E ;strobe Enable
nop
nop
nop
nop
nop
nop
nop
nop
cbi PortD, LCD_E

pop argument ;restore the argument, we need the low nibble now...
andi temp, 0x0F ;clear the data bits of our port value
swap argument ;we want to write the LOW nibble of the argument to
;the LCD data lines, which are the HIGH port nibble!
andi argument, 0xF0 ;clear unused bits in argument
or temp, argument ;and set the required argument bits in the port value
out PortC, temp ;and write the port value
cbi PortA, LCD_RS ;now take RS high for LCD char data register access
sbi PortD, LCD_E ;strobe Enable
nop
nop
nop
nop
nop
nop
nop
nop
cbi PortD, LCD_E
ret

LCD_wait:
ldi r18, 0x03
LCD_wait_l1:
clr r19
LCD_wait_l2:
dec r19
brne LCD_wait_l2
dec r18
brne LCD_wait_l1

ret


LCD_delay:
clr r2
LCD_delay_outer:
clr r3
LCD_delay_inner:
dec r3
brne LCD_delay_inner
dec r2
brne LCD_delay_outer
ret

LCD_init:
rcall LCD_delay ;first, we'll tell the LCD that we want to use it
ldi argument, 0x20 ;in 4-bit mode.
rcall LCD_command8 ;LCD is still in 8-BIT MODE while writing this command!!!

rcall LCD_delay
ldi argument, 0x28 ;NOW: 2 lines, 5*7 font, 4-BIT MODE!
rcall LCD_command ;

rcall LCD_delay
ldi argument, 0x0F ;now proceed as usual: Display on, cursor on, blinking
rcall LCD_command

rcall LCD_delay
ldi argument, 0x01 ;clear display, cursor -> home
rcall LCD_command

rcall LCD_delay
ldi argument, 0x06 ;auto-inc cursor
rcall LCD_command
ret

text_out:
ldi Zl, LOW(2*line1)
ldi Zh, HIGH(2*line1)
text_out_l1:
lpm
adiw Zl, 1
tst r0
breq text_out_l2

mov argument, r0
rcall LCD_putchar
rcall LCD_wait
rjmp text_out_l1
text_out_l2:

ldi argument, 0x80
ori argument, 0x40
rcall LCD_command
rcall LCD_wait

ldi Zl, LOW(2*line2)
ldi Zh, HIGH(2*line2)
text_out_l3:
lpm
adiw Zl, 1
tst r0
breq text_out_l4
mov argument, r0
rcall LCD_putchar
rcall LCD_wait
rjmp text_out_l3
text_out_l4:
ret




line1: .db ' ',' ',' ','G','R','E','A','T','I','N','G','S','!',' ',' ',' ',0
line2: .db ' ',' ',' ','V','I','C','E',' ','C','I','T','Y','!',' ',' ',' ',0

...как тэг кода ставить? не подскажете?
Причина редактирования: Оформление цитаты исходника.


--------------------
Нет повести печальнее на свете, чем повесть о хреновом интернете.
Go to the top of the page
 
+Quote Post
vet
сообщение Feb 29 2008, 08:59
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32



coolibin,
как приведённый код соотносится с обсуждаемой темой?
Цитата
...как тэг кода ставить? не подскажете?
давим кнопку "Ответить"; обращаем внимание на спецкнопочки над полем ввода сообщения.


--------------------
Главная линия этого опуса ясна мне насквозь!
Go to the top of the page
 
+Quote Post
coolibin
сообщение Feb 29 2008, 10:46
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 19-07-07
Пользователь №: 29 228



Цитата(vet @ Feb 29 2008, 10:59) *
как приведённый код соотносится с обсуждаемой темой?

Это собственно и есть моя программа которая не работает, прерывание не происходит((

Сообщение отредактировал coolibin - Feb 29 2008, 10:46


--------------------
Нет повести печальнее на свете, чем повесть о хреновом интернете.
Go to the top of the page
 
+Quote Post
GDI
сообщение Feb 29 2008, 10:56
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



Цитата
...как тэг кода ставить? не подскажете?

можно и в окне быстрого ответа просто написать (code)тут ваш код(/code), только скобочки квадратные поставить [].


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
vet
сообщение Feb 29 2008, 11:22
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32



Цитата(coolibin @ Feb 29 2008, 13:46) *
Это собственно и есть моя программа которая не работает, прерывание не происходит((

так про матричную клавиатуру в коде ни единого намека smile.gif
а прерывание не происходит, потому что вектор прописан неправильно.


--------------------
Главная линия этого опуса ясна мне насквозь!
Go to the top of the page
 
+Quote Post
=GM=
сообщение Feb 29 2008, 11:42
Сообщение #12


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(vet @ Feb 29 2008, 11:22) *
а прерывание не происходит, потому что вектор прописан неправильно

Поправлю, для INT0 - правильно, а для INT1 - неправильно.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
coolibin
сообщение Feb 29 2008, 12:57
Сообщение #13


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 19-07-07
Пользователь №: 29 228



Цитата(vet @ Feb 29 2008, 13:22) *
так про матричную клавиатуру в коде ни единого намека smile.gif
а прерывание не происходит, потому что вектор прописан неправильно.

Ну, задумывалась она как матричная клава. Дальше прерывания не дошёл. А что в векторе прерываний не правильно? Дело в том что это моя первая прога раньше никогда не писал под микропроцы


--------------------
Нет повести печальнее на свете, чем повесть о хреновом интернете.
Go to the top of the page
 
+Quote Post
vet
сообщение Feb 29 2008, 13:11
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32



Цитата(coolibin @ Feb 29 2008, 15:57) *
А что в векторе прерываний не правильно?
не на месте.
разрешено INT1, а инициализирован вектор INT0.


--------------------
Главная линия этого опуса ясна мне насквозь!
Go to the top of the page
 
+Quote Post
coolibin
сообщение Mar 1 2008, 11:11
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 19-07-07
Пользователь №: 29 228



Цитата(vet @ Feb 29 2008, 15:11) *
не на месте.
разрешено INT1, а инициализирован вектор INT0.


Вы имеете ввиду нужно так:
Код
jmp RESET; Reset
nop
jmp EXT_INT1

?
Я так сначала и делал, но результат не изменился(((


--------------------
Нет повести печальнее на свете, чем повесть о хреновом интернете.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 13:15
Рейтинг@Mail.ru


Страница сгенерированна за 0.01423 секунд с 7
ELECTRONIX ©2004-2016