PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PCF8574 - Mal wieder...



teamohnename
14.07.2011, 11:55
Hallo,
auch, wenn das vielleicht schon 1000 Mal erklärt wurde, habe ich das ganze noch nicht richtig verstanden.
Ich möchte einen PCF8574 mit der I²C Lib von Peter Fleury in C ansteuern.
So funktioniert auf jeden Fall:

i2c_start_wait(0x70 + I2C_WRITE);
i2c_write(0xff);
i2c_stop();
Ist ja auch soweit nicht sonderlich schwer. Jetzt möchte ich aber LEDs einzeln aus- und anschalten. Ich kann die Ports ja nicht einzeln setzen. Ich muss immer alle zusammen in Binär bzw. Hex senden. Wenn ich also eine LED setze, weiß ich ja nicht, ob eine andere schon an ist, die würde ich so, wie das oben gemacht wird ja ausschalten. Ich müsste also erst die Ports auslesen und in eine Variable schreiben, dann diese Variable so ändern, dass z.B. das 4. Bit gesetzt oder gelöscht wird. Wie mache ich das? Soweit bin ich schon:

void setPortPCF8574(uint8_t adr, uint8_t port, uint8_t setOrDel) //Adresse, Pin Nr., die gesetzt/gelöscht werden soll, Pin setzen oder löschen
{
i2c_start_wait(adr + I2C_WRITE); //I²C Kommunikation starten (schreiben)
i2c_rep_start(adr+I2C_READ); //erneut starten, lesen
uint8_t ports=i2c_readAck(); //ports einlesen
i2c_stop(); //I²C Kommunikation stoppen

if(setOrDel==0) //wenn Variable 0 ist
{
ports = (ports | (1<<port)); //Pin löschen
}
else
{
ports = (ports ^ (1<<port)); //sonst (z.B. bei 1) Pin setzen
}

i2c_start_wait(adr + I2C_WRITE); //I²C Kommunikation starten (schreiben)
i2c_write(ports); //ports senden
i2c_stop(); //I²C Kommunikation stoppen
}

Damit passieren aber merkwürdige Dinge... Ports löschen funktioniert gar nicht. Setzen funktioniert nur bedingt, ich kann nur in bestimmten Reihenfolgen Ports löschen oder setzen, von daher gehe ich davon aus, dass der Befehl zum ,,manipulieren" der Variable, in denen die Ports gespeichert werden, falsch ist. LEDs sind nur an Pins P4 bis P7 angeschlossen, an P0-P3 Taster, das kommt aber nachher.

Ich hoffe, ihr habt das Problem verstanden!
Vielen Dank für Eure Hilfe schonmal im Vorraus und
Viele Grüße
teamohnename

radbruch
14.07.2011, 12:16
So vielleicht:


if(setOrDel==0) //wenn Variable 0 ist
{
ports = (ports & ~(1<<port)); //Pin löschen
}
else
{
ports = (ports | (1<<port)); //sonst (z.B. bei 1) Pin setzen
}

PICture
14.07.2011, 12:58
Hallo!

Ich kenne Cäh gar nicht, aber einzelne Bits, ohne andere zu beeinflüssen, löscht man mit 0 in AND und setzt mit 1 in OR, was der radbruch angeblich schon in Cäh formuliert hat, was ich aber nicht checken kann. ;)

radbruch
14.07.2011, 13:02
& ist bitweises Und, | ist bitweises Oder, ~(Tilde) bedeutet bitweises Invertieren in Cäh:

http://www.rn-wissen.de/index.php/C-Tutorial#Bit-Operatoren

PICture
14.07.2011, 13:11
Vielen Dank für deine extra Erklärung :D

Für mich ist aber die C-Programiersprache künstlicher als meine eigene KI.

teamohnename
14.07.2011, 13:31
Hallo radbruch,
danke, so funktioniert es schon sehr viel besser, es gibt aber immer noch ein paar Probleme:
So:

setPortPCF8574(0x70,4,1);

_delay_ms(500);
setPortPCF8574(0x70,4,0);
_delay_ms(500);
setPortPCF8574(0x70,4,1);
_delay_ms(500);
setPortPCF8574(0x70,4,0);
_delay_ms(500);
setPortPCF8574(0x70,4,1);
_delay_ms(500);
Blinkt die LED an P4, so, wie es sein sollte.
Hier:

setPortPCF8574(0x70,4,1);
_delay_ms(500);
setPortPCF8574(0x70,5,1);
_delay_ms(500);
setPortPCF8574(0x70,6,1);
_delay_ms(500);
setPortPCF8574(0x70,7,1);
_delay_ms(500);
setPortPCF8574(0x70,7,0);
_delay_ms(500);
setPortPCF8574(0x70,6,0);
_delay_ms(500);
setPortPCF8574(0x70,5,0);
_delay_ms(500);
setPortPCF8574(0x70,4,0);
_delay_ms(500);
hängt sich der ATmega8 aber beim Ausschalten der LEDs auf. So:

setPortPCF8574(0x70,4,1);

_delay_ms(500);
setPortPCF8574(0x70,5,1);

_delay_ms(500);

setPortPCF8574(0x70,6,1);

_delay_ms(500);

setPortPCF8574(0x70,7,1);

_delay_ms(500);


i2c_start_wait(0x70 + I2C_WRITE);
i2c_write(0xff);

i2c_stop();

setPortPCF8574(0x70,7,0);

_delay_ms(500);
setPortPCF8574(0x70,6,0);

_delay_ms(500);

setPortPCF8574(0x70,5,0);

_delay_ms(500);

setPortPCF8574(0x70,4,0);

_delay_ms(500);

gehen die, nachdem alle eingeschaltet wurden, alle ordnungsgemäß aus. Das Programm hängt sich aber nicht auf. Wie gesagt, alles etwas merkwürdig...
Danke und
Viele Grüße
teamohnename