www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Expander: Digitaleingänge


Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin Leute,

ich habe einen ATmega324P20PU und führe damit mehrere Sachen durch, wo 
ich 10 Digitaleingänge benötige. Da ich jedoch nur 7 zur Verfügung habe, 
muss ich noch welche hinzufügen.

Nun habe ich den PCF8574AP in der Hand und versuche mich gerade in das 
Thema TWI und Expander einzulesen.

Momentan stellen sich mir 2 Fragen:

1. Für meine Anwendung (ich brauche ja noch 3-4 Digitaleingänge) ist 
diese Logik nicht ganz korrekt oder?

http://www.mikrocontroller.net/articles/Port-Expan...

Die Pins 4-7 kann ich eh weglassen (?) und bei den Pins 0-3 muss ich 
nach dem ACK ein 0xFO als Schreibzugriff senden und dann die internen 
PullUps aktivieren. Habe ich dann einen digitalen Eingang?

2. Zum Thema TWI: 
http://www.mikrocontroller.net/articles/AVR_TWI#Au...

An welcher Stelle kommt denn da nun die Abfrage des Wertes, sprich wo 
kann ich da meine IF-Abfrage einbauen, die überprüft, ob an dem 
Digitaleingang ein Signal anlag.


Vielen Dank im Voraus!

