PCF8574 über I2C

#410713
Lesenswert?

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
Angehängte Dateien:
#410717
Lesenswert?

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
Gast #1035331
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren