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.