Avrpmpop 0 5 сентября, 2014 Опубликовано 5 сентября, 2014 (изменено) · Жалоба Программа работы микроконтроллера с матричной клавиатурой 4х4. #asm .equ __lcd_port=0x15 #endasm #include <lcd.h> #include <stdio.h> #include <delay.h> #include <mega16.h> // quartz crystal frequency [Hz] #define F_XTAL 3686400L // PIND0..3 will be row inputs #define KEYIN PIND // PORTD4..7 will be column outputs #define KEYOUT PORTD // used for TIMER0 count initialization #define INIT_TIMER0 TCNT0=0x100L-F_XTAL/64L/500L #define FIRST_COLUMN 0x80 #define LAST_COLUMN 0x10 typedef unsigned char byte; // store here every key state as a bit, // bit 0 will be KEY0, bit 1 KEY1,... unsigned keys; // LCD display buffer char buf[33]; // TIMER 0 interrupt at every 2 ms interrupt [TIM0_OVF] void timer0_int(void) { static byte key_pressed_counter=20; static byte key_released_counter,column=FIRST_COLUMN; static unsigned row_data,crt_key; // reinitialize TIMER0 INIT_TIMER0; row_data<<=4; // get a group of 4 keys in in row_data row_data|=~KEYIN&0xf; column>>=1; if (column==(LAST_COLUMN>>1)) { column=FIRST_COLUMN; if (row_data==0) goto new_key; if (key_released_counter) --key_released_counter; else { if (--key_pressed_counter==9) crt_key=row_data; else { if (row_data!=crt_key) { new_key: key_pressed_counter=10; key_released_counter=0; goto end_key; }; if (!key_pressed_counter) { keys=row_data; key_released_counter=20; }; }; }; end_key:; row_data=0; }; // select next column, inputs will be with pull-up KEYOUT=~column; } // test if a key was pressed unsigned inkey(void) { unsigned k; if (k=keys) keys=0; return k; } void init_keypad(void) { DDRD=0xf0; INIT_TIMER0; TCCR0=3; TIMSK=2; #asm("sei") } main() { unsigned k; init_keypad(); lcd_init(20); lcd_putsf("CVAVR Keypad"); // read keys and display key code while (1) { lcd_gotoxy(0,1); if (k=inkey()) { sprintf(buf,"Key code=%Xh",k); lcd_puts(buf); } else lcd_putsf("NO KEY "); delay_ms(500); } } Здравствуйте помогите пожалуйста понять алгоритм работы выделенного жирным шрифтом фрагмента кода. Мне нужно его понять, чтоб написать свою программу. Иначе не выходит((( Насколько я понял там происходит чтение - нажата ли кнопка на определенной строке. Для этого взяли выходы порта D 7...4, как выходы столбцов. Но мне не понятно это условие if (column==(LAST_COLUMN>>1)) При самом первом вызове прерывания, там будет if(64==8) условие не выполняется, мы пропускаем все скобки и перемещаемся к строке KEYOUT=~column; И на этом всё, чтения не было. А как же тогда происходит считывание нажатых клавиш? Изменено 5 сентября, 2014 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kolobok0 0 6 сентября, 2014 Опубликовано 6 сентября, 2014 · Жалоба Программа работы микроконтроллера с матричной клавиатурой 4х4. .... static byte key_released_counter,column=FIRST_COLUMN; ... column>>=1; if (column==(LAST_COLUMN>>1)) ... ...понять алгоритм работы...это условие if (column==(LAST_COLUMN>>1)) ...будет if(64==8) ... пропускаем все скобки...А как же тогда происходит считывание нажатых клавиш? Всё очень просто... Прерывание от таймера. Т.е. оно происходит с определённым интервалом постоянно. Обратите внимание на переменную column она статична - т.е. её значение сохраняется между вызовами обработчика прерывания. т.е. вначале условие будет 64==8, в следующее прерывание 32==8, затем 16==8, 8==8... так же инверсия от column засылается на пины сканирования матрицы (получаем бегущий ноль) - см. конец обработчика. при этом на каждом проходе идёт запоминание пинов - см. raw_data (она так же статичная переменная) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Avrpmpop 0 7 сентября, 2014 Опубликовано 7 сентября, 2014 (изменено) · Жалоба Спасибо за ответ))) Я хочу разобрать прерывание по переполнению таймера отдельно. Вот такой код я сделал, тут в случае срабатывания прерывания на всех ножках порта С будет логическая "1". Но прерывание не срабатывает, что нужно мне сделать, что прерывание происходило? #include <mega16.h> #include <delay.h> interrupt [TIM0_OVF] void timer0_int(void)//прерывание по переполнению Таймера/Счетчика 0 { DDRC=0xFF; PORTC=0xFF; } void main(void) { SREG=0b10000000; TCCR0=0b00000001; while(1) { delay_ms(500); } } Изменено 7 сентября, 2014 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 35 7 сентября, 2014 Опубликовано 7 сентября, 2014 · Жалоба Вот такой код я сделал, тут в случае срабатывания прерывания на всех ножках порта С будет логическая "1". Но прерывание не срабатывает, что нужно мне сделать, что прерывание происходило? Добавьте: TIFR = 1; TIMSK = 1; А при TCCR0=1; прерывания по таймеру будут происходить слишком часто - Меге тяжело. Поставьте лучше TCCR0=5; // делитель 1:1024 все равно ведь кнопки пальцами давят, а потому милисекунды роли не играют. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Avrpmpop 0 7 сентября, 2014 Опубликовано 7 сентября, 2014 · Жалоба Добавьте: TIFR = 1; TIMSK = 1; Отлично,Великолепно))) Заработало))) Да вы просто Небожитель))) Великий))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 35 7 сентября, 2014 Опубликовано 7 сентября, 2014 · Жалоба Отлично,Великолепно))) Заработало))) Чтобы в самом деле было великолепно, было бы лучше заменить ATmega16 на какую-нибудь по современнее, у которых прерывание бывает не только от таймеров, но и от изменения уровней в порту (PCINT). Тогда прерывание будет происходить экономно - лишь в моменты, когда какая-то кнопка замыкает контакт или его размыкает (обычно это одно прерывание на весь порт). Скажем что-то вроде ATmega88/168. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Avrpmpop 0 7 сентября, 2014 Опубликовано 7 сентября, 2014 · Жалоба Ладно, буду пробовать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 35 7 сентября, 2014 Опубликовано 7 сентября, 2014 · Жалоба А у вас эта микросхемина в корпусе DIP40 или TQFP44? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Avrpmpop 0 7 сентября, 2014 Опубликовано 7 сентября, 2014 · Жалоба Пока еще никакая микросхема))) Теоретически пока ещё всё))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 35 7 сентября, 2014 Опубликовано 7 сентября, 2014 · Жалоба Пока еще никакая микросхема))) Теоретически пока ещё всё))) А как же тогда она у вас "заработала"? :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Avrpmpop 0 7 сентября, 2014 Опубликовано 7 сентября, 2014 (изменено) · Жалоба В Proteus 7 смоделировал))) Там по умолчанию DIP корпус, таким и оставил Изменено 7 сентября, 2014 пользователем Джигрудязь Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 35 7 сентября, 2014 Опубликовано 7 сентября, 2014 · Жалоба В Proteus 7 смоделировал))) Там по умолчанию DIP корпус, таким и оставил. А что? Я корпус DIP Тоже люблю :). Но раз оно у вас пока не в железе, то рекомендую все-таки присмотреться к тем Мегам, у которых имеется прерывание PCINT (от изменения уровней на всём порту). Их список нетрудно вытащить из хидеров, поиском на слово "PCINT". У меня получился такой список (преамбулу "ATmega" для краткости опускаю): 1280, 1281, 1284(p), 162, 164(a,p,pa), 165(a,p,pa), 168(a,p,pa), 169(a,p,pa), 2560, 2561, 324(a,p,pa), 325(a,p,pa), 3250(a,p,pa), 328(p), 329(a,p,pa), 3290(a,p,pa), 406, 48(a,p,pa), 640, 644(a,p,pa), 645(a,p,pa), 6450(a,p,pa), 649(a,p,pa), 6490(a,p), 88(a,p,pa). Если вы затрудняетесь выбрать сами, то могу посоветовать ATmega88a, если вам только для клавиатуры надо, и ATmega1284p, если для души :) (она же на фото изображена). Те и другие бывают в разных корпусах, в том числе и DIP. Остерегайтесь присохнуть к первой попавшейся, т.к. примерами изобилуют, как правило, самые старые. А то многие, как начали осваивать с 8515 или 8535, так и присохли к ним, хотя эти МК давно уже пора выбросить на свалку истории. :) P.S. На худой случай (если сами изготавливать платы не умеете) можно купить готовую Ардуинку, например, Arduino Uno, которая и подходящую (в смысле PCINT) микросхему содержит, и ардуинову прошивку позволяет заменить на свою. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Avrpmpop 0 7 сентября, 2014 Опубликовано 7 сентября, 2014 · Жалоба Вот оно чё)))))) Хорошо, буду знать))) Спасибо Большое))))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться