www.mikrocontroller.net

Forum: Compiler & IDEs PCF8574 über I2C


Autor: Stefan Tschiggerl (stefan90)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Stefan Tschiggerl (stefan90)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Robert Schilling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Stefan Tschiggerl (stefan90)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan Tschiggerl (stefan90)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hier der code als Anhang, dann ist es übersichtlicher

Autor: Eugen Kannsnet (kannsnet)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Eugen Kannsnet (kannsnet)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>ok ich hab des jetzt gerechnet,

Auch ich habe gerechnet: zwei Jahre, zwei Monate und sieben Tage ist die 
Anfrage alt.

Autor: Peter Diener (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Diener (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ist denn jetzt los, mein Beitrag gehört woanders hin. Bitte löschen.

Danke,

Peter

Autor: roboter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hört sich interessant an.
Kann man damit zb auch ein i2cEEpron 24c256 betreiben oder ein 
Kompassmodul Cmps03?

mfg

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.