I2C softwaremässig umsetzen
-
hallo zusammen
ich bin gerade an einer ausbildung als elektroniker und arbeite an einem kleineren projekt.
in diesem projekt soll ich mit dem PIC16F876A mit einem temperatursensor (LM75) kommunizieren um dessen werte auszulesen. das ganze soll über I2C funktionieren, jedoch muss ich nun das ganze I2C softwaremässig umsetzen da ich die I2C hardware schon für was anderes brauche.
leider weiss ich nicht was ich alles definieren muss damit ich schlussendlich die c-befehle für I2C gebrauchen kann und es funktioniert. achja, wir arbeiten mit dem Ccs-Compiler in MPLap.
ich hoffe da kann mir jemand ein wenig weiterhelfen
-
Elektroniker schrieb:
jedoch muss ich nun das ganze I2C softwaremässig umsetzen da ich die I2C hardware schon für was anderes brauche.
Warum kannst du nicht beide Slaves am I2C-Master betreiben? Oder ist der I2C-Controller mit einer anderen Hardware-Resource verkuddelt die du brauchst?
-
Ist jetzt aus meiner M16C- Adaption geklaut, funktioniert aber einwandfrei. Man muß nur wissen, daß ich Pins verwendet habe, die kein aktives Hi treiben (Pullup), kann man aber durch Anpassen leicht ändern.
Natürlich ist da nix mit Multimasterbetrieb usw. ist jetzt nur der absolute Grundstock für i2c.
Wieso sind die Pins für i2c eigentlich anderweitig belegt, man kann ja von einer Slaveklasse meist acht oder mehr Bausteine ranhängen und die Hardwareimplementationen können sogar meist Multimasterbetrieb.
Naja, wahtsoever, vielleicht hilft's Dir:#define sda_value p7_0 #define sda pd7_0 #define sck p7_1 #define sck_dir pd7_1 void wait(void) { char i; for ( i=0; i<=8; i++ ) { } } char I2C_stac() // generate start condition { // sck_dir = 0; // SCL High sda = 0; // SDA release sck = 1; wait(); if (sda_value) // beide High { sda = 1; sda_value = 0; // force SDA low wait(); // sck_dir = 1; sck = 0; // force SCL low wait(); return 255; } else return 0; } char I2C_stoc() // generate stop condition { char merk; sda = 1; // Force Low wait(); sck = 1; // SCL High wait(); sda = 0; // SDA release wait(); // sck_dir = 0; if (sda_value) // High merk = 255; else merk = 0; sda_value = 0; // SDA low } char GetAck(char ack) { char merk; sda = 0; // SDA release sck = 1; // SCL hi wait(); merk = (char) sda_value; if (merk) { merk = 255; } sck = 0; // while (sda_value == 0); sda_value = 0; if (ack) { merk = !merk; } return merk; } void PutAck(char ack) { if (ack) { sda = 1; sda_value = 0; } else sda = 0; // SDA release sck = 1; // SCL hi wait(); sck = 0; } char I2C_out(char value, char ack) { char i; for (i=0; i<=7 ;i++ ) { if (value & 128) sda = 0; // SDA release else { sda_value = 0; sda = 1; } sck = 1; // SCL hi value <<=1; wait(); sck = 0; // SCL lo } return GetAck(ack); } char I2C_in(char *value, char ack) { char i; sda = 0; for (i=0; i<=7 ;i++ ) { sck = 1; // SCL hi wait(); *value <<=1; // make place for bit if (sda_value) *value |= 1; sda_value = 0; sck = 0; // SCL lo } PutAck(ack); return 255; } char I2C_adress_device(char dev_adress, char mode, char attempts) { char out; out = (char)((char)((char)( dev_adress & 7) << 1)| 0xa0); // ((dev_adress & 7) <<1) | 0xa0; if (mode) out |= 0x01; // write, ACK expected do { if (I2C_stac()) // send start condition if (I2C_out(out,255)) return 255; else I2C_stoc(); } while (--attempts); return 0; }
-
pointercrash() schrieb:
Man muß nur wissen, daß ich Pins verwendet habe, die kein aktives Hi treiben (Pullup), kann man aber durch Anpassen leicht ändern.
das mit den pull-ups ist doch das einzig richtige. ansonsten kann's kurzschlüsse geben, wenn der master aktive einsen ausgibt (und ein slave z.b. clock-stretching macht).
-
~fricky schrieb:
und ein slave z.b. clock-stretching macht.
Clock-stretching?
Was perverses ist das denn?
-
vielen dank für die auskunft! der code funktioniert nun mit eurer hilfe schon mal ohne fehlermeldungen, jetzt muss ich das nur noch testen und wenns funzt ists perfekt
also die beiden pins SLC und SDA sind bereits durch dot-matrix-driver belegt und darum musste ich den temperatursensor auf zwei andere pins legen.
-
Javaner schrieb:
Clock-stretching?
Was perverses ist das denn?das ist iic-flusskontrolle. damit können slaves den master ausbremsen, wenn sie 'ne verschnaufpause brauchen.