лениво делаю простой терминал с "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 штук), чтобы не попалить контроллер при "неудачном" нажании двух кнопок вместе.
Они обозначены как :
/* | | | | | d d d d d 1 2 3 4 5 | | | | | +==================+==+==+==+==+====+ */String enter() - а функция ничего не возвращает, ворнинги компилятора Arduino IDE благополучно от нас прячет :(
ворнинги компилятора Arduino IDE благополучно от нас прячет :(
Дабы не смущать ранимые души "навечков" - меньше знаешь - крепче спишь.
изначально она возвращала буффер, потом мутировала, но остались артефакты. Спасибо.
Я же говорю - лениво делаю. Вылизывать буду на очередной волне прилива творческой энергии. ;-)
Кстати, в схеме в верхней части клавиатуры стоят диоды (5 штук), чтобы не попалить контроллер при "неудачном" нажании двух кнопок вместе.
если инициировать пин как OUTPUT во время опроса матрицы и сбрасывать в INPUT после опроса, то хоть все пины скрути вместе, ничего ужасного не случится - у тебя всегда только ОДИН пин матрицы будет в небезопасном состоянии.
Уважаемый Клапауций 888, мне кажется, что при считывании нужно четко выставлять 0 или 1 на сканирующей группе портов. А если про нажатии двух кнопок пин с 0 окажется соединенным с пином с 1, то бюудет что-то типа КЗ с увеличением протекающего тока и перегрузкой и потенциальным выходом из строя входных-выходных цепей пинов.
Может я не прав, на истину не претедую.
Уважаемый Клапауций 888, мне кажется, что при считывании нужно четко выставлять 0 или 1 на сканирующей группе портов. А если про нажатии двух кнопок пин с 0 окажется соединенным с пином с 1, то бюудет что-то типа КЗ с увеличением протекающего тока и перегрузкой и потенциальным выходом из строя входных-выходных цепей пинов.
а, зачем на всей группе? - достаточно на одном пине и относительно этого пина считываешь состояния перпендикулярных... что там у тебя - строк или колонок, настроенных на инпут.
*не, ну можно, если есть сомнения - взять три пина: один настроить на выход, а два на вход и позамерять между ними ток мультиметром, замыкая их в разных комбинациях и все в куче.
Анахронизм какой-то.) Может PS/2? Есть маленькие, аккуратненькие. И нажимать приятно, не?)