ArduinoUNO에서 PS/2 키보드를 사용한 메모

3959 단어 AVRArduino

ArduinoUNO에서 PS/2 키보드 사용



옛 PC용 키보드는 동기 시리얼 통신이므로 AVR이라면 쉽게 연결할 수 있다고 생각해 보았다.

연결



일반적으로 동기 통신으로 8O1 (시작 비트 1, 데이터 8, 홀수 패리티, 정지 비트 1
Data, Clock 모두 오픈 콜렉터로 4.7KΩ으로 풀업되고 있다
키보드와 ArduinoUNO 연결
데이터 -> PIN0 (RX)
시계 -> PIN4 (XCK)
전원을 잊지 않고



키보드에서 수신



처음에 성실하게 레지스터를 설정했지만, Serial.begin에서 초기 설정 후에 동기 통신으로 변경하는 것만으로 수신 인터럽트도 포함해 사용할 수 있다.
  Serial.begin(9600, SERIAL_8O1); //初期設定はおまかせして
  UCSR0C |= (1 << UMSEL00);   //同期通信モードへ変更

/*
 ワイヤードOR接続のおまじない、Input時はハイインピーダンス
  Output時はLOWになる 
*/
  pinMode(0, INPUT);
  pinMode(4, INPUT);

  digitalWrite(0, LOW);
  digitalWrite(4, LOW);  


읽기는 보통 Serial.Read()를 사용할 수 있으며, 데이터는 키 톱에 인쇄된 문자가 아니라 스캔 코드라고 불리는 데이터, 용도에 따라 변환이 필요
uint8_t  get_usart() {
  uint8_t c;
  while (Serial.available() == 0)
    ;
  c = (0x00ff & Serial.read());
  return c;

}


키보드로 보내기



파워 온 리셋 이외로 리셋하는 경우나, 키보드의 LED를 컨트롤 하는 경우는 USART를 무효 유효 전환하거나 조금 번거로운 수속이 필요.
  • 시계, 데이터가 모두 HIGH가 될 때까지 기다립니다
  • USART 비활성화
  • 마이크로 컴퓨터에서 Clock을 LOW로 설정
  • 마이크로 컴퓨터에서 Data를 LOW로 (start bit)
  • 마이크로 컴퓨터에서 Clock을 HIGH로 설정
  • 키보드가 Clock을 LOW로하기 때문에 순서대로 Data에 기입한다
  • 5를 8회 반복하면 패리티
  • 정지 비트
  • 키보드에서 수신 완료로 한 번 더 시계가 온다
  • USART를 활성화하고 키보드에서 회신을 기다립니다



  • 키보드에 대한 명령(일부)




    1
    2
    3


    재설정
    0xFF
    리셋

    LED
    0xED
    다음 데이터로 LED 전도 소등 bit2=CapsLock,bit1=NumLock,bit0=ScrollLock


    주요 답장 코드




    1
    2
    3


    Ack
    0xFA
    정상 수신

    Resend
    0xFE
    데이터 재전송 요청

    #define CLK_LO  pinMode(4,OUTPUT);
    #define CLK_HI  pinMode(4,INPUT);
    #define DATA_LO pinMode(0,OUTPUT);
    #define DATA_HI pinMode(0,INPUT);
    #define WAIT_CLK_LO while(digitalRead(4) == HIGH);
    #define WAIT_CLK_HI while(digitalRead(4) == LOW);
    
    #define DELAY 50
    
    
    uint8_t send_data(uint8_t data) {
      int shift = 1;
      uint8_t parity = 0;
      uint8_t rcv;
    
    
      WAIT_CLK_HI;   //busy?
      delayMicroseconds(DELAY);
    
      TIMSK1 &= ~(1 << OCIE1A); //timer off
      UCSR0B &= ~(1 << RXEN0); //usart off
      UCSR0C &= ~(1 << UMSEL00);
    
      CLK_LO;                 //RTS
      delayMicroseconds(DELAY);
    
      DATA_LO; //start bit
      delayMicroseconds(DELAY);
      CLK_HI;
    
      WAIT_CLK_LO;          //キーボード発生のクロック待ち
      delayMicroseconds(DELAY / 2);
    
      while (shift != 0x100) {
    
        if (data & shift) {
          DATA_HI;  //bit = 1
          parity++;
        } else {
          DATA_LO  //bit = 0
        }
        WAIT_CLK_LO;
        WAIT_CLK_HI;
        delayMicroseconds(DELAY / 2);
        shift <<= 1;
      }
      //parity
      if (parity & 0x01) {
        DATA_LO;  //bit = 1
      } else {
        DATA_HI;  //bit = 0
      }
      WAIT_CLK_LO;
      WAIT_CLK_HI;
      delayMicroseconds(DELAY/2);
    
      DATA_HI; //stop bit
      WAIT_CLK_LO;
      WAIT_CLK_HI;
      WAIT_CLK_LO;
      WAIT_CLK_HI;
    
      UCSR0B &= ~(1 << RXCIE0); // intrrupt off
      UCSR0B |= (1 << RXEN0); //usart on
      UCSR0C |= (1 << UMSEL00);
      while (!(UCSR0A & (1 << RXC0))); //キーボードから応答待ち
      rcv = UDR0;
      UCSR0B |= (1 << RXCIE0); // intrrupt on
    
      TIMSK1 |= (1 << OCIE1A);
      return rcv;
    }
    

    요약



    수신만이라면 Serial.begin에 한 줄 추가하는 것만으로 간단하게 할 수 있는, 읽기 데이터가 스캔 코드이므로 조금 버릇이 있지만 키수가 많은 간단 입력 디바이스로서, 약간의 공작이나 실험에는 편리.

    참고로 한 사이트
    htp://이오이오입니다. 웨 b. FC2. 작은 m/PS2/PS2. HTML

    좋은 웹페이지 즐겨찾기