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!
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
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.
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...
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?
@ 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
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
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.
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.
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
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?
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
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
intmain(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_tbla;
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
return0;
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!