лениво делаю простой терминал с "spectrum like" клавиатурой на atmega8
- Войдите на сайт для отправки комментариев
Ср, 06/12/2017 - 13:50
Приветствую. Вот, может кому пригодится:
В очередной раз накатило вдохновение, разобрал нафик что делал раньше и присобачил готовую клавиатуру к atmega8. Туда-же прицепил двустрочный дисплей. Потенциально это будет калькулятор, но пока просто читает цифры и пишет их на екран.
никакой оптимизации и борьбы с дребезгом пока. чтение клавиатуры через таймер. Программа забирает из буффкра, если что есть и чистит этот буффер.
раскладка спектрумовская алфавитно-цифровая. шифты не сделаны пока. Мега работает на внутреннем генераторе 1Мгц (ну или 8 - я еще не определился, что важнее : экономичность или скорость).
#include <Wire.h> #include <LiquidCrystal_PCF8574.h> LiquidCrystal_PCF8574 lcd(0x27); /* (c0,c1,c2,c3) + (d4,d5,d6,d7) (b1,b2,b3,b4,b5) #define NUM_ROWS 8 #define NUM_COLS 5 byte rowPins[NUM_ROWS] = {A0, A1, A2, A3, 4, 5, 6, 7}; //connect to the row pinouts of the keypad byte colPins[NUM_COLS] = { 9, 10, 11, 12, 13}; //connect to the column pinouts of the keypad В данном скетче сканирование идет по столбцам, то есть на них подается сигнал, а снимается со строк. Значит диоды ставятся на пины, подключенные к столбцам, чтобы исключить КЗ между столбцами с выставленным 0 и 1, а резисторы ограничивают ток на читающих пинах. D9 D10 D11 D12 D13 | | | | | d d d d d 1 2 3 4 5 | | | | | +==================+==+==+==+==+====+ R1 _ | . | | | | | | _ r8 A0 ----|_|----+--1--2--3--4--5 . 6--7--8--9--0----+--|_|--- D4 r2 _ | | | | | | . | | | | | | _ r7 A1 ----|_|----+--Q--W--E--R--T . Y--U--I--O--P----+--|_|--- D5 r3 _ | | | | | | . | | | | | | _ r6 A2 ----|_|----+--A--S--D--F--G . H--J--K--L--ENTER+--|_|--- D6 r4 _ | | | | | | . | | | | | | _ r5 A3 ----|_|----+--^--Z--X--C--V . B--N--M--#--' '--+--|_|--- D7 +==+==+==+==+==+===+==+==+==+==+====+ | | | | |___| | | | | | | | |_________| | | | | | |_______________| | | | |_____________________| | |___________________________| ____ ____ | U | _______________________ reset----|1 28|--A5--scl+ LCD 16x2 | rx-------|2 27|--A4--sda+______________________| tx-------|3 26|-------------------K1-строки int0---|4 a 25|-------------------K1-левой int1---|5 t 24|-------------------K1-половины строки K2-------|6 m 23|-------------------K1-клавиатуры vcc-|7 e 22|-gnd gnd-|8 g 21|- x0-|9 a 20|-vcc x1-|10 8 19|---------K3 сканирование столбцов левой K2-------|11 18|---------K3 матрицы половины K2-------|12 17|---------K3 клавиатуры K2-------|13 16|---------K3 -|14 15|---------K3 |_______| */ /* пока используем atmega8 команды типа ПП-БП - параметр из двух цифр длина команды 2 байта - код команды и адрес перехода команды типа X-П - второе нажатие - параметр - номер регистра клавиатура на основе mk52 F ШГ> П->X 7 8 9 - / K ШГ< X->П 4 5 6 + || В/О БП 1 2 3 <-> В| А| С/П ПП 0 . /-/ ВП Cx */ void setup() { // Serial.begin(9600); // pinMode(8, OUTPUT); /* or use: DDRB = DDRB | B00000001; // this sets pin8 as output without changing the value of the other pins */ DDRB = DDRB | 0B00111111; // инициализировать клавиатуру - выход - сканируюшие контакты PORTB = 0x00;//низкий уровень на всем B delay(10); DDRC = DDRC & ~(0B11110000); // вход PORTC = 0xFF; delay(10); DDRD = DDRD & ~(0b00001111); // вход PORTD = 0xFF; delay(10); delay(10); cli(); // Set the registers TCCR1A = 0; //Timer Counter Control register // Set mode TCCR1B = (1 << WGM12); // turn on CTC mode // Set prescale values (1024). (Could be done in same statement // as setting the WGM12 bit.) TCCR1B |= (1 << CS12) | (1 << CS10); //Enable timer compare interrupt===> TIMSK1 for ATmega328, //TIMSK for ATmega8 TIMSK |= (1 << OCIE1A); // Set OCR1A //OCR1A = 15624; OCR1A = 1562; sei(); // Enable global interrupts lcd.begin(16, 2); lcd.clear(); lcd.setCursor(0, 0); lcd.setBacklight(255); Serial.begin(9600); } ISR (TIMER1_COMPA_vect) { cli(); kb_scan(); sei(); dispX(); } int cnt = 0; //stack. длина чисел 16 знаков (включая знак - и запятую) static String x1= " "; static String x = " "; static String y = " "; static String z = " "; static String t = " "; char sgCH = 0x0B; // команда смены знака #define KEY_ENTER 13 #define KEY_BRK '#' #define SYMBOL_SHIFT 1 #define CAPS_SHIFT 2 // Keyboard #define ROWS 8 #define COLS 5 char a[ROWS][COLS] = { {'5', '4', '3', '2', '1'}, {'T', 'R', 'E', 'W', 'Q'}, {'G', 'F', 'D', 'S', 'A'}, {'V', 'C', 'X', 'Z', CAPS_SHIFT}, {'6', '7', '8', '9', '0'}, {'Y', 'U', 'I', 'O', 'P'}, {'H', 'J', 'K', 'L', KEY_ENTER}, {'B', 'N', 'M', SYMBOL_SHIFT, ' '} }; int i = 0; int j = 0; char keyPressed = 0; char keycode = 0; void kb_scan() { for (i = 0; i < 5; i++) //колонки - столбцы { PORTB &= ~(1 << i + 1); //начиная со второго бита delay (20); for (j = 0; j < 4; j++) // у нас 2 блока по 4 строки { if (!(PINC & (1 << j))) // старшие разряды регистра С { keyPressed = a[j][i]; //Serial.println(cnt++); Serial.print(i); Serial.print(" - "); Serial.print(j); Serial.println(" ");Serial.println(keyPressed); } else if (!(PIND & (1 << j + 4))) //младшие разряды Д { keyPressed = a[j + 4][i]; //Serial.println(cnt++); Serial.print(i); Serial.print(" = "); Serial.print(j); Serial.println(" "); Serial.println(keyPressed); } else if (keyPressed != 0) { keycode = keyPressed; PORTB ^= (1 << 0); // индикация, что не висим - мигаем keyPressed = 0; } } PORTB |= (1 << i + 1); delay(10); } } void loop() { enter(); Serial.println(x); } void dispX() { lcd.setCursor(0, 0); // lcd.print(x); lcd.setCursor(0, 1); // lcd.print(x1); } String enter() { char curDigit; static uint8_t curPos = 0; if (keycode != 0) { //key pressed curDigit = keycode; if ((curDigit >= '0' && curDigit <= '9') || curDigit == '.' ) { if (curPos < 15) { x[curPos++] = curDigit; } } else if ( curDigit == sgCH ) { if (x[15] == '-')x[15] = ' '; else x[15] = '-'; } keycode = 0; } }
Кстати, в схеме в верхней части клавиатуры стоят диоды (5 штук), чтобы не попалить контроллер при "неудачном" нажании двух кнопок вместе.
Они обозначены как :
String enter() - а функция ничего не возвращает, ворнинги компилятора Arduino IDE благополучно от нас прячет :(
ворнинги компилятора Arduino IDE благополучно от нас прячет :(
Дабы не смущать ранимые души "навечков" - меньше знаешь - крепче спишь.
изначально она возвращала буффер, потом мутировала, но остались артефакты. Спасибо.
Я же говорю - лениво делаю. Вылизывать буду на очередной волне прилива творческой энергии. ;-)
Кстати, в схеме в верхней части клавиатуры стоят диоды (5 штук), чтобы не попалить контроллер при "неудачном" нажании двух кнопок вместе.
если инициировать пин как OUTPUT во время опроса матрицы и сбрасывать в INPUT после опроса, то хоть все пины скрути вместе, ничего ужасного не случится - у тебя всегда только ОДИН пин матрицы будет в небезопасном состоянии.
Уважаемый Клапауций 888, мне кажется, что при считывании нужно четко выставлять 0 или 1 на сканирующей группе портов. А если про нажатии двух кнопок пин с 0 окажется соединенным с пином с 1, то бюудет что-то типа КЗ с увеличением протекающего тока и перегрузкой и потенциальным выходом из строя входных-выходных цепей пинов.
Может я не прав, на истину не претедую.
Уважаемый Клапауций 888, мне кажется, что при считывании нужно четко выставлять 0 или 1 на сканирующей группе портов. А если про нажатии двух кнопок пин с 0 окажется соединенным с пином с 1, то бюудет что-то типа КЗ с увеличением протекающего тока и перегрузкой и потенциальным выходом из строя входных-выходных цепей пинов.
а, зачем на всей группе? - достаточно на одном пине и относительно этого пина считываешь состояния перпендикулярных... что там у тебя - строк или колонок, настроенных на инпут.
*не, ну можно, если есть сомнения - взять три пина: один настроить на выход, а два на вход и позамерять между ними ток мультиметром, замыкая их в разных комбинациях и все в куче.
Анахронизм какой-то.) Может PS/2? Есть маленькие, аккуратненькие. И нажимать приятно, не?)