-         

Ergebnis 1 bis 4 von 4

Thema: PCF8574 auslesen

  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    04.04.2005
    Ort
    Hamburg
    Alter
    29
    Beiträge
    826

    PCF8574 auslesen

    Anzeige

    Also mein Problem ist folgendes:

    Ich lese für eine Tastaturmatrix einen PCF8574 aus an welchem über Pullups an allen 8 Eingängen 5V hängen. (Schaltplan ist denke ich nicht wichtig, falls doch gibts Bilder)

    Wird nun eine Taste gedrückt geht eine Leitung irgendwann auf GND, wenn die Zeilen nacheinander alle durchprobiert werden.

    Ich lese nun den PCF8574 aus und erhalte also ein Byte voll einsen und ein Bit ist ne 0. Die 0 zeigt mir die Spalte der gedrückten Taste an. Das funktioniert auch wunderbar, solange es nicht das 8. Bit ist. Dann stürzt mir der Controller ab, bzw. die Schleife wird einfach nicht fortgesetzt.

    Hier mal mein Programmcode:
    Code:
    	
    DDRD &= ~((1<<PD6)|(1<<PD7)); //PD6 und PD7 als Eingang definieren
    	uart_init();
    	//sei(); /* egal .... */
    	cli();    /* egal .... */
    	uint16_t input = 0;
    	uint8_t zeilen_zaehler = 1;
    	uart_puts(" Lese Tastatur...\r\n");
    	while(1){ //Hauptprogrammschleife
    		for(zeilen_zaehler=1; zeilen_zaehler; zeilen_zaehler = zeilen_zaehler<<1) {
    		//zeilen_zaehler hat also eine 1 im 1. bit, welches bei jedem Schleifendurchlauf eins nach links wandert bis es hinten raus fällt. Dann bricht die Schleife ab.
    			input = 0;
    			pcf8574_set_outputs(I2C_Z,~zeilen_zaehler);
    			//Ich setze alle Pins auf 5V, bis auf die zu testende Leitung, die auf GND, deswegen ~
    			input = ((PIND&((1<<PD6)|(1<<PD7)))<<2); 
    			//diese beiden Kanäle les ich auch aus, da ich insgesamt 10 Spalten einlse
    			/*PD6 und PD7 auf 1 setzen. Durch das & werden nur noch 1 an PD6 oder PD7 behalten. <<2 um es auf die ersten beiden Bits des nächsten Bytes zu legen. */
    			input |= pcf8574_get_inputs(I2C_SP);
    			//es wird das niedrige Byte beschrieben.
    			if (input==895) //entspricht einer 0 auf dem 8. Bit und auf den anderen Bits 1-10 eine 1.
    {uart_puts(".bl2.");Msleep(750);uart_puts(".blub.");}
    /*Debugmeldung um einen Spannungseinbruch beim Tastendruck oder ähnliches zu ermitteln. Auch nach der Wartezeit(oder ohne) kommen alle ausgaben bis zum ende dieses schleifendurchlaufs*/
    			if(input != 1023) { //falls eine Leitung auf GND liegt, diese ausgeben.
    				uart_puts("Z.Nr.: ");
    				PrintInt(zeilen_zaehler);
    				uart_puts(" Lese Tastatur: ");
    				PrintInt(input);
    				//PrintInt(~(input|0xfc00)); //die höchsten 6 Bits ausblenden und den Wert invertiert ausgeben, weil einfacher zu lesen
    				uart_puts("\r\n");
    			}
    			if (input==895) {uart_puts(".bl3.");}
    		}
    		//uart_puts("..");
    	}
    So, hoffentlich kann man den Code überhaupt lesen ....

    Egal welchen Eingang ich auf GND ziehe, es funktioniert. Wenn ich den Eingang unten halte, dann kommt ganz schnell nacheinander im Terminal die Zeile und Spalte (also zeilen_zaehler und input) auf den Bildschirm.

    Ziehe ich jedoch das 8. Bit des PCF8574 auf GND wird der Schleifendurchlauf beendet (wie mir das Terminal zeigt) aber danach startet einfach kein weiterer und erst ein Reset des Controllers schafft hier abhilfe.

    Kann mir jemand bei diesem sehr speziellen Problem helfen?
    Hier noch der Code zum auslesen des PCF8574:

    Code:
    /*pcf8574.c*/
    #include "pcf8574.h"
    #include "uart.h"
    
    
    void pcf8574_init (void)
    {
    	/*set bus speed*/
    	TWBR = 0x10;
    }
    
    
    unsigned char pcf8574_send_start (void)
    {
    	/*writing a one to TWINT clears it, TWSTA=Start, TWEN=TWI-enable*/
    	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
    	/*wait, until start condition has been sent --> ACK*/
    	while (!(TWCR & (1<<TWINT)));
    	return TWSR;
    }
    
    
    void pcf8574_send_stop (void)
    {
    	/*writing a one to TWINT clears it, TWSTO=Stop, TWEN=TWI-enable*/
    	TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);	
    }
    
    
    unsigned char pcf8574_send_add_rw (unsigned char address, unsigned char rw)
    {
    	/*address can be 0 .. 8; rw=0 --> write, rw=1 --> read*/
    	unsigned char addr_byte = 0;
    	/*shift address one bit left*/
    	addr_byte = address << 1;
    	/*set RW-Bit, if necessary*/
    	addr_byte |= rw;
    	/*0b0100xxx0 --> address of Expander*/
    	addr_byte |= 0b01000000;
    	/*TWDR contains byte to send*/
    	TWDR = addr_byte;
    	/*send content of TWDR*/
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	/*wait, until address has been sent --> ACK*/
    	while (!(TWCR & (1<<TWINT)));
    	return TWSR;
    }
    
    
    unsigned char pcf8574_send_byte (unsigned char byte)
    {
    	/*TWDR contains byte to send*/
    	TWDR = byte;
    	/*send content of TWDR*/
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	/*wait, until byte has been sent --> ACK*/
    	while (!(TWCR & (1<<TWINT)));
    	return TWSR;
    }
    
    
    unsigned char pcf8574_read_byte (void)
    {
    	/*send content of TWDR; TWEA = enable ACK*/
    	TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
    	/*wait, until byte has been received --> ACK*/
    	while (!(TWCR & (1<<TWINT)));
    	return TWDR;
    }
    
    
    unsigned char pcf8574_get_inputs (unsigned char address)
    {
    	pcf8574_init ();
    	pcf8574_send_start ();
    	pcf8574_send_add_rw (address, 1);
    	unsigned char input = pcf8574_read_byte ();
    	pcf8574_send_stop ();
    	if (input==127) {uart_puts(".bl.");}
    	return input;
    }
    
    
    void pcf8574_set_outputs (unsigned char address, unsigned char byte)
    {
    	pcf8574_init ();
    	pcf8574_send_start ();
    	pcf8574_send_add_rw (address, 0);
    	pcf8574_send_byte (byte);
    	pcf8574_send_stop ();
    }
    Code:
    /*pcf8574.h*/
    #ifndef _PCF8574_H
    #define _PCF8574_H
    
    
    #include <avr/io.h>
    
    
    void pcf8574_init (void);
    
    unsigned char pcf8574_send_start (void);
    
    void pcf8574_send_stop (void);
    
    unsigned char pcf8574_send_add_rw (unsigned char address, unsigned char rw);
    
    unsigned char pcf8574_send_byte (unsigned char byte);
    
    unsigned char pcf8574_read_byte (void);
    
    extern unsigned char pcf8574_get_inputs (unsigned char address);
    
    extern void pcf8574_set_outputs (unsigned char address, unsigned char byte);
    
    #endif
    Vielen Dank

    Andun
    www.subms.de
    Aktuell: Flaschcraft Funkboard - Informationssammlung

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    04.04.2005
    Ort
    Hamburg
    Alter
    29
    Beiträge
    826
    Hi

    So, nur um das mal aufzuklären:

    Ihc habe das ganze jetzt ohne die pcf8574.c und .h gelöst und einfach die "normale" i2cmaster.c und twimaster.h genommen. Damit funktioniert es.

    Das Problem war írgendwo im i2cinit, dass er das nicht geschafft hat .... egal...

    Andun
    www.subms.de
    Aktuell: Flaschcraft Funkboard - Informationssammlung

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2007
    Beiträge
    386
    ....Das Problem war írgendwo im i2cinit, dass er das nicht geschafft hat .... egal... .....


    warum gehst du der sache nicht auf den grund?

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    04.04.2005
    Ort
    Hamburg
    Alter
    29
    Beiträge
    826
    Hi

    Hast recht Eigentlich ziemlich schlecht so, aber das war aus Zeit gründen.

    Die von mir verwendete Bibliothek benutze hauptsächlich auch nur die Registrierungszugriffe wie die "normale" I2C Bibliothek auch.

    Und da ich jetzt nur 2 Funktionen ohne die Kapselung außen rum aufrufen muss, stört mich nicht wirklich.

    Irgendwann schau ihc mir dass aber vielleicht nochmal an. Im moment hab ich aber leider nicht so viel Zeit

    mfg
    Andun
    www.subms.de
    Aktuell: Flaschcraft Funkboard - Informationssammlung

Berechtigungen

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