//Bei mir handelt es sich um zwei Bausteine des Typs "PCF8574A" //Dabei habe ich an einem Versuchshalber 8 Taster und am anderen 8 LED angeschlossen. ..... #define PCF_TASTER 0x76 /* Codierung laut Datenblatt: codiert -> 0 1 1 | 1 | 1 | 1 | A2 | A1 | A0 | 0 | = 1110110 = 118 Dez = 76 h */ #define PCF_LAMPEN 0x78 /* codiert -> 1 0 0 | 1 | 1 | 1 | A2 | A1 | A0 | 0 | = 1110010 = 114 Dez = 78 h */ ..... // den Bus noch initialiesieren. Bei mir am Portc. SCL = Pin6, SDA = Pin7 // I2C Bus functions #asm .equ __i2c_port=0x15 .equ __sda_bit=7 .equ __scl_bit=6 #endasm #include ..... ..... /*********************************************************************/ /* Anhand der übergebenen Adresse kann man den Zustand der I/O Ports */ /* des gewünschten Teilnehmers auslesen lassen. Dieser Wert wird als */ /* Funktionswert zurückgegeben. */ pcf_port_zustand(unsigned char pcf_teilnehmer) { unsigned char port_zustand; // In diese Variable wird der // Wert des I/O Port geschrieben i2c_start(); // Start zur Datenübertragung i2c_write(pcf_teilnehmer); // Übergebene Adresse senden i2c_start(); i2c_write(pcf_teilnehmer | 1);// Die "1" für lesen senden port_zustand = i2c_read(0); // Portzustand empfangen i2c_stop(); // Ende der Datenübertragung return port_zustand; // Wert an den Funktionsaufruf } /*********************************************************************/ /*********************************************************************/ /* Mit diese Funktion kann der Zustand eines Pins abgefragt werden. */ /* Es ist der Teilnehmer und der gewünschte Pin an die Funktion zu */ /* übergeben. */ pcf_lesen(unsigned char pcf_teilnehmer, unsigned char pin) { unsigned char port_zustand; // aktueller Zustsand des Portes unsigned char signal; // Rückgabe des Signalwertes port_zustand = pcf_port_zustand(pcf_teilnehmer); // erst mal den // den Zustand des Portes einlesen port_zustand >>= pin; // Um testen zu können wie der Zustand // des gewünschten Pins ist, schiebt // man das gesuchte Bit ganz nach // rechts (Bit 0). signal = (port_zustand & 1); // Mit der "verundung" erhält man den // aktuellen Zustand des Pins. Ist das // Bit = 1 so ist auch das Ergebnis 1, // sonst 0. return signal; // Wert an Funktionsaufruf } /*********************************************************************/ /*********************************************************************/ /* Mit diese Funktion kann man ein Pin direkt setzen. Dabei muss man */ /* an die Funktion den Teilnehmer und den gewünschte Pin übergeben */ pcf_pinset(unsigned char pcf_teilnehmer, unsigned char pin) { unsigned char port_zustand; // aktueller Zustsand des Portes unsigned char maske = 1; // Bitmaske für den Port // !!ACHTUNG!!! Bei angeschlossenen LED's leuchten sie, wenn eine "0" // am Port anliegt. Also muss man etwas umdenken port_zustand = pcf_port_zustand(pcf_teilnehmer); // erst mal den // den Zustand des Portes einlesen maske <<= pin; // Um das gewünschte Bit zu setzen wird // erst mal eine "1" an die Bitposition // "geschoben". port_zustand = ~port_zustand; // Der Portzustand wird in der Variable // erst mal invertiert. maske = ~(port_zustand | maske); // der neue Wert für das Port wird // erzeugt in dem man jetzt den inver- // tierten Portzustand mit der maske // "verodert". Diese Ergebnis wird dann // invertiert in der maske gespeichert. // Genaue gesagt handelt es sich um ein "XOR" (exklusiv oder) // wahrheitstabelle: // a|b|y // 0|0|0 // 0|1|1 // 1|0|1 // 0|0|0 // mit anderen Worten, immer "eins" wenn etwas ungleich ist! // Bsp.: 11101101 ->LED 4 & 1 leuchten ->1 soll gelöscht werden // maske 00000010 // Port neu 00010010 (invertiert) // "!(verodern)" -------- // 00010000 // "invertiert" 11101111 -> LED 4 leuchtet, 1 ist gelöscht i2c_start(); // Start zur Datenübertragung i2c_write(pcf_teilnehmer); // Übergebene Adresse senden i2c_start(); // Start zur Datenübertragung i2c_write(pcf_teilnehmer | 0);// Die "0" für schreiben senden i2c_write(maske); // neuen Wert schreiben i2c_stop(); // Ende der Datenübertragung } /*********************************************************************/ /*********************************************************************/ /* Mit diese Funktion kann man ein Pin direkt löschen. Dabei muss man*/ /* an die Funktion den Teilnehmer und den gewünschte Pin übergeben */ pcf_pinclr(unsigned char pcf_teilnehmer, unsigned char pin) { unsigned char port_zustand; // aktueller Zustsand des Portes unsigned char maske = 1; // Bitmaske für den Port // !!ACHTUNG!!! Bei angeschlossenen LED's leuchten sie, wenn eine "0" // am Port anliegt. Also muss man etwas umdenken port_zustand = pcf_port_zustand(pcf_teilnehmer); // erst mal den // den Zustand des Portes einlesen maske <<= pin; //Um das gewünschte Bit zu löschen wird // erst mal eine "1" an die Bitposition // "geschoben". maske = (port_zustand | maske);// Portzustand wird mit der Maske // "verodert" und neu in maske // gespeichert // Bsp.: 00010010 -> LED 4 & 1 leuchten -> 6 soll gesetzt werden // maske 01000000 // "verodern" -------- // 01010010 -> LED 6, 4, und 1 leuchten i2c_start(); // Start zur Datenübertragung i2c_write(pcf_teilnehmer); // Übergebene Adresse senden i2c_start(); i2c_write(pcf_teilnehmer | 0);// Die "0" für schreiben senden i2c_write(maske); // neuen Wert schreiben i2c_stop(); // Ende der Datenübertragung } /*********************************************************************/ /*********************************************************************/ /* Mit diese Funktion kann man eine Variablenwert direkt einem Pin */ /* zuordnen. Dabei ist aber darauf zu achten das nur "0" und "1" */ /* einen Sinn macht. Normalerweise würde man da eine Bit-Variable */ /* verwenden aber das geht bei einer Funktion nicht */ /* es handelt sich hier eigentlich nur um eine simple Funktion, ist */ /* abber sehr hilfreich für mein Programm */ pcf_pinwert(unsigned char pcf_teilnehmer, unsigned char pin, unsigned char wert) { if (wert == 0) pcf_pinclr(pcf_teilnehmer,pin); else pcf_pinset(pcf_teilnehmer,pin); } /*********************************************************************/ ... ... // Beispiel in der Main() /////////////////////////////////////////////// // Hab ich vergessen, sorry!! i2c_init(); // initialisierung des I2C Busses /////////////////////////////////////////////// ... // Mit dem Taster 0 die 4.LED einschalten // |-- Funktionsaufruf // | |-- Bausteintyp (Adresse; siehe #define) // | | |-- Pin-Nummer // | | | // | | | |-- Funktionsaufruf // | | | | |-- Bausteintyp // | | | | | |-- Pin-Nummer // | | | | | | if (pcf_lesen(PCF_TASTER, 0) == 1) pcf_pinset(PCF_LAMPEN, 4); // Mit dem Taster 1 die 4.LED auschalten if (pcf_lesen(PCF_TASTER, 1) == 1) pcf_pinclr(PCF_LAMPEN, 4); // Den Zustand des Tasters 2 direkt an die 5.LED anzeigen pcf_pinwert(PCF_LAMPEN, 5, pcf_lesen(PCF_TASTER, 2)); // Die 7.LED leuchtet wenn die Variable "alarm" den Wert // "1" bekommt pcf_pinwert(PCF_LAMPEN, 7, alarm); // Mit dem Taster 7 die LED 7 wieder auschalten if (pcf_lesen(PCF_TASTER, 7) == 1) pcf_pinclr(PCF_LAMPEN, 7); ...