Autor: H.Joachim Seifert (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du nicht sowieso schon einen I2C-Bus hast, dann auch mal die 
Alternativen überlegen:
-Multiplexer
-Schieberegister

Manche I2C-Bausteine sind für die gelieferte Funktionalität einfach viel 
zu teuer, gerade bei PCFxxx ist mir das schon mehrfach aufgefallen.

http://www.mikrocontroller.net/articles/AVR-Tutori...

Autor: Mario Grafe (mario)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo ist das Problem? Du kannst jeden I/O des PCF8574 als Eingang 
definieren. Es wird einfach via I2C konfiguriert.

Du solltest dir eine fertige I2C-Master-Library zu Hilfe nehmen, um dir 
das Leben nicht unnötig schwer zu machen, z.B. von Peter Fleury: 
http://www.jump.to/fleury

Ob am Digitaleingang etwas anliegt, erfährst du über den Interrupt vom 
PCF8574.

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe die Libary kopiert und mir angeschaut. Ist die Abfrage dann so 
richtig?
  i2c_init();                //initialisieren

  if (!(i2c_start()))        //was muss ich da übergeben?
    {
    i2c_write(0x01);

    i2c_rep_start();//was muss ich da übergeben?

    uchk = i2c_readNak(); //wertzuweisung

    i2c_stop();      //terminierung
  }
if (uchk)      //wenn uchk wahr, dann ...
[...]

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lese gerade, dass bei den Funktionen der Ort des Devices + Modus 
angegeben werden muss. Ist damit die Adresse des Expanders oder des 
ATmega gemeint?

Autor: Mario Grafe (mario)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lies dich erstmal in die I2C-Problematik ein. Bei der Library ist auch 
ein Beispiel dabei (für EEPROM glaube ich).

Merke folgendes:
- I2C ist ein Master-Slave Protokoll!
- Dein Atmega ist der Master!
- Die Deviceadresse ist eine 7-Bit Adresse (wird aber häufig als 8-Bit 
Wert angegeben, das letzte bit ist das read/write flag)
- Die oberen 4 Bit sind fest (0x70), die unteres sind frei wählbar 
(A[2:0]),
- Wenn du A[2:0] auf Masse legst is deine Deviceadresse 0x70 (+ 
R/W-Flag)
- Du mußt immer zuerst eine Start-Condition + Device-Adresse senden 
bevor du i2c_write oder ...read machen kannst

Also etwa so:
i2c_init();
i2c_start_wait(0x70+I2C_WRITE);   
i2c_write(irgendeinwert);
i2c_stop();

was genau gesetzt werden muß steht eindeutig im Datenblatt des 
PCF8475...
so nu aber los...

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab ich so verstanden, ich werde erstmal löten, dann versuchen und mich 
weiterbilden. sollte ich dennoch fragen haben, hab ich ja dich mario :P

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe alles soweit verstanden,mir ist klar welchen Device der 
Expander nun hat.Desweiteren habe ich A0-A2 auf GND gelegt und SDA, CLP, 
INT an meinen Prozessor angeschlossen(dazu parallel auf 5V gezogogen)

Allerdings: wie kann ich genau einen der 8 verschiedenen Ports am 
Expander auslesen?

Beim read Befehl gebe ich ja den Device an(sprich auf welches Element er 
zugreifen soll; in meinem Fall 0x70+I2C_READ. Doch wie sage ich ihm, 
dass er PIN0 auslesen soll?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Carsten (Gast)

>Allerdings: wie kann ich genau einen der 8 verschiedenen Ports am
>Expander auslesen?

Indem du den IC normal ausliest und Bitmanipulation durchführst.

MFG
Falk

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
i2c_init();                                // init I2C interface
    i2c_start_wait(0x70+I2C_READ);
    i2c_readNak();                       // wie lese ich z.B.PIN 4 am 
Expander??
    i2c_stop();


Der Expander hat 8 Ausgänge, von P0-P7. Diese befinden sich an den Pins 
4 - 7 und 9 - 12.

Ich verstehe noch nicht ganz, wie das machen soll T.T...sry

zumal ich dann ja noch eine IF-Abfrage machen möchte, sprich, wenn an 
dem Eingang Spannung anliegt, dann blabla

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
LIES DEN GOTTVERDAMMTEN ARTIKEL Bitmanipulation!!!

Autor: Mario Grafe (mario)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lies das Datenblatt! Da steht alles drin!
Du liest immer die gesamten 8 bit aus.

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
okay ich will euch nicht weiter verärgern mit meiner dummheit :/

Daher sagt mir einfach nur ob ich das richtig verstanden habe (Ja oder 
nein genügt). Ich lese den Expander aus. Wenn an Pin 0-4 eine Spannung 
anliegt und an den Pin 5-8 keine, dann werden die 8 bit 11111000 
übertragen/ausgelesen mit dem Readbefehl. Falls ich nun prüfen möchte, 
ob an einem Eingang etwas anliegt muss ich mit Bitmanipulation z.b. mit 
00001000 verunden. Falls das dann ungleich null ist, liegt an Pin 4 
Spannung an.

Autor: Mario Grafe (mario)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define Dev_Address  0x70      // device address
//[...] P.Fleury auch included
int main(void)
{
  // Portsettings
  DDRA  = 0x00;  // PORT A as Input
  DDRB  = 0x00; // PORT B0 as Input
  DDRD  = 0xFF;  // PORT  D as Output
  PORTD  = 0x00; // LEDs PORT D red ON

uint8_t bla;

    DDRB &=~ (1<<PB0);                 /* PIN PB0 auf Eingang (Taster)            */
    PORTB = (0<<PB0);                 /* Pullup-Widerstand aktivieren            */

while(1)
{
      if (PINB & (1<<PB0))// Falls Taster an PIN PB0 gedrueckt...
      {
            i2c_init();         // init I2C interface
       
     if(!(i2c_start(Dev_Address+I2C_WRITE)))
     {
         i2c_write(0xF);    //PIN 0:3 = Eingang
                i2c_rep_start(Dev_Address+I2C_READ);        
                bla = i2c_readNak();                            
                i2c_stop();
            }       
       }
       if(bla & 0x08)                                 PORTD |=(1<<PD4);      //Horn an

}

also meine Abfrage funktioniert noch nicht. Aber soweit ist doch erstmal 
alles i.O. oder? Habe mit einem Multimeter nachgemgessen, an allen 
Eingängen liegen 5V an, an den Ausgängen jedoch auch.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

> Wenn an Pin 0-4 eine Spannung anliegt und an den Pin 5-8 keine, dann
>werden die 8 bit 11111000

>ja

Nein. Es gibt z.B. keinen P8.

Bei der Binärschreibweise steht Bit 0 immer rechts.
Also liest du 0b00011111 ein.

MfG Spess

Autor: Carsten (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hm ja hast recht, war ein Schreibfehler von mir.

Ich habe mal das Testprogramm von Peter Fleury laufen lassen.

Bei jedem Schritt habe ich eine LED eingefügt, die leuchten soll. 
Außerdem habe ich oben beim define die Adresse auf 0x70 geändert. 
Allerdings geht das nur solange, bis
ret = i2c_start(Dev24C02+I2C_WRITE);       // set device address and write mode

ausgeführt wird. Die LED die nach dem init gesetzt ist, leuchtet, die 
nach dem oben genannten Befehl nicht mehr. Woran könnte das liegen?

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe es noch weiter eingegrenzt. Der hängt sich in der i2c_start 
Funktion bei der 1. while Schleife auf.
//wait until transmission completed
while(!(IWCR &(1<<TWINT)));

danach gehts nicht mehr weiter

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
korrigiere:
//wait until transmission completed
while(!(TWCR &(1<<TWINT))); 

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich bin derweil auch mal mit dem Oszilloskop drangegangen. Beim drücken 
des Tasters kommt eine Frequenz, ganz kurz, auf beiden Kanälen und 
gleichzeitig. Danach ist die Spannung konstant bei 1,5V

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Danach ist die Spannung konstant bei 1,5V

Aber Pull-Up-Widerstände hast du dran?

MfG Spess

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja, 10k auf 5v, bei allen 3 (int, scl,sda)

Autor: Carsten (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Also, ich habe das ganze nochmal mit einem PCA9555D versucht und wieder 
ist es das gleiche. Er hängt bei der while Schleife in der 
Startfunktion.
//wait until transmission completed
while(!(TWCR &(1<<TWINT))); 

Bitte helft mir ich bin voll am verzweifeln. Ich kopiere nur nochmal die 
main, die gesamte .c Datei kommt ini den Anhang.
int main(void){

  // Portsettings
  DDRA  = 0x00;  // PORT A as Input
  DDRB  = 0x00; // PORT B0 as Input
  DDRC  = 0x00;
  PORTC  = 0x00;
  DDRD  = 0xFF;  // PORT  D as Output
  PORTD  = 0x00; // LEDs PORT D red ON

uint8_t bla;

    DDRB &=~ (1<<PB0);                 /* PIN PB0 auf Eingang (Taster)            */
    PORTB = (0<<PB0);                 /* Pullup-Widerstand aktivieren            */

while(1)
{  

    if (PINB & (1<<PB0))
    {
  i2c_init();
 
  if(!(i2c_start(Dev_Address+I2C_WRITE)))
  {   
    PORTD |=(1<<PD4);     //LED an
      i2c_start_wait(Dev_Address+I2C_WRITE);
         
     i2c_write(0xF);

          i2c_rep_start(Dev_Address+I2C_READ);       // set device address and read mode
       
    bla = i2c_readNak();                    // read one byte
          i2c_stop();
         } 
}

return 0;
}

Die LED an PD4 geht nicht wenn ich sie hinter die Startfunktion setze.

Zur Hardware: Ich habe einen ATmega324P20PU und daran habe ich einmal 
einen PCA9555 und einen PCF8574A getestet. Bei beiden tritt das gleiche 
Problem auf. Ich habe SCL, INT und SDA per 10k Pullup Widerstand auf 5V 
gezogen.SDA und SCL sind am ATmega auf PC0 und PC1. INT habe ich mit 
INT0(PD2) verbunden. Es liegen ca 1,5V dauerhaft an SDA und SCL an. Der 
Rest ist eigentlich auch i.O. Ich nutze einen 16 Mhz Quarz, wobei ich es 
auch schon ohne versucht habe....ohne Erfolg.

Bitte helft mir. Ich bin echt mies drauf das das nicht klappt T.T

Grüße und danke schonmal!

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
push

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.