- Labornetzteil AliExpress         
Ergebnis 1 bis 8 von 8

Thema: PS/2 Maus am PIC16F886

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    27.03.2009
    Beiträge
    7

    PS/2 Maus am PIC16F886

    Anzeige

    Praxistest und DIY Projekte
    Hallo,
    ich bin noch ein relativ unerfahrener Bastler und möchte mittels einer PS/2 Maus und eines PIC16F886 die Bewegung der Maus erfassen und auf einem DEM16217 Display ausgeben. Das Display habe ich weils nur für den Moment ist parallel an den PIC angeschlossen. Die Ansteuerung Funktioniert auch so weit. Die Clock und Datenleitung der Maus habe ich über 2 4k7 Pullups gegen 5V an 2 Ports des PICS angeschlossen. So weit so gut, doch ich bekomme die Kommunkikation zwischen PIC und Maus nicht so recht zum Laufen, deshalb möchte ich euch bitten mal ein Auge auf meinen Code zu werfen.
    Gruß stumpi
    Angehängte Dateien Angehängte Dateien

  2. #2
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Ich beschäftige mich zur Zeit mit dem Anschluß einer PC-Tastatur an einen AVR. Da Maus und Tastatur die selben Protokolle verwenden kann dir vielleicht dieser Link hilfreich sein:

    http://www.marjorie.de/ps2/ps2_protocol.htm

    Ich habe das zwar noch nicht selbst ausprobiert, aber einige Stellen in deinem Code scheinen danach nicht ganz richtig zu sein:

    Code:
    unsigned char readByte(void){
    signed char i;
    unsigned char daten=0;
       
       delay_us(3);            //Sensor Zeit lassen um die Daten aus dem Register zu holen
    
       for (i=7; i>-1; i--){
          while (0==INPUT(clk));      // SCK =0 Sensor bereitet Daten auf fallender Flanke vor !
             
          delay_us(1);         //Sensor kurz Zeit lassen
          
          if(INPUT(data)==1){       //BIT einlesen
             daten |= (1<<i);
          }
    	  else{
             daten &=~ (1<<i);         
          }         
    
       }
       return data;
    }
    Die Wartezeiten erscheinen mir zu kurz. Das LSB kommt zuerst! Start/Stop/Parity wird ignoriert. Das Taktende wird nicht abgewartet. Und schließlich sind die Daten bei fallender Flanke des Taktes (von 1 nach 0) gültig.

    Achtung! Auch beim Schreiben gibt die Maus den Takt vor. Der Takteingang am Kontroller muss wohl immer hochohmig sein.

    Viel Erfolg.

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    27.03.2009
    Beiträge
    7
    @radbruch vielen dank für den link und die prompte antwort
    ich habe meinen code verbessert (hoffe ich) doch ich kann immer noch keine daten von der maus empfangen
    funktioniert deine kommunikation zwischen tastatur und avr??
    Angehängte Dateien Angehängte Dateien

  4. #4
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Inzwischen funktioniert es mit einer Tastatur ganz gut:

    Code:
    // PS/2-Schnittstelle am ATMega32                                  1.4.2009 mic
    // RP6 liest AT-Tastatur am I2C-Port
    
    // http://www.marjorie.de/ps2/ps2_protocol.htm
    // http://www.beyondlogic.org/keyboard/keybrd.htm
    
    #include "RP6RobotBaseLib.h"
    
    uint8_t i, scancode;
    
    int main(void)
    {
    	initRobotBase();
    	DDRC &= ~3; //SDA und SCL sind Eingänge
    	PORTC  &= ~3; // ohne interne PullUps (extern sind 4k7 PullUps angeschlossen)
    
    	while(1)
    	{
    		i=0;
    		scancode=0;
    		while(PINC & 1); // Warten auf Startbit
    		while(!(PINC & 1)); // Ende Startbit
    		do
    		{
    		   while(PINC & 1); // Tastatur bereitet die Daten vor
    		   if(PINC & 2) scancode |= (1<<i); // Bit einlesen
    		   i++;
    		   while(!(PINC & 1)); // gelesen, auf nächstes Bit warten
    		}while(i<8);
    
    		while(PINC & 1); // Warten auf Paritybit
    		while(!(PINC & 1)); // Ende Paritybit
    		while(PINC & 1); // Warten auf Stopbit
    		while(!(PINC & 1)); // Ende Stopbit
    
    		writeInteger(scancode, 16);
    		writeChar('\n');
    	}
    	return(0);
    }
    Mit der Maus funktioniert das seltsamerweise nicht. Dein Programm habe ich nicht getestet. Ich bin aber noch dran.

    Gruß

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  5. #5
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Und nochmals hallo

    Es funktioniert! Zwar mit einem AVR, aber das sollte ein PIC auch können. Ich weiß allerdings nicht ob die PICs auch Tristatepins besitzen, ich gehe aber davon aus.

    Das Problem: Entgegen den meisten Dokus muss man der PS/2-Maus wohl ein Kommando senden um sie zum Senden der Daten zu überreden. Alle meine Testmäuse wurden aktiv nachdem sie ein 0xf4 (enable) erhalten hatten:
    Code:
    // PS/2-Schnittstelle am ATMega32                                  1.4.2009 mic
    // RP6 liest PS/2-Maus am I2C-Port
    
    // http://www.marjorie.de/ps2/ps2_protocol.htm
    // http://www.beyondlogic.org/keyboard/keybrd.htm
    // http://instruct1.cit.cornell.edu/cou...c72/index.html
    
    // Hihi: http://www.mikrocontroller.net/topic/130824
    
    #include "RP6RobotBaseLib.h"
    
    #define Clock_Low  	{DDRC |=1; PORTC &=~1;}	// clock low aktiv
    #define Data_Low   	{DDRC |=2; PORTC &=~2;}	// data low aktiv
    #define Clock_High 	{DDRC &=~1; PORTC &=~1;}// Eingang mit externem 4K7-PullUp)
    #define Data_High  	{DDRC &=~2; PORTC &=~2;}// Eingang mit externem 4K7-PullUp)
    #define Data_Out     {DDRC |=2; PORTC |=2;} 	// data high aktiv
    #define Clock_In     (PINC & 1)					// Eingang abfragen
    #define Data_In      (PINC & 2)					// Eingang abfragen
    
    void send(uint8_t kommando)
    {
    	uint8_t i, parity;
    	parity=0;
    
    	Clock_Low;  		// Clock auf Low und kurz warten -> Bus übernehmen
    	sleep(2);
    	Data_Low;  			// Datenleitung auf Low
    	Clock_High; 		// Clock auf high -> Takt wieder freigeben
    	while(!Clock_In); // Warten bis Maus den Takt ausgibt
    
      	for(i=0; i<8; i++) // 8 Bit Daten senden
    	{
    		while(Clock_In);  // Warten bis schreiben erlaubt
    		if(kommando & (1<<i)) { Data_Out; parity++; } else Data_Low
    		while(!Clock_In); // Daten bereitgestellt, warten bis Maus liest
    	}
    
      while(Clock_In); // Warten bis schreiben wieder erlaubt, dann Parity ausgeben
      if(!(parity & 1)) Data_Out else Data_Low // Parity richtig senden
      //if(parity & 1) Data_Out else Data_Low // Parityfehler erzwingen
      while(!Clock_In); // Maus liest Parity
      while(Clock_In);  // Stopbit abwarten (wird scheinbar nicht geprüft)
      while(!Clock_In); // Maus liest Stopbit
    
      Data_High;	// Datenleitung freigeben
    
      while(Data_In);  // ack von Maus abwarten
      while(!Data_In); // Das war's
    }
    uint8_t read(void)
    {
    		uint8_t i, scancode, parity;
    		scancode=0;
    		parity=0;
    		while(Clock_In); // Warten auf Startbit
    		while(!Clock_In); // Ende Startbit
      		for(i=0; i<8; i++) // 8 Bits einlesen
    		{
    		   while(Clock_In); // Maus bereitet die Daten vor
    		   if(Data_In) scancode |= (1<<i); // Bit einlesen
    		   while(!Clock_In); // gelesen, auf nächstes Bit warten
    		}
    
    		while(Clock_In); // Warten auf Paritybit
    		if(Data_In) parity=1; // Parity einlesen
    		while(!Clock_In); // Ende Paritybit
    		while(Clock_In); // Warten auf Stopbit
    		while(!Clock_In); // Ende Stopbit
    	return(scancode);
    }
    
    int main(void)
    {
    	initRobotBase();
    	Clock_High;
    	Data_High;
    	
    		send(0xff); // reset
    		writeInteger(read(), 16);
    		writeChar('\n');
    		writeInteger(read(), 16);
    		writeChar('\n');
    		send(0xff); // reset
    		writeInteger(read(), 16);
    		writeChar('\n');
    		writeInteger(read(), 16);
    		writeChar('\n');
    		send(0xf4); // enable
    		writeInteger(read(), 16);
    		writeChar('\n');
    		mSleep(500);
     		writeString_P("\nBitte Maus bewegen!\n\n");
    
    	while(1)
    	{
    		writeInteger(read(), 16);
    		writeChar('\n');
    	}
    	return(0);
    }
    Achtung! Auch beim Senden von Kommandos gibt die Maus den Takt vor! Das Protokoll stimmt zwar anscheinend immer noch nicht mit der Doku überein, aber die Maus sendet Daten die man jetzt mal dekodieren kann. Es gibt noch viel zu erforschen ;)

    Gruß

    mic

    [Edit]
    btw. sind Mäuse zur Wegerfassung nicht geeignet:
    https://www.roboternetz.de/phpBB2/ze...=421528#421528
    Der erste Absatz gilt auch für Kugelmäuse.
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    27.03.2009
    Beiträge
    7
    also mit meinem code konnte ich zwar daten senden aber irgendwie gibts da noch nen kleinen fehler
    ich habs jetzt mal dein code so angepasst das er auf dem pic läuft
    die maus antwortet jetzt auf 0xFF und 0xF4 mit 0xFA wie gewünscht bin aber noch nicht dazu gekommen die gesendeten daten auszuwerten.
    bei jeder bewegung sendet die maus 3 byte oder?

  7. #7
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Ist doch schon prima wenn es funzt. Ja, es sind drei Bytes: Overflow- und Richtungsbits für Deltax/-y und die Statusbits der Tasten im ersten Byte, gefolgt vom 8Bit-Zweierkomlement (Kehrwert-1?) für Deltax und Deltay.

    Das Protokoll stimmt übrigends doch. Das Problem ist die serielle Ausgabe während das PS/2-Gerät sendet. Dadurch werden gelegentlich Daten verbummelt. Ich hab'noch ein bisschen rumgespielt, inzwischen meldet sich sogar eine USB-Funkmaus mit PS/2-Adapter brav mit FA AA 00 :)

    Die blockierenden Funktionen sind nicht wirklich befriedigend, zumal nicht mal ein Timeout vorgesehen ist. Besser wäre ein interruptfähiger Eingang an Clock mit entsprechender ISR. Das habe ich aber nicht zur Verfügung deshalb untersuche ich mal ob man nicht das TWI-Modul im AVR dazu überreden kann die Tastatur-/Mausdaten einzulesen. PICs können vermutlich auch TWI, oder?

    Gruß

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    27.03.2009
    Beiträge
    7
    also der pic hat interupt pins und auch 2 I²C pins
    ich denke ich werde es mal mit interrupts versuchen
    kannst du die 3 gesendeten bytes gescheit abspeichern?

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad