Forum: Mikrocontroller und Digitale Elektronik Problem mit PS2


von TheMason (Gast)


Lesenswert?

Hallo

auch nach durchsehen der Beiträge zum Thema PS2 hab ich nicht viel 
finden können das mir weiterhelfen könnte. Ich habe einen MSP430 und 
möchte eine PS2-Tastatur (und dann eine PS2-Maus) anschließen und das 
ganze per Interrupt einlesen.
Ich habe mir einige Quellcodes und die APP Note von Atmel angeguckt und 
auf dem MSP umgesetzt.
Wenn ich die umgesetzte Atmel-App-Note laufen lasse, kommen zwar zeichen 
an, aber jedes mal ein anderes.
Daraufhin habe ich eine eigene Version gebaut. Lief zwar etwas stabiler, 
aber auch hier kamen ab und zu falsche Zeichen an.
Nächster schritt war es einen Time-Out einzubauen. Danach kamen zwar 
keine falschen Zeichen mehr an, aber manche Codes dafür auch nicht mehr 
(z.b. wurde nur ein Release code gesendet, aber der Scan-Code dazu 
fehlt).
Die Fehler tauchen recht häufig auf.

Meine Fragen gehen nun an alle die erfolgreich eine PS2-Tastatur zum 
laufen gebracht haben (egal mit welchem Controller) :

Musstet ihr auch mit Timeouts arbeiten oder tat/tut es tastatur und maus 
bei euch auch ohne diese Extra-Massnahme ?
Mir ist bei einigen Code-Beispielen (Atmel-Note, div. Quellcodes hier 
aus dem Forum) aufgefallen das das Parity gar nicht beachtet/geprüft 
wird, muß das so, (bei mir hat es die Fehlerrate reduziert) ?!

Insgesamt kommt mir das ganze spanisch vor, vor allem weil die tastaur 
eigentlich immer "Fehler" produziert, und ich mittlerweile einen patzer 
in der Hardware vermute.


Mal eine generelle Frage dazu :

Da ich mir nicht sicher mit welcher Spannung die Tastatur betrieben 
werden muß, habe ich mal 3.3V verwendet. Normalerweise sollte das doch 
eigentlich kein Problem darstellen oder ? Meine tastatur selbst ist 
schon was älter (4-5 jahre). Kann es sein das das schon der einzige 
fehler ist ? Obwohl es mich wundert das die tastatur dann überhaupt was 
sendet ...
Ich habe noch 100Ohm widerstände in die Clock und Datenleitung gelegt, 
damit wenn ich auf 5V gehen muß mir den MSP430 nicht zu sehr quäle. 
Wären 100 Ohm ok oder sollte man doch eher mehr nehmen, oder kann ich 
mir die Widerstände evtl. komplett schenken (selbst wenn mein Prozi nur 
mit 3.3v läuft) ?


Gruß
Rene

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

PC-Tastaturen und -Mäuse arbeiten mit 5V Versorgungsspannung.

von TravelRec. (Gast)


Lesenswert?

PS/2 arbeitet mit 5V. Außedem mußt Du am Controller PullUp-Widerstände 
anschließen, so 4,7kOhm bis 10kOhm. Wenn die Tastatur keinen PullUp drin 
hat, kannst Du keine vernünftigen Signale lesen, weil "Open Collector". 
TimeOuts sind nicht nötig. Die Tastatur ist der Takt-Master, der 
Controller muß diesem Takt direkt und ohne nennenswerte Verzögerung 
folgen und das PS/2 Timing laut Spezifikation einhalten.

von TheMason (Gast)


Lesenswert?

hallo rufus,

mmhh ... also könnte das doch DER fehler sein.
mich wundert das nur, weil in der Anleitung meines Spartan-3-Starterkits 
steht das tastaturen und mäuse mit beiden spannungen zurecht kommen 
müssten. nur ältere tastaturen und mäuse bräuchten 5V.
wie würde es in dem fall denn mit dem widerstand aussehen ? reichen 100 
Ohm oder sollte ich lieber mehr nehmen ?

gruß
rene

von TheMason (Gast)


Lesenswert?

erstmal danke für die infos.

ich hab jetzt die vcc für die tastatur auf 5v gesetzt und noch 5.6K 
pullups in die clock und datenleitung gebracht.

gefruchtet hat das ganze nicht wirklich.

ich habe auf sw-seite die timeouts mal rausgenommen, sämtliche prüfungen 
sein lassen und beschränke mich nur aufs empfangen.
es kommt zwar was an, aber es ist oftmals schrott.
hier mal der code dazu ...
ich weiß langsam nicht mehr weiter. für tipps und infos bin ich dankbar

gruß
rene

von TheMason (Gast)


Lesenswert?

hier der code : (mit dem dateianhängen hat nicht geklappt ...)



  #define PVAL_PS2CLK   0x01
  #define PVAL_PS2DATA  0x02


  #define BD_bPS2Data()       (((P1IN & PVAL_PS2DATA) >> 1) & 1)

  #define BD_vPS2SetClkLo()   P1DIR |=  PVAL_PS2CLK;
  #define BD_vPS2SetClkHi()   P1DIR &= ~PVAL_PS2CLK;


  #define BD_vPS2SetDataLo()  P1DIR |=  PVAL_PS2DATA;
  #define BD_vPS2SetDataHi()  P1DIR &= ~PVAL_PS2DATA;



  typedef UCHAR T_PS2_COMM    (VOID);

  UCHAR BD_ucPS2PortFSMReceive (VOID);
  UCHAR BD_ucPS2PortFSMSend    (VOID);

  static volatile UCHAR ucData     = 0;
  static volatile UCHAR ucBitCnt   = 0;
  static volatile UCHAR ucParCount = 0;


  static T_PS2_COMM    *pfPS2Comm        = (T_PS2_COMM *) 
&BD_ucPS2PortFSMReceive;

  UINT uiPS2ByteCounter = 0;
  UCHAR ucPData;




  //--------------------------------------------------------------------
  //
  //  initialisierung
  //
  //--------------------------------------------------------------------
  void BD_vPS2InitPort (void)
  {
    P1DIR &= ~(0x03);           // ports p1.0 & p1.1 als eingänge
    P1OUT |=  (0x03);           // ports p1.0 & p1.1 auf low 
(pegel-schaltung per umschaltung)
    P1SEL &= ~(0x03);           // ports p1.0 & p1.1 ohne spezialfkt.
    P1IE  |=  (PVAL_PS2CLK);    // pin 1.0 -> interrupt
    P1IES |=  (PVAL_PS2CLK);    // pin 1.0 flanke 1->0
  }

  void BD_vPS2InitData (void)
  {
    ucData        = 0;
    ucBitCnt      = 0;
    ucParCount    = 1;  // parity mit 1 starten ( bei 0,2,4,6 einsen ist 
parity 1, sonst 0 )
  }

  //--------------------------------------------------------------------
  //
  //  PS2-Kommunikations Statemachine - Empfang
  //
  //  - wird vom interrupt aufgerufen
  //
  //--------------------------------------------------------------------

  UCHAR BD_ucPS2PortFSMReceive (VOID)
  {
    UCHAR ucPs2DIn;


    ucPs2DIn = BD_bPS2Data();

    if (ucBitCnt == 0)
    {
      if (ucPs2DIn == 0)
      {
        ucBitCnt    = 1;
        ucData      = 0;
        ucParCount  = 1;
      }
    }
    else if ((ucBitCnt >= 1) && (ucBitCnt <= 8))
    {
      ucData |= (ucPs2DIn << (ucBitCnt - 1));
      //ucParCount = (ucPs2DIn == 1) ? !ucParCount : ucParCount;
      ucBitCnt++;
    }
    else if ((ucBitCnt == 9))
    {
      //if (ucPs2DIn == ucParCount) { ucBitCnt = 10; } // parity prüfen
      //                      else  { ucBitCnt =  0; }
      ucBitCnt = 10;
    }
    else if ((ucBitCnt == 10))
    {
      //if (ucPs2DIn == 1)  // stopbit prüfen
      //{
        ucBitCnt = 0;
        uiPS2ByteCounter++;
        ucPData = ucData;
//        HW_vWriteStd7SegByte (0, ucData);
//        if (pfReceivePS2Data != NULL) { pfReceivePS2Data (ucData); }
        return 1;
      //}
    }

    return 0;
  }


  __interrupt void BD_vPort1ISR (void);

  #pragma vector = PORT1_VECTOR
  __interrupt void BD_vPort1ISR (void)
  {
    // flags und flanke zwischenspeichern
    UCHAR ucP1IFG = P1IFG;
    UCHAR ucP1IES = P1IES;
    // flags resetten
    P1IFG = 0;

    // auswerten
    if ((ucP1IFG & PVAL_PS2CLK) &&  (ucP1IES & PVAL_PS2CLK)) // flanke 
p1.0 0->1
    {
      if (pfPS2Comm != NULL) { pfPS2Comm (); }
    }
  }

von TravelRec. (Gast)


Lesenswert?

Welcher Code?

von TravelRec. (Gast)


Lesenswert?

Ach der, hatte noch nicht aktualisiert :-), sorry aber C ist nicht 
meins...

von TheMason (Gast)


Lesenswert?

hab da was gefunden ....

das ganze funktioniert jetzt zwar, aber ich muß auf den timer-interrupt 
verzichten.
der funkt blöderweise dazwischen und macht mir das timing kaputt. der 
ist anscheinend höher-priorisiert und laut datenblatt kann ich die 
priortäten nicht ändern. jedenfalls sieht es ganze gut aus wenn der 
deaktiviert ist.
jetzt muß ich mal überlegen wie ich das hinkriege das der timer trotzdem 
laufen kann.

trotzdem danke soweit.

ps falls jemand ne idee hat wie man das hinkriegen kann, oder schonmal 
einen msp mit einer ps/2 schnittstelle verheiratet hat wär ich dankbar 
für einen tip

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.