26 июля 2015 г.

Как работать с PS/2 интерфейсом, клавиатура и мышь

Зачем кому-то нужен PS/2 интерфейс? Может вы задумали сделать проект, где необходимо вводить целые слова, в таком случае парой кнопкой не обойдешься, а собирать матрицу из кнопок не очень увлекательное занятие.

Часто используют старые клавиатуры и мышки ради практики работы на ПЛИС, клавиатуру можно подключить к любому дисплею, чтобы получить терминал. Можно с ней поэкспериментировать просто ради спортивного интереса.



Коннекторы

Есть несколько типов коннекторов для подсоединения клавиатуры и мыши:


Папа

(Штекер)
Мама

(Разъём)
DIN (AT/XT):     
1 - Clock
2 - Data
3 - N/C
4 - GND
5 - Vcc (+5V)

Папа

(Штекер)
Мама

(Разъём)
Mini-DIN (PS/2):
1 - Data
2 - N/C
3 - GND
4 - Vcc (+5V)
5 - Clock
6 - N/C         



6-pin SDL:
A - N/C
B - Data
C - GND
D - Clock
E - Vcc (+5V)
F - N/C                             

Клавиатура потребляет до 300 мА, мышь до 100 мА. Их выводы представляют собой схему открытый коллектор:



Рис.1 Схема выхода микросхемы реализованной на транзисторе с открытым коллектором.
Это позволяет работать с напряжениями отличными от 5В. Но в любом случае необходимо использовать подтягивающий резистор для передачи данных, т.к. транзистор может открыться и выставить лог.0, но он не может подать на выход высокий логический уровень.

В микроконтроллерах можно выставить резистор подтяжки программно, не добавляя лишних элементов. Иначе можно соединить линии Clock и Data с резистором на 10 кОм:



Рис.2 Подключение резистора к выходу с открытым коллектором.

Интерфейс PS/2

Интерфейс PS/2 похож на USART - синхронный UART.  Передача данных происходит по 2 цифровым сигналам: "Clock"и "Data". Clock указывает на наличие нового бита, Data передаёт 1 байт информации в посылке из 11-12 бит:
  • Стартовый бит, всегда 0.
  • 8 бит информации, начиная с младшего разряда.
  • бит проверки чётности (parity).
  • Стоп бит, всегда 1.
  • бит подтверждения, выставляется клавиатурой, всегда 0.
В нашем случае проверяется чётность: количество единиц в байте содержащем информацию + бит чётности всегда будет давать нечётное число. Можно также сказать что бит паритета = 1 если у нас чётное число единиц.
Частота синхроимпульсов может быть в пределах от 10 КГц до 30 КГц. Клавиатура и мышь сами посылают Clock сигналы, нужно лишь успевать на них реагировать.

Есть 3 начальных состояния линий Data и Clock:

  • Data = 1, Clock = 1 - хост ждёт данные от устройства
  • Data = 1, Clock = 0 - хост хочет передать данные устройству
  • Data = 0, Clock = 0 - Передача данных запрещена

Прежде чем начать передать данные устройство ждёт пока линия Clock не будет иметь высокий уровень в течение 50 мкс, после чего оно начинает передавать данные по мере необходимости


Рис.3 Временная диаграмма передачи данных от клавиатуры хосту
Хост может в любое время начать передавать данные, для этого ему необходимо опустить линию Clock до низкого уровня и продержать его там не меньше чем 100 мкс. Если хост прервал передачу данных, то после приёма сообщения наше устройство заново передаст предыдущее сообщение, если его размер не превышает буфер хранения нашего устройства.

После того как продержим clock нужное время, выставляем лог. 0 на Data, выставляем высокий уровень на Clock, Дальше наше PS/2 устройство начинает генерировать синхроимпульсы, во время спада импульсов устройство считывает бит на линии Data. После того как передали старт бит, 8 бит информации и бит паритета, нужно выставить на Data высокий уровень, что соответствует стоп биту, после него устройство должно передать 1 бит подтверждения полученной информации (лог. 0):

