Форум РадиоКот • Просмотр темы - Опрос матричной клавиатуры.
Сообщения без ответов | Активные темы
Страница 1 из 1
[ Сообщений: 20 ]
Автор
Сообщение
azerhud
Заголовок сообщения: Опрос матричной клавиатуры.
Добавлено: Чт июл 21, 2022 16:09:19
Зарегистрирован: Чт июл 21, 2022 15:37:28Сообщений: 31
Рейтинг сообщения: 0
Доброе время суток. Есть код опроса матричной клавиатуры и вывода данных на LCD дисплей. У автора он работал. Я внёс не большое изменения, переключил строки на другой порт и теперь как бы я не старался, код не работает. С автором связаться не смог так как статья 24.08.2013 года. Может кто поможет понять ошибку? Сам код и схема :
Спойлер Код:
#include <mega8.h> // Alphanumeric LCD Module functions #asm .equ __lcd_port=0x18 ;PORTB #endasm #include <lcd.h> int i=0,j=0; char portStateC[4]= {0xEF,0xDF,0xBF,0x7F}; char inputStateD[4]={0x01,0x02,0x04,0x08}; char mass2[4][4]={{'1','2','3','4'}, {'5','6','7','8'}, {'9','A','B','C'}, {'D','E','F','D'}}; interrupt [TIM2_COMP] void timer2_comp_isr(void) { for(i=0; i<4; i++) { PORTD=portStateC[i]; for(j=0; j<4; j++) { if(((PIND&inputStateD[j])==0) && (PINC&inputStateD[j])) { while((PIND&inputStateD[j])!=inputStateD[j]){}; lcd_putchar(mass2[i][j]); } } } } void main(void) { PORTC=0xFF; DDRC=0x0F; PORTD=0xFF; DDRD=0xF0; ASSR=0x00; TCCR2=0x0F; TCNT2=0x00; OCR2=0xC3; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x80; lcd_init(8); // Global enable interrupts #asm("sei") while (1) { }; }
Добавил файлы проекта.
Последний раз редактировалось azerhud Пт июл 22, 2022 09:30:37, всего редактировалось 2 раз(а).
Вернуться наверх
Реклама
Dimon456
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Чт июл 21, 2022 19:39:09
Карма: 20
Рейтинг сообщений: 145
Зарегистрирован: Вс дек 25, 2016 08:34:54Сообщений: 1849
Рейтинг сообщения: 0
Проект вместе с протеусом сюда, в архив zip, иначе ни кто вам этот код разбирать не будет.
Вернуться наверх
Реклама
Martian
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Чт июл 21, 2022 21:55:42
Карма: 68
Рейтинг сообщений: 1958
Зарегистрирован: Сб дек 18, 2021 19:25:32Сообщений: 12867
Рейтинг сообщения: 0
char portStateC[4]= {0xEF,0xDF,0xBF,0x7F}; здесь смещение нуля в старших разрядах, но в схеме подключено к младшим. char inputStateD[4]={0x01,0x02,0x04,0x08}; здесь смещение единицы в младших разрядах, но в схеме подключено к старшим. PORTD=portStateC[i] здесь к D происходит подключение того, что для C, и 1это вроде бы делает логичным нелогичное выше, но нелогично в целом. if(((PIND&inputStateD[j])==0) && (PINC&inputStateD[j])) - inputStateD как бы намекает, что это для сравнения с D как со входом... но: выше уже всё было перепутано, а тут внезапно сравнивается и PIND и PINC... И всё это вообще неважно: по схеме порт D является входом для сигнала с порта C. В порту C в младших четырёх разрядах должна бегать единичка, притом, цикл из 4 итераций не нужен, лучше поднять частоту срабатывания таймера. И массив для перемещения единичким тоже не нужен, есть прекрасные короткие сдвиги. А в программе всё наоборот и в кашу
Вернуться наверх
azerhud
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Пт июл 22, 2022 06:30:48
Зарегистрирован: Чт июл 21, 2022 15:37:28Сообщений: 31
Рейтинг сообщения: 0
Здесь подправил.
Код:
char portStateC[4]= {0xFE,0xFD,0xFB,0xF7}; char inputStateD[4]={0x01,0x20,0x40,0x80}; //... interrupt [TIM2_COMP] void timer2_comp_isr(void) { for(i=0; i<4; i++) { PORTC=portStateC[i]; for(j=0; j<4; j++) { if(((PIND&inputStateD[j])==0) && (PINC&inputStateD[j])) { while((PIND&inputStateD[j])!=inputStateD[j]){}; lcd_putchar(mass2[i][j]); } } } } //...
Но похоже опять я сделал что то не так
Последний раз редактировалось azerhud Пт июл 22, 2022 13:59:44, всего редактировалось 1 раз.
Вернуться наверх
Martian
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Пт июл 22, 2022 09:48:02
Карма: 68
Рейтинг сообщений: 1958
Зарегистрирован: Сб дек 18, 2021 19:25:32Сообщений: 12867
Рейтинг сообщения: 0
А я тоже ошибся, в логике. Прошу прощения.
Сканирующим портом всё-таки является порт D и там должен бегать лог. 0 - тогда при нажатии двух и более кнопок исключается закорачивание выходов, если бы сканирование было на порту С
то есть, скан должен быть так (как и было в самом начале, за исключением несовпадающих по логике наименований):
Код:
char portStateD[4]= {0xEF,0xDF,0xBF,0x7F}; char portStateD[4]= {0xEF,0xDF,0xBF,0x7F}; //... interrupt [TIM2_COMP] void timer2_comp_isr(void) { for(i=0; i<4; i++) { PORTD=portStateD[i]; for(j=0; j<4; j++) { //... } } }
то есть, осталось всего лишь правильно определить во втором цикле, где на порту С образовался 0.
Кстати, порт С должен обязательно быть сконфигурирован с внутренней подтяжкой к питанию.
например, так:
Код:
char portStateD[4]= {0xEF,0xDF,0xBF,0x7F}; //... interrupt [TIM2_COMP] void timer2_comp_isr(void) { for(i=0; i<4; i++) { PORTD=portStateD[i]; for(j=0; j<4; j++) { if(!(PORTС & (1 << j)) { //здесь получили координаты i и j кнопки } } } }
Вернуться наверх
Реклама
azerhud
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Пт июл 22, 2022 10:05:53
Зарегистрирован: Чт июл 21, 2022 15:37:28Сообщений: 31
Рейтинг сообщения: 0
Не совсем понял этот момент.
...
то есть, скан должен быть так (как и было в самом начале, за исключением несовпадающих по логике наименований):
Код:
char portStateD[4]= {0xEF,0xDF,0xBF,0x7F}; char portStateD[4]= {0xEF,0xDF,0xBF,0x7F}; //...
мне нужно дважды задать этот массив?
Код:
har portStateD[4]= {0xEF,0xDF,0xBF,0x7F}; char portStateD[4]= {0xEF,0xDF,0xBF,0x7F};
Весь код.
Спойлер Код:
#include <mega8.h> // Alphanumeric LCD Module functions #asm .equ __lcd_port = 0x18 ; PORTB #endasm #include <lcd.h> int i = 0, j = 0; char portStateD[4] = {0xEF, 0xDF, 0xBF, 0x7F}; char inputStateC[4] = {0x01, 0x02, 0x04, 0x08}; char mass2[4][4] = {{'1', '2', '3', '4'}, {'5', '6', '7', '8'}, {'9', 'A', 'B', 'C'}, {'D', 'E', 'F', 'D'} }; interrupt [TIM2_COMP] void timer2_comp_isr(void) { for(i = 0; i < 4; i++) { PORTD = portStateD[i]; for(j = 0; j < 4; j++) { if((!(PORTC) & (1 << j))) { if(((PIND & inputStateC[j]) == 0) && (PINC & inputStateC[j])) { while((PIND & inputStateC[j]) != inputStateC[j]) {}; lcd_putchar(mass2[i][j]); } } } } } void main(void) { PORTC = 0xFF; DDRC = 0x0F; PORTD = 0xFF; DDRD = 0xF0; ASSR = 0x00; TCCR2 = 0x0F; TCNT2 = 0x00; OCR2 = 0xC3; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK = 0x80; lcd_init(8); // Global enable interrupts #asm("sei") while (1) ; }
Вернуться наверх
Реклама
metan
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Пт июл 22, 2022 11:47:49
Карма: 6
Рейтинг сообщений: 183
Зарегистрирован: Ср янв 06, 2010 10:01:46Сообщений: 585
Рейтинг сообщения: 0
Вам же дали готовую процедуру
Вот так попробуйте
Код:
interrupt [TIM2_COMP] void timer2_comp_isr(void) { for(i = 0; i < 4; i++) { PORTD = portStateD[i]; for(j = 0; j < 4; j++) { if((!(PINC) & (1 << j))) lcd_putchar(mass2[i][j]); } } }
char portStateD[4] = {0xEF, 0xDF, 0xBF, 0x7F}; //только один раз, конечно нужно объявлять
char inputStateC[4] = {0x01, 0x02, 0x04, 0x08}; // в предлагаемом варианте вообще не нужен
И да, вам еще сказали, что младшие линии порта опроса (PORTC) должны быть настроены на вход с подтяжкой. И посмотрите, как у вас. Чтобы не путаться, избегайте магических цифр, или хотя бы дополняйте их подробным комментарием, куда, что и как настраивается. Хотя бы как визард это делает:
Код:
// Input/Output Ports initialization // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=P State6=P State5=P State4=P State3=P State2=P State1=P State0=P PORTB=0xFF; DDRB=0x00;
Вернуться наверх
azerhud
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Пт июл 22, 2022 13:23:17
Зарегистрирован: Чт июл 21, 2022 15:37:28Сообщений: 31
Рейтинг сообщения: 0
Уже не знаю что делать, вроде перепробовал все Ваши варианты.
Спойлер Код:
#include <mega8.h> // Alphanumeric LCD Module functions #asm .equ __lcd_port = 0x18 ; PORTB #endasm #include <lcd.h> int i = 0, j = 0; char portStateD[4] = {0xEF, 0xDF, 0xBF, 0x7F}; char mass2[4][4] = {{'1', '2', '3', '4'}, {'5', '6', '7', '8'}, {'9', 'A', 'B', 'C'}, {'D', 'E', 'F', 'D'} }; interrupt [TIM2_COMP] void timer2_comp_isr(void) { for(i = 0; i < 4; i++) { PORTD = portStateD[i]; for(j = 0; j < 4; j++) { if((!(PINC) & (1 << j))) lcd_putchar(mass2[i][j]); } } } void main(void) { DDRC = 0x0F; // Единица младших разрядах, порт настроен как выход, PORTC = 0xFF; // Включаем подтягивающие резисторы DDRD = 0xF0; // Ноль младших разрядах, порт настроен как вход, PORTD = 0xFF; // Включаем подтягивающие резисторы ASSR = 0x00; TCCR2 = 0x0F; TCNT2 = 0x00; OCR2 = 0xC3; TIMSK = 0x80; lcd_init(8); // Global enable interrupts #asm("sei") while (1) ; }
Опишу проблему. Исходная статья по адресу
http://avr-start.ru/?p=1244&cpage=1#comments Всё работает отлично, но мне нужно подключить клавиатуру 4х5 и передавать символы нажатой кнопки по UART. Для этого я и решил разделить строки и столбцы. Но как бы я не пытался не удаётся мне запустить программу. Может найдётся человек который напишет мне рабочую программу с подробным описанием. Готов заплатить. Бюджет не большой
У самого уже мозги кипят.
Вернуться наверх
Dimon456
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Пт июл 22, 2022 14:19:49
Карма: 20
Рейтинг сообщений: 145
Зарегистрирован: Вс дек 25, 2016 08:34:54Сообщений: 1849
Рейтинг сообщения: 0
Спойлер Код:
char portStateD[4] = {0xEF, 0xDF, 0xBF, 0x7F}; char inputStateC[4] = {0x01, 0x02, 0x04, 0x08}; char mass2[4][4] = {{'1', '2', '3', '4'}, {'5', '6', '7', '8'}, {'9', 'A', 'B', 'C'}, {'D', 'E', 'F', 'D'} }; interrupt [TIM2_COMP] void timer2_comp_isr(void) { char i,j; for(i=0; i<4; i++) { PORTD=portStateD[i]; for(j=0; j<4; j++) { if(((PINC&inputStateC[j])==0)) { while((PINC&inputStateC[j])!=inputStateC[j]){}; lcd_putchar(mass2[i][j]); } } } } void main(void) { DDRC = 0x00; PORTC = 0xFF; DDRD = 0xF0; PORTD = 0xFF; ASSR = 0x00; TCCR2 = 0x0F; TCNT2 = 0x00; OCR2 = 0xC3; TIMSK = 0x80; lcd_init(8); #asm("sei") while (1) ; }
Вернуться наверх
Реклама
azerhud
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Пт июл 22, 2022 15:33:13
Зарегистрирован: Чт июл 21, 2022 15:37:28Сообщений: 31
Рейтинг сообщения: 0
Dimon456 , Огромное СПАСИБО за помощь
Вернуться наверх
metan
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Пт июл 22, 2022 15:37:29
Карма: 6
Рейтинг сообщений: 183
Зарегистрирован: Ср янв 06, 2010 10:01:46Сообщений: 585
Рейтинг сообщения: 0
azerhud писал(а):
DDRC = 0x0F; // Единица младших разрядах, порт настроен как выход, PORTC = 0xFF; // Включаем подтягивающие резисторы
metan писал(а):
И да, вам еще сказали, что младшие линии порта опроса (PORTC) должны быть настроены на вход с подтяжкой. И посмотрите, как у вас.
Dimon456 писал(а):
DDRC = 0x00; PORTC = 0xFF;
Вернуться наверх
azerhud
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Пт июл 22, 2022 18:28:51
Зарегистрирован: Чт июл 21, 2022 15:37:28Сообщений: 31
Рейтинг сообщения: 0
metan ,
Dimon456 , Спасибо. Пытаюсь поставить плюс но мне сообщают что менять карму ещё рано.
Добавлено after 1 hour 9 minutes 44 seconds: Вроде всё получилось благодаря Вам.
Схема проекта.
Код проекта:
Спойлер Код:
#include <mega8.h> #include <delay.h> // Alphanumeric LCD Module functions #asm .equ __lcd_port = 0x18 ; PORTB #endasm #include <lcd.h> char portStateD[4] = {0xEF, 0xDF, 0xBF, 0x7F}; char inputStateC[5] = {0x01, 0x02, 0x04, 0x08, 0x10}; char key; int temp = 0; char mass2[4][5] = { {'1', '2', '3', '4', '5'}, {'6', '7', '8', '9', '0'}, {'A', 'B', 'C', 'D', 'E'}, {'F', 'G', 'I', 'K', 'L'} }; //отправка символа по usart`у void USART_SendChar(unsigned char sym) { while(!(UCSRA & (1 << UDRE))); UDR = sym; } interrupt [TIM2_COMP] void timer2_comp_isr(void) { char i, j; for(i = 0; i < 4; i++) { PORTD = portStateD[i]; for(j = 0; j < 5; j++) { if(((PINC & inputStateC[j]) == 0)) { while((PINC & inputStateC[j]) != inputStateC[j]) {}; lcd_putchar(mass2[i][j]); key = (mass2[i][j]); temp = 1; } } } } void main(void) { DDRC = 0x00; PORTC = 0xFF; DDRD = 0xF0; PORTD = 0xFF; //инициализация USART`a UBRRH = 0; UBRRL = 51; //скорость обмена 9600 бод при Fcpu = 8MГц UCSRB = (1 << TXEN); // разр передачи. UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0); //размер слова 8 разрядов ASSR = 0x00; TCCR2 = 0x0F; TCNT2 = 0x00; OCR2 = 0xC3; TIMSK = 0x80; lcd_init(16); PORTB.3=0; #asm("sei") while(1) { //если зафиксировано нажатие, //отправить код кнопки в терминал if ((key) && (temp == 1)) { DDRD |= 1<<2; USART_SendChar(key); temp = 0; delay_ms(200); DDRD &= ~(1<<2); } } }
Если не трудно, проверьте пожалуйста, нет ли ошибок и недочётов.
Вернуться наверх
Dimon456
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Пт июл 22, 2022 20:33:07
Карма: 20
Рейтинг сообщений: 145
Зарегистрирован: Вс дек 25, 2016 08:34:54Сообщений: 1849
Рейтинг сообщения: 0
Начнем наверное, как уже выше подметили, с включения подтягивающих резисторов там где это необходимо
Спойлер Код:
PORTC = 0x0F; DDRC = 0x00; PORTD = 0xF0 | (1<<2) ; DDRD = 0xF0;
Переменная temp должна быть объявлена как volatile, так как изменяется в прерывании, да и не зачем ее int делать, то есть volatile char , если переменная будет принимать значение 0 и 1, то достаточно ее объявить как volatile bit
Код:
volatile bit temp = 0;
Какой смысл проверять key?
Код:
if ((key) && (temp == 1))
Вы с key дальше ни чего не делаете.
Достаточно проверить
Код:
if (temp == 1)
У вас массив mass2 объявлен как тип char, соответственно функция USART_SendChar() должна так же принимать тип char
Код:
void USART_SendChar(char sym)
С MAX487 я не работал, не знаю как правильно, подскажут другие.
Вернуться наверх
azerhud
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Ср июл 27, 2022 15:25:37
Зарегистрирован: Чт июл 21, 2022 15:37:28Сообщений: 31
Рейтинг сообщения: 0
Всё что смог на данный момент:
Спойлер Код:
#include <mega8.h> #include <delay.h> // Alphanumeric LCD Module functions #asm .equ __lcd_port = 0x18 ; PORTB #endasm #include <lcd.h> char portStateD[4] = {0xEF, 0xDF, 0xBF, 0x7F}; char inputStateC[5] = {0x01, 0x02, 0x04, 0x08, 0x10}; char key; volatile bit temp = 0; char mass2[4][5] = { {'1', '2', '3', '4', '5'}, {'6', '7', '8', '9', '0'}, {'A', 'B', 'C', 'D', 'E'}, {'F', 'G', 'I', 'K', 'L'} }; //отправка символа по usart`у void USART_SendChar(char sym) { while(!(UCSRA & (1 << UDRE))); UDR = sym; } interrupt [TIM2_COMP] void timer2_comp_isr(void) { char i, j; for(i = 0; i < 4; i++) { PORTD = portStateD[i]; for(j = 0; j < 5; j++) { if(((PINC & inputStateC[j]) == 0)) { while((PINC & inputStateC[j]) != inputStateC[j]) {}; key = (mass2[i][j]); switch(key) { case '1': lcd_puts("TOT"); delay_ms(500); lcd_clear(); break; case '2': lcd_puts("TIM"); delay_ms(500); lcd_clear(); break; case '3': lcd_puts("DAY"); delay_ms(500); lcd_clear(); break; case '4': lcd_puts("MTH"); delay_ms(500); lcd_clear(); break; case '5': lcd_puts("RES"); delay_ms(500); lcd_clear(); break; case '6': lcd_puts("COU"); delay_ms(500); lcd_clear(); break; case '7': lcd_puts("1"); break; case '8': lcd_puts("4"); break; case '9': lcd_puts("7"); break; case '0': lcd_puts("*"); delay_ms(500); lcd_clear(); break; case 'A': lcd_puts("<"); delay_ms(500); lcd_clear(); break; case 'B': lcd_puts("2"); break; case 'C': lcd_puts("5"); break; case 'D': lcd_puts("8"); break; case 'E': lcd_puts("0"); break; case 'F': lcd_puts(">"); delay_ms(500); lcd_clear(); break; case 'G': lcd_puts("3"); break; case 'I': lcd_puts("6"); break; case 'K': lcd_puts("9"); break; case 'L': lcd_puts(" OK"); break; } temp = 1; } } } } void main(void) { PORTC = 0x0F; DDRC = 0x00; PORTD = 0xF0 | (1 << 2) ; DDRD = 0xF0; //инициализация USART`a UBRRH = 0; UBRRL = 51; //скорость обмена 9600 бод при Fcpu = 8MГц UCSRB = (1<<RXEN) | (1<<TXEN); // разр приём и передачи. UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0); //размер слова 8 разрядов ASSR = 0x00; TCCR2 = 0x0F; TCNT2 = 0x00; OCR2 = 0xC3; TIMSK = 0x80; lcd_init(16); PORTB.3 = 0; #asm("sei") while(1) { //если зафиксировано нажатие, //отправить код кнопки в терминал if(temp == 1) { DDRD |= 1 << 2; USART_SendChar(key); temp = 0; delay_ms(200); DDRD &= ~(1 << 2); if((key == '5') || (key == 'L')) { delay_ms(500); lcd_clear(); } } } }
Вернуться наверх
Martian
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Ср июл 27, 2022 23:41:12
Карма: 68
Рейтинг сообщений: 1958
Зарегистрирован: Сб дек 18, 2021 19:25:32Сообщений: 12867
Рейтинг сообщения: 0
for(j = 0; j < 5; j++) можно переписать так, что inputStateC станет лишним, а значит, и тройное обращение к нему в условиях - тоже.
Вернуться наверх
metan
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Чт июл 28, 2022 09:08:37
Карма: 6
Рейтинг сообщений: 183
Зарегистрирован: Ср янв 06, 2010 10:01:46Сообщений: 585
Рейтинг сообщения: 3
Martian писал(а):
for(j = 0; j < 5; j++) можно переписать
Это конечно, так, но это пустяки по сравнению с конскими задержками внутри прерывания, как мне кажется
Я бы перенес проверку значения key внутрь главного цикла.
Вернуться наверх
azerhud
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Сб июл 30, 2022 18:58:45
Зарегистрирован: Чт июл 21, 2022 15:37:28Сообщений: 31
Рейтинг сообщения: 0
Пока только так смог:
Спойлер Код:
interrupt [TIM2_COMP] void timer2_comp_isr(void) { char i, j; for(i = 0; i < 4; i++) { PORTD = portStateD[i]; for(j = 0; j < 5; j++) { if(((PINC & inputStateC[j]) == 0)) { while((PINC & inputStateC[j]) != inputStateC[j]) {}; key = (mass2[i][j]); switch(key) { case '1': lcd_clear(); lcd_puts("TOT"); break; case '2': lcd_clear(); lcd_puts("TIM"); break; case '3': lcd_clear(); lcd_puts("DAY"); break; case '4': lcd_clear(); lcd_puts("MTH"); break; case '5': lcd_clear(); lcd_puts("RES"); break; case '6': lcd_clear(); lcd_puts("COU"); break; case '7': lcd_puts("1"); break; case '8': lcd_puts("4"); break; case '9': lcd_puts("7"); break; case '0': lcd_puts("*"); break; case 'A': lcd_puts("<"); break; case 'B': lcd_puts("2"); break; case 'C': lcd_puts("5"); break; case 'D': lcd_puts("8"); break; case 'E': lcd_puts("0"); break; case 'F': lcd_puts(">"); break; case 'G': lcd_puts("3"); break; case 'I': lcd_puts("6"); break; case 'K': lcd_puts("9"); break; case 'L': lcd_clear(); lcd_puts(" OK"); break; } temp = 1; } } } }
Вернуться наверх
Dimon456
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Чт авг 04, 2022 10:08:49
Карма: 20
Рейтинг сообщений: 145
Зарегистрирован: Вс дек 25, 2016 08:34:54Сообщений: 1849
Рейтинг сообщения: 0
azerhud , вот такой код, поиграйся
Спойлер Код:
#include <mega8.h> #include <delay.h> // Alphanumeric LCD Module functions #asm .equ __lcd_port = 0x18 ; PORTB #endasm #include <lcd.h> char portStateD[4] = {0xEF, 0xDF, 0xBF, 0x7F}; char inputStateC[4] = {0x01, 0x02, 0x04, 0x08}; char mass2[4][4] = {{'1', '2', '3', '4'}, {'5', '6', '7', '8'}, {'9', 'A', 'B', 'C'}, {'D', 'E', 'F', 'D'} }; //отправка символа по usart`у void USART_SendChar(char sym) { while(!(UCSRA & (1 << UDRE))); UDR = sym; } #include <string.h> #define MAX_DMA_BUFFERS_COUNT 16 // 4 8 16 32 64 128 #define BUFFER_MASK (MAX_DMA_BUFFERS_COUNT-1) volatile unsigned char BUFF_RX_BUF[MAX_DMA_BUFFERS_COUNT]={0}; volatile unsigned char DMA_WR_BUF = 0; volatile unsigned char DMA_RD_BUF = 0; // Timer 2 output compare interrupt service routine interrupt [TIM2_COMP] void timer2_comp_isr(void) { char key; char i,j; for(i=0; i<4; i++) { PORTD=portStateD[i]; for(j=0; j<4; j++) { if(((PINC&inputStateC[j])==0)) { while((PINC&inputStateC[j])!=inputStateC[j]){}; key = (mass2[i][j]); DMA_WR_BUF++; DMA_WR_BUF &= BUFFER_MASK; BUFF_RX_BUF[DMA_WR_BUF] = key; } } } } void main(void) { char key_x; PORTC = 0x0F; DDRC = 0x00; PORTD = 0xF0 | (1 << 2) ; DDRD = 0xF0; //инициализация USART`a UBRRH = 0; UBRRL = 51; //скорость обмена 9600 бод при Fcpu = 8MГц UCSRB = (1<<RXEN) | (1<<TXEN); // разр приём и передачи. UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0); //размер слова 8 разрядов ASSR = 0x00; TCCR2 = 0x0F; TCNT2 = 0x00; OCR2 = 0xC3; TIMSK = 0x80; lcd_init(16); PORTB.3 = 0; #asm("sei") while(1) { //если зафиксировано нажатие while (DMA_RD_BUF != DMA_WR_BUF) { DMA_RD_BUF++; DMA_RD_BUF &= BUFFER_MASK; key_x = BUFF_RX_BUF[DMA_RD_BUF]; switch(key_x) { case '1': lcd_puts("TOT"); delay_ms(500); lcd_clear(); break; case '2': lcd_puts("TIM"); delay_ms(500); lcd_clear(); break; case '3': lcd_puts("DAY"); delay_ms(500); lcd_clear(); break; case '4': lcd_puts("MTH"); delay_ms(500); lcd_clear(); break; case '5': lcd_puts("RES"); delay_ms(500); lcd_clear(); break; case '6': lcd_puts("COU"); delay_ms(500); lcd_clear(); break; case '7': lcd_puts("1"); break; case '8': lcd_puts("4"); break; case '9': lcd_puts("7"); break; case '0': lcd_puts("*"); delay_ms(500); lcd_clear(); break; case 'A': lcd_puts("<"); delay_ms(500); lcd_clear(); break; case 'B': lcd_puts("2"); break; case 'C': lcd_puts("5"); break; case 'D': lcd_puts("8"); break; case 'E': lcd_puts("0"); break; case 'F': lcd_puts(">"); delay_ms(500); lcd_clear(); break; case 'G': lcd_puts("3"); break; case 'I': lcd_puts("6"); break; case 'K': lcd_puts("9"); break; case 'L': lcd_puts(" OK"); break; } DDRD |= 1 << 2; USART_SendChar(key_x); delay_ms(200); DDRD &= ~(1 << 2); if((key_x == '5') || (key_x == 'L')) { delay_ms(500); lcd_clear(); } } }; }
Вернуться наверх
azerhud
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Пт авг 12, 2022 20:59:32
Зарегистрирован: Чт июл 21, 2022 15:37:28Сообщений: 31
Рейтинг сообщения: 0
вот такой код, поиграйся
Спасибо. Применил Ваш код.
Но боюсь вновь намудрил.
Спойлер Код:
//*** Пример работы с USART интерфейсом микроконтроллеров AVR *** #include <avr/io.h> #include <avr/interrupt.h> #define BAUDRATE 9600 // Скорость обмена данными #define F_CPU 8000000UL // Рабочая частота контроллера #define PAUSE PAUSE_ms(100); #include <string.h> #define MAX_DMA_BUFFERS_COUNT 16 // 4 8 16 32 64 128 #define BUFFER_MASK (MAX_DMA_BUFFERS_COUNT-1) volatile unsigned char BUFF_RX_BUF[MAX_DMA_BUFFERS_COUNT] = {0}; volatile unsigned char DMA_WR_BUF = 0; volatile unsigned char DMA_RD_BUF = 0; unsigned char NUM = 0; unsigned char count = 0; unsigned char byte_receive = 0; unsigned char i = 1; char portStateD[4] = {0xEF, 0xDF, 0xBF, 0x7F}; char inputStateC[5] = {0x01, 0x02, 0x04, 0x08, 0x10}; char key; volatile int temp = 0; char mass2[4][5] = { {'1', '2', '3', '4', '5'}, {'6', '7', '8', '9', '0'}, {'A', 'B', 'C', 'D', 'E'}, {'F', 'G', 'I', 'K', 'L'} }; // Функция задержки в мкс void PAUSE_us(unsigned char time_us) { register unsigned char i; for(i = 0; i < time_us; i++) { asm volatile(" PUSH R0 "); asm volatile(" POP R0 "); } } // Функция задержки в мс void PAUSE_ms(unsigned int time_ms) { register unsigned int i; for(i = 0; i < time_ms; i++) { PAUSE_us(250); PAUSE_us(250); PAUSE_us(250); PAUSE_us(250); } } #define RS PB2 #define EN PB3 // Функция передачи команды void lcd_com(unsigned char p) { PORTB &= ~(1 << RS); // RS = 0 (запись команд) PORTB |= (1 << EN); // EN = 1 (начало записи команды в LCD) PORTB &= 0x0F; PORTB |= (p & 0xF0); // старший нибл PAUSE_us(100); PORTB &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) PAUSE_us(100); PORTB |= (1 << EN); // EN = 1 (начало записи команды в LCD) PORTB &= 0x0F; PORTB |= (p << 4); // младший нибл PAUSE_us(100); PORTB &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) PAUSE_us(100); } // Функция передачи данных void lcd_data(unsigned char p) { PORTB |= (1 << RS) | (1 << EN); // RS = 1 (запись данных), EN - 1 (начало записи команды в LCD) PORTB &= 0x0F; PORTB |= (p & 0xF0); // старший нибл PAUSE_us(100); PORTB &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) PAUSE_us(100); PORTB |= (1 << EN); // EN = 1 (начало записи команды в LCD) PORTB &= 0x0F; PORTB |= (p << 4); // младший нибл PAUSE_us(100); PORTB &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) PAUSE_us(100); } // Функция инициализации LCD void lcd_init(void) { PAUSE_ms(50); // Ожидание готовности ЖК-модуля // Конфигурирование четырехразрядного режима PORTB |= (1 << PB5); PORTB &= ~(1 << PB4); // Активизация четырехразрядного режима PORTB |= (1 << EN); PORTB &= ~(1 << EN); PAUSE_ms(5); lcd_com(0x28); // шина 4 бит, LCD - 2 строки lcd_com(0x08); // полное выключение дисплея lcd_com(0x01); // очистка дисплея PAUSE_us(100); lcd_com(0x06); // сдвиг курсора вправо lcd_com(0x0C); // включение дисплея, курсор не видим } // Функция вывода строки на LCD void lcd_string(unsigned char command, char *string) { lcd_com(0x0C); lcd_com(command); while(*string != '\0') { lcd_data(*string); string++; } } // Функция передачи данных по USART void uart_send(char data) { while(!( UCSRA & (1 << UDRE))); // Ожидаем когда очистится буфер передачи UDR = data; // Помещаем данные в буфер, начинаем передачу } // Функция передачи строки по USART void str_uart_send(char *string) { while(*string != '\0') { uart_send(*string); string++; } } // Функция приема данных по USART int uart_receive(void) { while(!(UCSRA & (1 << RXC))); // Ожидаем, когда данные будут получены return UDR; // Читаем данные из буфера и возвращаем их при выходе из подпрограммы } // Функция инициализации USART void uart_init(void) { // Параметры соединения: 8 бит данные, 1 стоповый бит, нет контроля четности // USART Приемник: Включен // USART Передатчик: Включен // USART Режим: Асинхронный // USART Скорость обмена: 9600 UBRRL = (F_CPU / BAUDRATE / 16 - 1); // Вычисляем скорость обмена данными UBRRH = (F_CPU / BAUDRATE / 16 - 1) >> 8; UCSRB |= (1 << RXCIE) | // Разрешаем прерывание по завершению приема данных (1 << RXEN) | (1 << TXEN); // Включаем приемник и передатчик UCSRC |= (1 << URSEL) | // Для доступа к регистру UCSRC выставляем бит URSEL (1 << UCSZ1) | (1 << UCSZ0); // Размер посылки в кадре 8 бит } // Прерывание по окончанию приема данных по USART ISR(USART_RXC_vect) { NUM = UDR; // Принимаем символ по USART byte_receive = 1; uart_send(NUM); // Посылаем символ по USART } ISR(TIMER2_COMP_vect) { char key; int i, j; for(i = 0; i < 4; i++) { PORTD = portStateD[i]; for(j = 0; j < 5; j++) { if(((PINC & inputStateC[j]) == 0)) { while((PINC & inputStateC[j]) != inputStateC[j]) {}; key = (mass2[i][j]); DMA_WR_BUF++; DMA_WR_BUF &= BUFFER_MASK; BUFF_RX_BUF[DMA_WR_BUF] = key; } } } temp = 1; } // Главная функция int main(void) { char key_x; PORTC = 0x1F; DDRC = 0x00; PORTD = 0xF0 | (1 << 2) ; DDRD = 0xF0; DDRB = 0b11111110; PORTB = 0x00; ASSR = 0x00; TCCR2 = 0x0F; TCNT2 = 0x00; OCR2 = 0xC3; TIMSK = 0x80; lcd_init(); // Инициализация LCD uart_init(); // Инициализация USART sei(); // Глобально разрешаем прерывания str_uart_send("Initialization system\r\n"); // Передаем строку по USART lcd_string(0x80, " AVR USART TEST "); // Выводим строку на LCD PAUSE_ms(2500); lcd_com(0x01); // Очищаем LCD while(1) { while (DMA_RD_BUF != DMA_WR_BUF) { DMA_RD_BUF++; DMA_RD_BUF &= BUFFER_MASK; key_x = BUFF_RX_BUF[DMA_RD_BUF]; switch(key_x) { case '1': str_uart_send( "1"); lcd_string(0x80, "TOT"); PAUSE_ms(500); lcd_com(0x01); break; case '2': str_uart_send( "2"); lcd_string(0x80, "TIM"); PAUSE_ms(500); lcd_com(0x01); break; case '3': str_uart_send( "3"); lcd_string(0x80, "DAY"); PAUSE_ms(500); lcd_com(0x01); break; case '4': str_uart_send( "4"); lcd_string(0x80, "MTH"); PAUSE_ms(500); lcd_com(0x01); break; case '5': str_uart_send( "5"); lcd_string(0x80, "RES"); PAUSE_ms(500); lcd_com(0x01); break; case '6': str_uart_send( "6"); lcd_string(0x80, "COU"); PAUSE_ms(500); lcd_com(0x01); break; case '7': str_uart_send( "7"); lcd_string(0x80, "1"); PAUSE_ms(500); break; case '8': str_uart_send( "8"); lcd_string(0x80, "4"); PAUSE_ms(500); break; case '9': str_uart_send( "9"); lcd_string(0x80, "7"); PAUSE_ms(500); break; case '0': str_uart_send( "0"); lcd_string(0x80, "*"); PAUSE_ms(500); PAUSE_ms(500); lcd_com(0x01); break; case 'A': str_uart_send( "A"); lcd_string(0x80, "<"); PAUSE_ms(500); PAUSE_ms(500); lcd_com(0x01); break; case 'B': str_uart_send( "B"); lcd_string(0x80, "2"); PAUSE_ms(500); break; case 'C': str_uart_send( "C"); lcd_string(0x80, "5"); PAUSE_ms(500); break; case 'D': str_uart_send( "D"); lcd_string(0x80, "8"); PAUSE_ms(500); break; case 'E': str_uart_send( "E"); lcd_string(0x80, "0"); PAUSE_ms(500); break; case 'F': str_uart_send( "F"); lcd_string(0x80, ">"); PAUSE_ms(500); PAUSE_ms(500); lcd_com(0x01); break; case 'G': str_uart_send( "G"); lcd_string(0x80, "3"); PAUSE_ms(500); break; case 'I': str_uart_send( "I"); lcd_string(0x80, "6"); PAUSE_ms(500); break; case 'K': str_uart_send( "K"); lcd_string(0x80, "9"); PAUSE_ms(500); break; case 'L': str_uart_send( "L"); lcd_string(0x80, " OK"); PAUSE_ms(500); PAUSE_ms(500); lcd_com(0x01); break; } if(byte_receive) { byte_receive = 0; count++; //USART_SendChar(key_x); lcd_data(NUM); // Выводим символ на LCD if(count > 16) // Если строка заполнена { count = 0; lcd_com(0x01); // Очищаем LCD } } } } }
Вернуться наверх
Dimon456
Заголовок сообщения: Re: Опрос матричной клавиатуры.
Добавлено: Пт авг 12, 2022 21:56:00
Карма: 20
Рейтинг сообщений: 145
Зарегистрирован: Вс дек 25, 2016 08:34:54Сообщений: 1849
Рейтинг сообщения: 0
azerhud писал(а):
Но боюсь вновь намудрил.
Да уж, намудрили так намудрили.
Особенно Функцию задержки, откуда вы это только берете?
У avr-gcc и так нормальный delay.
Вернуться наверх
Страница 1 из 1
[ Сообщений: 20 ]
Кто сейчас на форуме
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения