Forum: Mikrocontroller und Digitale Elektronik Expander: Digitaleingänge


von Carsten (Gast)


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-Expander_PCF8574

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#Aufbau_des_TWI

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!

von H.Joachim S. (crazyhorse)


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-Tutorial:_Schieberegister

von Mario G. (mario)


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.

von Carsten (Gast)


Lesenswert?

Habe die Libary kopiert und mir angeschaut. Ist die Abfrage dann so 
richtig?
1
  i2c_init();                //initialisieren
2
3
  if (!(i2c_start()))        //was muss ich da übergeben?
4
    {
5
    i2c_write(0x01);
6
7
    i2c_rep_start();//was muss ich da übergeben?
8
9
    uchk = i2c_readNak(); //wertzuweisung
10
11
    i2c_stop();      //terminierung
12
  }
13
if (uchk)      //wenn uchk wahr, dann ...
14
[...]

von Carsten (Gast)


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?

von Mario G. (mario)


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:
1
i2c_init();
2
i2c_start_wait(0x70+I2C_WRITE);   
3
i2c_write(irgendeinwert);
4
i2c_stop();

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

von Carsten (Gast)


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

von Carsten (Gast)


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?

von Falk B. (falk)


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

von Carsten (Gast)


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

von Falk B. (falk)


Lesenswert?

LIES DEN GOTTVERDAMMTEN ARTIKEL Bitmanipulation!!!

von Mario G. (mario)


Lesenswert?

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

von Carsten (Gast)


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.

von Mario G. (mario)


Lesenswert?

ja

von Carsten (Gast)


Lesenswert?

1
#define Dev_Address  0x70      // device address
2
//[...] P.Fleury auch included
3
int main(void)
4
{
5
  // Portsettings
6
  DDRA  = 0x00;  // PORT A as Input
7
  DDRB  = 0x00; // PORT B0 as Input
8
  DDRD  = 0xFF;  // PORT  D as Output
9
  PORTD  = 0x00; // LEDs PORT D red ON
10
11
uint8_t bla;
12
13
    DDRB &=~ (1<<PB0);                 /* PIN PB0 auf Eingang (Taster)            */
14
    PORTB = (0<<PB0);                 /* Pullup-Widerstand aktivieren            */
15
16
while(1)
17
{
18
      if (PINB & (1<<PB0))// Falls Taster an PIN PB0 gedrueckt...
19
      {
20
            i2c_init();         // init I2C interface
21
       
22
     if(!(i2c_start(Dev_Address+I2C_WRITE)))
23
     {
24
         i2c_write(0xF);    //PIN 0:3 = Eingang
25
                i2c_rep_start(Dev_Address+I2C_READ);        
26
                bla = i2c_readNak();                            
27
                i2c_stop();
28
            }       
29
       }
30
       if(bla & 0x08)                                 PORTD |=(1<<PD4);      //Horn an
31
32
}

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.

von spess53 (Gast)


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

von Carsten (Gast)


Angehängte Dateien:

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
1
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?

von Carsten (Gast)


Lesenswert?

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

danach gehts nicht mehr weiter

von Carsten (Gast)


Lesenswert?

korrigiere:
1
//wait until transmission completed
2
while(!(TWCR &(1<<TWINT)));

von Carsten (Gast)


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

von spess53 (Gast)


Lesenswert?

Hi

>Danach ist die Spannung konstant bei 1,5V

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

MfG Spess

von Carsten (Gast)


Lesenswert?

ja, 10k auf 5v, bei allen 3 (int, scl,sda)

von Carsten (Gast)


Angehängte Dateien:

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.
1
//wait until transmission completed
2
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.
1
int main(void){
2
3
  // Portsettings
4
  DDRA  = 0x00;  // PORT A as Input
5
  DDRB  = 0x00; // PORT B0 as Input
6
  DDRC  = 0x00;
7
  PORTC  = 0x00;
8
  DDRD  = 0xFF;  // PORT  D as Output
9
  PORTD  = 0x00; // LEDs PORT D red ON
10
11
uint8_t bla;
12
13
    DDRB &=~ (1<<PB0);                 /* PIN PB0 auf Eingang (Taster)            */
14
    PORTB = (0<<PB0);                 /* Pullup-Widerstand aktivieren            */
15
16
while(1)
17
{  
18
19
    if (PINB & (1<<PB0))
20
    {
21
  i2c_init();
22
 
23
  if(!(i2c_start(Dev_Address+I2C_WRITE)))
24
  {   
25
    PORTD |=(1<<PD4);     //LED an
26
      i2c_start_wait(Dev_Address+I2C_WRITE);
27
         
28
     i2c_write(0xF);
29
30
          i2c_rep_start(Dev_Address+I2C_READ);       // set device address and read mode
31
       
32
    bla = i2c_readNak();                    // read one byte
33
          i2c_stop();
34
         } 
35
}
36
37
return 0;
38
}

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!

von Carsten (Gast)


Lesenswert?

push

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
Noch kein Account? Hier anmelden.