Рис.4 Временная диаграмма передачи данных от хоста клавиатуре
С передачей данных могут возникнуть проблемы, я выставлял новый бит данных по переднему фронту синхро сигнала, в этом случае 1 мышь не понимала команду, 2 мышь давала лишь 11 синхро импульсов, она не давала мне передать  стоп бит, но после этого она начинала отвечать мне 3 байтами данных о положении мыши. Когда я менял бит по заднему фронту, обе мыши не могли понять команду. Когда мышь сама передаёт данные шина данных меняется между синхроимпульсами. Не знаю почему у меня возникли такие трудности, возможно не поладки мыши, либо у разных производителей передача реализована по разному. Лучше всего посмотреть как мышь передаёт данные и попытаться его повторить.

На осцилограммах видно что шина данных меняется перед зандним фронтом синхросигнала.

Клавиатура

Как и с мышкой общаться можно в 2 направлениях: хост -> клавиатура, клавиатура -> хост. При подключении питания с клавиатурой уже можно работать, можно обойтись без инициализации. Большинство символов можно передать с помощью 1 байта, F = 0x2B (шестнадцатеричный код). Но для некоторых символов этого не достаточно, к примеру, стрелка вверх обозначает код = 0xE075. Если зажать кнопку, клавиатура периодически будет отсылать её код (Make code). После отпускания кнопки, клавиатура отсылает "Break" код, обозначающий, что кнопку отпустили. Break код это тот же код клавиши, но с добавлением в начало или в середину 1 байта, код F0, Если мы отпустим клавишу F, клавиатура отправит 2 байта = F0, 2B.

Коды букв никак не связаны с ASCII таблицей, интерпретация входящих символов зависит от хоста. Скан коды символов можно посмотреть в таблице, здесь представлен самый распространённый тип (2), на некоторых клавиатурах он может отличаться либо его можно изменить (всего 3 типа).



Рис.5 Скан коды символов на клавиатуре

Рис.6 Скан коды символов на цифровой клавиатуре
Я подключил осциллограф к клавиатуре и нажал "F" = 0x2B = 00101011, мы должны получить:
0 11010100 11 (данные передаются, начиная с младшего разряда)
вот что показал осциллограф:


Рис.7 Полученная осциллограмма нажатой кнопки "F"
Когда мы держим нажатой одну кнопку, она становится "повторяющейся" (typematic), если мы откроем блокнот и нажмём "A", появится 1 буква, затем после некоторой задержки появится поток тех же букв. Задержка между 1 и 2 символом называется задержкой автоповтора (typematic delay) и может меняться от 0.25с до 1с. Количество символов в секунду при автоповторе - частота автоповтора (typematic rate) меняется от 2 до 30 символов в секунду (cps). Эти значения можно настроить.

Помимо символов, клавиатура и хост могут отсылать друг другу особые команды, к примеру, чтобы зажечь светодиоды над цифровой клавиатурой. Вот перечень основных команд:

  • 0xFF (Reset) - клавиатура отвечает "подтверждаю" (ack = 0xFA), затем переходит в состояние "Reset".
  • 0xFE (Resend) - Клавиатура / хост отвечают последним переданным байтом. Если это был "resend" (0xFE), то отправляется байт до этого. 
  • 0xF6 (Set Default) - Загружает стандартные значения частоты и задержки автоповтора (10.9cps / 500мс), все кнопки в стандартном режиме (typematic/make/break), 2 скан код.
  • 0xF5 (Disable) - Клавиатура перестаёт проверять кнопки и загружает параметры по умолчанию (Set Default)
  • 0xF4 (Enable) - Включает клавиатуру после предыдущей команды.
  • 0xEE (Echo) - Клавиатура отвечает тем же "Echo" (0xEE).
  • 0xF2 (Read ID) - Клавиатура отвечает, посылая 2 байта ID устройства 0xAB, 0x83.
  • 0xF0 (Set Scan Code Set) -  Клавиатура отвечает подтверждением (ack = 0xFA), затем считывает следующий байт параметра, посланный хостом. Параметр может быть 0x01, 0x02 или 0x03, чтобы выставить 1, 2 или 3, скан коды, после чего клавиатура ответит "ack". Если отправить 0x00, клавиатура оставит текущий скан код, передаст подтверждение (ack = 0xFA) и отмравит номер используемого скан кода.
