лениво делаю простой терминал с "spectrum like" клавиатурой на atmega8

doleynikov
Offline
Зарегистрирован: 30.01.2015

Приветствую. Вот, может кому пригодится: 

В очередной раз накатило вдохновение, разобрал нафик что делал раньше и присобачил готовую клавиатуру к 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;
  }
}

 

doleynikov
Offline
Зарегистрирован: 30.01.2015

Кстати, в схеме в верхней части клавиатуры стоят диоды (5 штук), чтобы не попалить контроллер при "неудачном" нажании двух кнопок вместе.

Они обозначены как :       

/*   
                                      |  |  |  |  |
                                      d  d  d  d  d
                                      1  2  3  4  5
                                      |  |  |  |  |
                   +==================+==+==+==+==+====+
 */

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

String enter() - а функция ничего не возвращает, ворнинги компилятора Arduino IDE благополучно от нас прячет :(

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DIYMan пишет:

ворнинги компилятора Arduino IDE благополучно от нас прячет :(

Дабы не смущать ранимые души "навечков" - меньше знаешь - крепче спишь.

doleynikov
Offline
Зарегистрирован: 30.01.2015

изначально она возвращала буффер, потом мутировала, но остались артефакты. Спасибо.

Я же говорю - лениво делаю. Вылизывать буду на очередной волне прилива творческой энергии. ;-)

Клапауций 888
Клапауций 888 аватар
Offline
Зарегистрирован: 05.12.2017

doleynikov пишет:

Кстати, в схеме в верхней части клавиатуры стоят диоды (5 штук), чтобы не попалить контроллер при "неудачном" нажании двух кнопок вместе.

если инициировать пин как OUTPUT во время опроса матрицы и сбрасывать в INPUT после опроса, то хоть все пины скрути вместе, ничего ужасного не случится - у тебя всегда только ОДИН пин матрицы будет в небезопасном состоянии.

doleynikov
Offline
Зарегистрирован: 30.01.2015

Уважаемый Клапауций 888, мне кажется, что при считывании нужно четко выставлять 0 или 1 на сканирующей группе портов. А если про нажатии двух кнопок пин с 0 окажется соединенным с пином с 1, то бюудет что-то типа КЗ с увеличением протекающего тока и перегрузкой и потенциальным выходом из строя входных-выходных цепей пинов.

Может я не прав, на истину не претедую.

Клапауций 888
Клапауций 888 аватар
Offline
Зарегистрирован: 05.12.2017

doleynikov пишет:

Уважаемый Клапауций 888, мне кажется, что при считывании нужно четко выставлять 0 или 1 на сканирующей группе портов. А если про нажатии двух кнопок пин с 0 окажется соединенным с пином с 1, то бюудет что-то типа КЗ с увеличением протекающего тока и перегрузкой и потенциальным выходом из строя входных-выходных цепей пинов.

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

*не, ну можно, если есть сомнения - взять три пина: один настроить на выход, а два на вход и позамерять между ними ток мультиметром, замыкая их в разных комбинациях и все в куче.

Green
Онлайн
Зарегистрирован: 01.10.2015

Анахронизм какой-то.) Может PS/2? Есть маленькие, аккуратненькие. И нажимать приятно, не?)