Hallo zusammen. Ich möchte einen PCF8574 mit einem Mega8 über I2C zum Laufen bringen. Die Adressierung funtioniert schon mal. Und die Start Condition läuft bereits. Nur wie kann ich nun Daten senden? Also es soll nun z.B eine LED an P0 des I2C-Slave zum Leuchten gebracht werden. Nur wie stelle ich das an? Muss ich erneut eine Adresse schicken? Also am lcd-Display hab ich derzeit 000, also der avr bleibt nirgendwo hängen Für Antworten wäre ich sehr dankbar Gruß Stefan
Hallo Anderas Danke erstmal für den Link, jetzt weiß ich endlich mehr! Nur eins ist mir noch nicht klar. Ich will nun wenn Schalter an P7 gedrückt ist, dass die Led an P0 leuchtet. Das Abfragen ist ja kein Problem aber wie sende ich dann, also damit nur der P0-Pin auf high gesetzt wird, alle anderen aber gleich bleiben? Gruß Stefan
Hallo Stefan Wenn du ausgelesen hast, weißt du erstmal den Status aller Output Pins [/C] if(bit_is_set(readout, 7)) readout |= (1 << 0); else readout &= ~(1 << 0); pcf8574_send(readout); [/C] GRuß Robert
Danke Robert, der Code funktioniert erst mal. Nur eins ist mir nicht klar. Hier nun erstmal der Code: #include <stdlib.h> #include <avr/io.h> #include "lcd.h" #define ADRESS 0x20 void i2c_start(uint8_t rw) { unsigned char addr_byte=0; TWBR = (1 << 1) | (1 << 3); //I2C initialisieren, TWBR=10 -> SCL freq=83.33 kHz TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //Sende Start Condition while(!(TWCR & (1<<TWINT))); //Warte bis Übertragung beendet ist addr_byte = ADRESS << 1; //addr_byte=adress und um 1 bit nach links verschieben (für r/w bit) addr_byte |= rw; //r/w bit hinzufügen addr_byte |= 0b01000000; //Aresscode vom PCF8574 (1. 4 Stellen = 0100 siehe Datenblatt) TWDR = addr_byte; //Adresse senden TWCR = (1 << TWINT) | (1 << TWEN); //Clear TWINT bit in TWCR to start transmission of address while(!(TWCR & (1 << TWINT))); //Warte bis Übertragung beendet ist } void i2c_send(unsigned char data) { TWDR= data; //Daten senden TWCR = (1 << TWINT) | (1 << TWEN); //Clear TWINT bit in TWCR to start transmission of data while(!(TWCR & (1 << TWINT))); //Warte bis Übertragung beendet ist } unsigned char i2c_read (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; } void i2c_stop(void) { TWCR= (1<<TWINT) | (1<<TWSTO) | (1<<TWEN); //Sende Stop-Condition while(!(TWCR & (1 << TWSTO))); //Warte bis Übertragung beendet ist } void wait(void) { for (int i=0; i<20000; i++) //delay for (int j=0; j<10; j++) asm volatile ("nop"); } int main (void) { char input; PORTC |= _BV(PC4); //Enable Pullup PORTC |= _BV(PC5); //Enable Pullup i2c_start(0); //I2C initialisieren und Start senden + MT Modus i2c_send(0xFF); //Daten senden, alle Pins auf high i2c_stop(); //Stop senden i2c_start(1); //I2C initialisieren und Start senden + MR Modus lcd_init(LCD_DISP_ON); //lcd initialisieren lcd_clrscr(); lcd_gotoxy(8,0); lcd_puts("I2C - TEST"); lcd_gotoxy(0,2); lcd_puts("Zum Start Schalter an\nP7 des PCF8574 betaetigen"); wait(); wait(); //Warte lcd_clrscr(); for(;;) { input=i2c_read(); //Status der Pins in input speichern for(int i=4;i<8;i++) //Status der Pins auf lcd ausgeben { if (input & (1<<i)) //bei P4 beginnen (aslo Binärcode genau verkehrt herum anzeigen) { //entspricht dann genau Schalteranordnung lcd_puts("1"); } else { lcd_puts("0"); } } if(bit_is_clear(input,7)) //Wenn 7. Bit in input gelöscht ist -> Schalter betätigt { input &=~ (1<<0); //P0 auf 0 setzen -> LED ein input |= (1<<7); //Schalter PIN weiter auf high setzten, sonst (Pin=0) Abfrage } //nicht mehr möglich else { input |= (1<<0); //P0 auf 1 setzen -> LED aus input |= (1<<7); //Schalter PIN weiter auf high setzten, sonst (Pin = 0) Abfrage } //nicht mehr möglich //hier darf kein stop(); rein sonst funktionierts nicht, wenn doch stop(); dann gehört //folgendes dazugeschrieben: // i2c_stop(); TWCR=0; oder TWCR=1; i2c_start(0); //In MT-Modus wechseln i2c_send(input); //input senden i2c_stop(); i2c_start(1); //In MR-Modus wechseln wait(); lcd_clrscr(); } return 0; } Nun: 1.) Warum darf ich das stop() nicht reinschreiben? bzw. warum gehört dann TWCR=0 oder =1 dazu? 2.) Warum muss der Schalterpin immer auf 1 sein? also: input |= (1<<7); hängt das damit zusammen, dass die Schalter auf GND gehen und der Schalter bewirkt dass dann das bit gelöscht wird, nicht aber das Schalten auf VCC bzw. GND? 3.) In meiner i2c_start() lege ich fest dass TWBR gleich 10 ist -> Frequenz = 83.33kHz. Sollte die aber nicht 100kHz betragen? Man soll aber laut Atmel nicht unter 10 in TWBR gehen. Wie soll das gehen? Ich hoffe da kann mir jemand weiterhelfen Gruß Stefan
Hallo, was für einen Wert nimmst du für TWPS an wenn du SCL berechnest? Beziehungsweise kann man den Inhalt von TWPS in der Software beeinflussen? SCL = CPU CLOCK / (16 + 2(TWBR)*4^TWPS) Gruß Eugen
ok ich hab des jetzt gerechnet, und so wie es scheint hast du mit einem cpu clock von 8MHz gerechnet. dann kommt am ende raus 4,000=4^TWPS. und dann kann man annehmen das TWPS 1 ist bei dir.
>ok ich hab des jetzt gerechnet,
Auch ich habe gerechnet: zwei Jahre, zwei Monate und sieben Tage ist die
Anfrage alt.
Hallo nochmal, wenn ich so nachdenke, kann es ja eigentlich nur die Station zweiter Generation sein, die du benutzt. Hat die nicht genug Ports, um ein LCD im 4 bit-Modus direkt anzusteuern? Das wäre erheblich einfacher. Das was vorher auf den Ports war, muss für ein Aquarium bestimmt nicht schnell sein und kann daher bequem über den PCF erledigt werden. Oder ist da ein Denkfehler drin? Peter
Was ist denn jetzt los, mein Beitrag gehört woanders hin. Bitte löschen. Danke, Peter
Hört sich interessant an. Kann man damit zb auch ein i2cEEpron 24c256 betreiben oder ein Kompassmodul Cmps03? mfg
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.