следующие команды, работают только когда выставлен 3 скан код:
  • 0xFD (Set Key Type Make) - Отключить "break" коды (отпускания кнопки) и автоповторение для выбранных клавиш. Клавиатура отправляет подтверждение (0xFA), отключает проверку нажатия и считывает список клавиш от хоста. Кнопки отправляются их "make" кодом 3 скан кода. Клавиатура каждый раз отвечает подтверждением. Для того чтобы прекратить передачу, хост отправляет любую другую команду. После чего клавиатура включает проверку нажатия. 
  • 0xFC (Set Key Type Make/Break) - Похожа на предыдущую команду, но отключает только автоповтор.
  • 0xFB (Set Key Type Typematic) - Похожа на предыдущие команды, но отключает только "break" код.
  • 0xFA (Set All Keys Typematic/Make/Break) - Клавиатура отвечает подтверждением, возвращает все кнопки в исходное состояние.
  • 0xF9 (Set All Keys Make) - Клавиатура отвечает подтверждением. Похожа на 0xFD, но для всех клавиш.
  • 0xF8 (Set All Keys Make/Break) - Клавиатура отвечает подтверждением. Похожа на 0xFC, но для всех клавиш.
  • 0xF7 (Set All Keys Typematic) - Клавиатура отвечает подтверждением. Похожа на 0xFB, но для всех клавиш.

  • 0xF3 (Set Typematic Rate/Delay) - После этой команды, хост отсылает 1 байт указывающий новые значения частоты (символы в секунду) и задержки автоповтора:
    Частота автоповтора

     Биты 0-4 
     Частота 
     Биты 0-4 
     Частота 
     Биты 0-4 
     Частота 
     Биты 0-4 
     Частота 
    00h
    30.0
    08h
    15.0
    10h
    7.5
    18h
    3.7
    01h
    26.7
    09h
    13.3
    11h
    6.7
    19h
    3.3
    02h
    24.0
    0Ah
    12.0
    12h
    6.0
    1Ah
    3.0
    03h
    21.8
    0Bh
    10.9
    13h
    5.5
    1Bh
    2.7
    04h
    20.7
    0Ch
    10.0
    14h
    5.0
    1Ch
    2.5
    05h
    18.5
    0Dh
    9.2
    15h
    4.6
    1Dh
    2.3
    06h
    17.1
    0Eh
    8.6
    16h
    4.3
    1Eh
    2.1
    07h
    16.0
    0Fh
    8.0
    17h
    4.0
    1Fh
    2.0
    Задержка
    Биты 5-6
    Задержка, с
    00b
    0.25
    01b
    0.50
    10b
    0.75
    11b
    1.00
  • 0xED (Set/Reset LEDs) - После этого следует байт определяющий состояние светодиодов над цифровой клавиатурой (numpad), выставив в нужный бит единицу, мы включим выбранный светодиод:
Старшие биты





Младшие биты
Всегда 0Всегда
0
Всегда
0
Всегда
0
Всегда
0
Caps LockNum LockScroll Lock


Мышь

Изначально в PS/2 мышке было 3 кнопки, затем добавилось колесо и ещё 2 дополнительные кнопки, рассмотрим все виды по порядку. Для хранения значения передвижения по осям X и Y, используются 8-ми битные счётчики. Значение, в которых изменяется в зависимости от движения мыши, счётчики обнуляются после передачи хранящихся в них данных, при переполнении счётчика выставляется соответствующий бит переполнения, поле чего значение счётчика не меняется. Также есть знаковый бит определяющий направление мыши по выбранной оси (влево вправо по х).

По умолчанию разрешение счётчика 4 значения на мм. Его можно изменить, отправив соответствующую команду. Также можно изменить "масштаб" (scaling), это не изменит работу счётчика, но поменяет данные, которые передаются на основании значения счётчика (только в стандартном режиме работы). По умолчанию оно 1:1. Можно изменить на 2:1, в этом случае значение для передачи будет вычисляться следующим образом:


Значение счётчикаПереданное значение
00
11
21
33
46
59
N > 52 * N

Мышь отсылает пакет данных, состоящий из 3 байт:




7 Бит6 Бит5 Бит4 Бит3 Бит2 Бит1 Бит0 Бит
1 Байт
Переполнение по У
Переполнение по Х
Знак оси У
Знак оси Х
Всегда 1
Средняя кнопка
Правая кнопка
Левая кнопка
2 БайтДвижение по оси Х
3 БайтДвижение по оси У


Можно выбрать один из нескольких режимов работы:

  • Reset - режим при включении питания, проводится диагностика и самопроверка.
  • Stream - основной режим работы, мышь отправляет пакет данных при изменении состояний счётчиков или нажатии кнопок.
  • Remote - хост должен запрашивать данные, мышь перестаёт их передавать сама.
  • Wrap - режим диагностики, мышь отвечает хосту тем же полученным пакетом байт (echo).

Режим Reset

Этот режим выставляется при включении питания, либо при запросе от хоста. При этом мышь выставляет следующие параметры:
  • Частота дисктретизации - 100 значений в секунду.
  • Разрешение - 4 значения / мм.
  • Масштаб - 1:1
  • Передача данных - отключено

Частота дискретизации (Data sampling) - означает максимальную частоту, при которой могут передаваться данные от мышки хосту. В этом режиме мышь производит самопроверку, после чего отправляет 0xAA (успех) или 0xFC (ошибка), после чего мышь посылает свой ID = 0x00, что отличает её от клавиатуры. 
После этого мышь переходит в режим Stream.

Рис.8 Полученная осциллограмма от мыши при включении питания

Режим Stream

В этом режиме мышь находится по умолчанию, нужно лишь разрешить передачу данных. Мышь передаёт данные с максимально возможной частотой равной частоте посылки, но только при их изменении.

Режим Remote

В этом случае мышь передаст 1 пакет данных только после запроса от хоста, после чего обнулит показания счётчиков как обычно и будет ждать следующей команды.

Режим Wrap

Здесь, мышь отправляет хосту те же данные, что он послал ей, кроме команд "Reset" и "Reset Wrap Mode"


   Дополнения Intellimouse

У Microsoft Intellimouse появилось 5 кнопок и рабочее колёсико. При включении питания она работает как старая мышь, т.е. не использует свои дополнительные 2 кнопки и колесо, ID = 0x00, посылает 3 байта. Чтобы включить её колёсико, хост посылает следующие команды:
  1. Выставить частоту посылки 200.
  2. Выставить частоту посылки 100.
  3. Выставить частоту посылки  80.

После чего хост запрашивает ID. Если это обычная мышь, она ответит 0x00, как и раньше, но если у этой мышки есть колесо, она ответит 0x03, После чего она будет передавать пакет из 4 байт:

7 Бит6 Бит5 Бит4 Бит3 Бит2 Бит1 Бит0 Бит
1 БайтПереполнение по УПереполнение по ХЗнак оси УЗнак оси ХВсегда 1Средняя кнопкаПравая кнопкаЛевая кнопка
2 БайтДвижение по оси Х
3 БайтДвижение по оси Y
4 БайтДвижение по оси Z

Движение колеса принимается как движение по оси Z, значение меняется от -8 до 7. Используются только младшие 4 бита.


Для того чтобы включить 4-ую и 5-ую кнопки, хост отправляет следующие команды:

  1. Выставить частоту посылки 200.
  2. Выставить частоту посылки 200.
  3. Выставить частоту посылки 80.
После чего хост запрашивает ID, если у мыши имеется 5 кнопок, она отвечает 0x04 и начинает отправлять следующий пакет:

7 Бит6 Бит5 Бит4 Бит3 Бит2 Бит1 Бит0 Бит
1 БайтПереполнение по УПереполнение по ХЗнак оси УЗнак оси ХВсегда 1Средняя кнопкаПравая кнопкаЛевая кнопка
2 БайтДвижение по оси Х
3 БайтДвижение по оси Y
4 БайтВсегда 0Всегда 05 Кнопка4 Кнопка Движение по оси Z

Также существуют мышки с 2 колёсиками, 1 вертикальное и 1 горизонтальное, если использовать вертикальное, всё работает как обычно, счетчик оси Z изменяется на 1 при движении, но если использовать горизонтальное, счётчик оси Z изменяется на 2. Если попытаться их использовать одновременно, то, что произойдёт зависит от драйвера и железа, на компьютере перестаёт восприниматься горизонтальное движение колеса.




Команды

Если мышь в режиме "Stream", хост должен отключить передачу данных (0xF5) перед тем как посылать другие команды. 
  • 0xFF (Reset) - Мышь отвечает подтверждением "acknowledge" ("ack") (0xFA)  и переходит в режим "Reset"
  • 0xFE (Resend) - Эту команду хост отправляет после того как получил от мыши неправильные данные, после чего мышь повторно отправляет предыдущий пакет. Если мышь повторно отправляет неверный пакет, хост может прервать питание мыши, запретить передачу данных либо выставить другой рабочий режим. Команда Resend не хранится в буфере, поэтому мышь не сможет ответь Resend на запрос Resend от хоста.
  • 0xF6 (Set Defaults) - Мышь отвечает "ack" (0xFA). После чего выставляет свои стандартные значения (как при включении питания), обнуляет счётчики и переходит в режим Stream.
  • 0xF5 (Disable Data Reporting) - Мышь отвечает "ack" (0xFA). Отключает передачу данных и обнуляет счетчики, тоже самое что режим "Remote".
  • 0xF4 (Enable Data Reporting) - Мышь отвечает "ack" (0xFA). Включает передачу данных, работает только в "Stream" режиме.
  • 0xF3 (Set Sample Rate) - Мышь отвечает "ack" (0xFA).  затем хост посылает частоту для передачи данных, мышь снова отвечает "ack" и сбрасывает счётчики. Возможные значения: 10, 20, 40, 60, 80, 100, и 200 выборок / с.
  • 0xF2 (Get Device ID) - Мышь отвечает "ack" (0xFA), затем посылает своё ID (0x00 для стандартной PS/2 мыши). Мышь также сбрасывает состояния счётчиков.
  • 0xF0 (Set Remote Mode) - Мышь отвечает "ack" (0xFA), сбрасывает значения счётчиков и переходит в режим "Remote".
  • 0xEE (Set Wrap Mode) - Мышь отвечает "ack" (0xFA), сбрасывает значения счётчиков и переходит в режим "Wrap".
  • 0xEC (Reset Wrap Mode) - Мышь отвечает "ack" (0xFA), сбрасывает значения счётчиков и переходит в режим, в котором она была до "Wrap" режима (Remote или Stream).
  • 0xEB (Read Data) - Мышь отвечает "ack" (0xFA), затем посылает пакет данных с информацией о движении, единственный способ получения данных в режиме Remote. Сбрасываюстся значения счётчиков
  • 0xEA (Set Stream Mode) - Мышь отвечает "ack" (0xFA), сбрасывает значения счётчиков и переходит в режим "Remote".
  • 0xE9 (Status Request) - Мышь отвечает "ack" (0xFA), посылает следующий пакет и сбрасывает состояния счётчиков:
7 Бит6 Бит5 Бит4 Бит3 Бит2 Бит1 Бит0 Бит
1 БайтВсегда 0РежимВключеноМасштабВсегда 0Левая к.Средняя к.Правая к.
2 БайтРазрешение
3 БайтЧастота посылки


Если кнопка нажата, в нужно бите стоит 1.
Масштаб = 1 если он 2:1; 0 при 1:1.
Включено = 1 если разрешена передача данных.
Режим = 1 при "Remote";  0 при "Stream". 
  • 0xE8 (Set Resolution) - Мышь отвечает "ack" (0xFA),  затем считывает следующий байт от хоста и отвечает "ack" после чего сбрасывает значения счётчиков. Этот байт определяет разрешение мыши:
Байт от хостаРазрешение
00
1 значение/мм
01
2 значения/мм
02
4 значения/мм
03
8 значений/мм

  • 0xE7 (Set Scaling 2:1) - Мышь отвечает "ack" (0xFA), после чего выставляет масштабирование 2:1.
  • 0xE6 (Set Scaling 1:1) - Мышь отвечает "ack" (0xFA), после чего выставляет масштабирование 1:1.

Единственные команды, которые PS/2 мышь отправляет хосту это "Resend" (0xFE) и "Error" (0xFC).



Источники:

retired.beyondlogic.org
сomputer-engineering.org


3 комментария :

  1. У меня тоже есть PS2, но там нету таких функций... В основном там кнопки Start и т.д да игры всякие. Если нетрудно объясните попроще: Как играть на моей соньке 2ой с использованием мыши и клавиатуры? Заранее спасибо!

    ОтветитьУдалить
    Ответы
    1. PS/2 - Это интерфейс мыши, а не плойка!

      Удалить
  2. Приветствую требуется от микросхемы предать к компу Scan-code break+CTRL. Написал прогу частоту генерирую используя циклическую задержку. в ЧЕМ МОЖЕТ БЫТЬ ПРОБЛЕМА Proteus показывает все четко.


    код на С среда Avr Studio 4.1

    //==============================

    /*
    24.05.2019 Create PS2
    Athor Malkhazi
    */

    #define F_CPU 8000000L
    #include
    #include
    //#include



    #define CLK PA0
    #define DATA PA1
    #define LED PD7


    unsigned int delay = 50;
    volatile unsigned int ctr = 0b1100010100; // 20 h14 00010100
    volatile unsigned int sbros = 0b1110101010; // reset

    //=========== own functios declare ===========
    void init(void);
    void sendByte(unsigned char shift, unsigned int d);
    void repear(void);
    void go(unsigned int t);


    int main(void){
    init();

    //sei();
    // repear();
    // go(sbros);

    while(1){

    /*начинается передача*/
    if( (PIND>>0) ){
    /*для нагл зажигаю Led*/
    PORTD |= (1<> если 1 устан. High else Low */
    void sendByte(unsigned char shift, unsigned int d){
    if ( (d>>shift) & 1 ){
    PORTA |= (1<<DATA);
    }else{
    PORTA &= ~(1<<DATA);
    }
    _delay_us(5);
    return;

    }//END

    /*-бросаем Data и щелкаем CLK*/
    void repear(void){

    PORTA &= ~(1<<DATA);
    _delay_us(100);
    PORTA &= ~(1<<CLK);
    _delay_us(delay);
    PORTA |= (1<<CLK);
    _delay_us(delay);
    return;
    }//END


    /*-передаем байт по биту в конце каждого итерации щелкаем CLK -*/
    void go(unsigned int t){

    for (unsigned char k = 0; k < 10; k++){
    sendByte(k, t);

    /*щелкаем CLK*/
    PORTA &= ~(1<<CLK);
    _delay_us(delay);
    PORTA |= (1<<CLK);
    _delay_us(delay);
    }
    return;
    }//end






















    ОтветитьУдалить