Hallo, ich habe ein Problem mit meinem I2C Bus in Verbindung mit einem D/A Wandler. Dies ist mein erstes Projekt mit einem I2C Bus. Ich verwende einen Mircochip PIC18F45K22 µC. Über den I2C Bus versuche ich 3 ICs anzusteuern. RTCC MCP7941 EEPROM 24AA64 D/A Wandler MCP4725 und optional DAC6571 Im ersten Versuch hab ich die PullUp Widerstände an SCL und SDA vergessen. Da ging erstmal gar nix, hab ich über die Suchfunktion aber lösen können. Habe an SCL und SDA jeweils ein 2,2k als PullUp eingelötet. Die RTCC und das EEPROM funktionieren jetzt super. Nur mit dem D/A hab ich meine Probleme. Ich kann einfach keinen Werte für die Ausgangsspannung vorgeben. Habe deswegen auch schon einen anderen D/A verwendet. siehe oben. Diese beiden D/A sind von der Pinbelegung identisch. Den A0 Adresspin hab ich auf Masse gelegt. VDD hängt an 5V, VSS an GND, Vout über 10k an Masse. Ich messe dann mit dem Multimeter den Spannungsabfall über den 10k Widerstand. Dieser bleibt jedoch konstant bei ca. 10mV. Ich bekomme von D/A einfach kein ACK. Da die anderen beiden ICs funktionieren, gehe ich davon aus, dass die Software an sich funktionieren sollte. Ablauf: Start Byte 1 Adresse Byte 2 MS Byte Byte 3 LS Byte Stop Ohne meine Timeout Funktion hängt sich die Software auf, da ich keine Bereitschaft vom D/A bekomme. Die beiden anderen ICs bräuchten den Timeout nicht. Beim 4725 hab ich auch die Wiederholung von Byte 2 und 3 probiert. Jedoch alles ohne Erfolg. Was kann man denn noch falsch machen, dass der IC einfach nicht läuft? Ich hoffe ihr könnt mir helfen. BOOLEAN i2c_ready(BYTE I2C_IC) { int1 ack; i2c_start(I2C_INT); // Startbit Senden ack = i2c_write(I2C_INT,I2C_IC); // ControlByte senden und ACK Bit abfragen i2c_stop(I2C_INT); // Stopbit senden return !ack; // Statusbit zurückgeben } int i2c_schreiben(int Bytes) { i2c_error=FALSE; // Merker I2C Fehler zurücksetzen i2c_timeout=0; // Zähler I2C zurücksetzen while(!i2c_ready(I2C_DA_OUT[0])){if (i2c_error){break;}} // warten bis IC bereit nach 250ms Fehler => Abbruch if (!i2c_error){ // Wenn Bus bereit i2c_start(I2C_INT); // Startbit senden for (i=0; i<Bytes; i++){i2c_write(I2C_INT,I2C_DA_OUT[i]);} // alle Bytes senden i2c_stop(I2C_INT); // Stopbit senden I2C_Bytes=0; // Anzahl Bytes auf Null setzen (=Merker ob senden ja/nein) } return i2c_error; } #int_timer2 // Interrupt Routine für Timer 2 void Takt_ISR() { if (!Tasten_Enable){ // wenn Taste gedrückt wurde if (--int_count_Tasten == 0){ // 300 ms abgelaufen - drücken wieder bearbeiten int_count_Tasten = INT_TASTER; // Zähler zurücksetzen Tasten_Enable = TRUE;}} // Tasten wieder frei geben if (!Analog_Enable){ // wenn Analogeingang gelesen wurde if (--int_count_Analog == 0){ // 300 ms abgelaufen - nächsten Analogwert lesen int_count_Analog = INT_ANALOG; // Zähler zurücksetzen Analog_Enable = TRUE;}} // Analogeingang wieder frei geben if (!RTCC_Enable){ // wenn Uhrzeit gelesen wurde if (--int_count_RTCC == 0){ // 500 ms abgelaufen - nächste Uhrzeit lesen int_count_RTCC = INT_UHRZEIT; // Zähler zurücksetzen RTCC_Enable = TRUE;}} // Uhrzeit wieder frei geben if(++i2c_timeout==250){i2c_error=TRUE;} // I2C Timeout } Edit: ich verwende den CCS Compiler und die Funktionen i2c_start(); i2c_stop; i2c_write sind dort vordefinierte funktionen. I2C_INT ist der Stream (es gibt 2 I2C Schnittstellen), ja und der D/A hängt am richten I2C Bus. Mit Multimeter die Widerstände nachgemessen. :)
Wenn ich einen neuen I2C-Baustein in Betrieb nehme, bastel ich mir
erstmal eine Funktion, die den Bus scannt.
Etwa so
loop über alle 128 Adressen {
Start
write Adresse
Stop
wenn ACK, Chip gefunden
}
So kann man leicht überprüfen, ob die Adressen stimmen und der Chip
lebt.
MfG Klaus
Hallo Klaus, vielen Dank für den Tipp, hab ich gleich mal ausprobiert. Erst war ich überrascht warum ich bei so viele Adressen ein ACK bekommen habe. Dann wars mir klar jedes IC sendet auf write und read ein ACK. So nun hab ich folgendes zurück bekommen: 160 => EEPROM 174 => RTCC (EEPROM) 222 => RTCC (SRAM) 224 => ?? keine Ahnung wer das ist 152 => D/A keine Antwort 144 => D/A Broadcast Adresse auch keine Antwort Jetzt bin ich etwas verwirrt. Ich habe keinen 4. IC an meinem Bus hängen. Also welcher IC anwortet mit ACK bei der 4. Adresse? Dachte erst die Adresse vom D/A wurde falsch im Datenblatt angegeben, aber mit der Adresse lässt sich der Analogwert auch nicht verstellen.
Hi, pass auf, denn deine DAs haben unterschiedliche Adressen! Warum gibs du uns eingendlich nicht die richtigen Adressen, könnte man besser überfliegen. I2C Adr. sind nur 7Bit oder 10Bit lang! MCP4725 Adr: b 1100xxa bei dir ist sie (a= 0) b 1100xx0 wie die A2 + A1 stehen, hast du ja nicht gesagt. Ergibt einen Adr.Raum von 96 - 102! DAC6571 Adr: b 100110a bei dir ist sie (a= 0) b 1001100 Ergibt einen Adr von 76! also schau noch mal in die Schaltung und prüfe sie! Beim Broadcast würd ich vorsichtig sein mit Antworten. KA! Stephan
Hallo Stephan, die Adressen: MCP4725 RS Bestellnummer: 669-6290, Teilnummer: MCP4725A0T-E/CH PIN A0 liegt an GND Datenblatt Seite 15 müsste mit der Teilnummer die A2 und A1 "0" sein. Adresse somit 0b11000000 = dezimal 192 Dieser IC ist gerade nicht eingelötet. DAC6571 RS Bestellnummer: 662-1448, Teilenummer: DAC6571IDBVTG4 PIN A0 liegt an GND Datenblatt Seite 15 gibt es 2 Adressen, IC und broadcast 0b10010000 IC = dezimal 144 0b10011000 broadcast = dezimal 152 hab meine Defines nicht mit angegeben: #define I2C_W_EEPROM 0b10100000 // dezimal 160 #define I2C_W_D_A 0b11000000 // dezimal 192 #define I2C_W_D_A_2 0b10010000 // dezimal 144 #define I2C_W_RTCC_E 0b10101110 // dezimal 174 #define I2C_W_RTCC_S 0b11011110 // dezimal 222 ich hab halt in der Software die Konstanten ausgetauscht um die beiden D/A's anzusprechen. Aktuell ist der DAC6571 verbaut, weil der MCP4725 nicht funktioniert hat und ich einfach nen anderen ausprobieren wollte, nachdem ich den IC 2x getauscht habe. Habe dann weil der DAC6571 auch nicht auf seiner Adresse antwortet mit der Broadcast probiert. Mitd er Lösung von Klaus hab ich ja auch antworten von den IC's bekommen. Code: void i2c_Adr_check() { int1 ack; for (i=0; i<255; i++){ i2c_start(I2C_INT); // Startbit Senden ack = i2c_write(I2C_INT,i); // ControlByte senden ACK Bit abfragen i2c_stop(I2C_INT); // Stopbit senden if (!ACK){fprintf (RS_CONTROL, "Adresse: %03u vorhanden ",i);} delay_ms(10); } } aus dem Compiler Manual zu i2c_write: This function returns the ACK Bit. 0 means ACK, 1 means NO ACK, 2 means there was a collision if in Multi_Master Mode. This does not return an ACK if using i2c in slave mode nur antwortet eben ein IC mit der ADR: 224 der gar nicht vorhanden ist. und der D/A antwortet weder bei 144 noch bei 152. Andi
Hi,
>Dies ist mein erstes Projekt mit einem I2C Bus.
Bitte lerne es gleich richtig und kennzeichne deine defines für die
Chips nicht als Adressen! (zb. I2C_W_EEPROM)
I2C Adr. sind nur 7Bit oder 10Bit lang!
1 | if (!ACK)... |
Das ist ein Schreibfehler hoffe ich, aber sonst ok. Deine Funktion gibt halt W und R Kommandos an. schreib einfach:
1 | ..."Adresse: %03u vorhanden ",i>>1);} |
dann bekommst du auch gleich die richtigen Adressen. Ich setzte hier den DAC7571 ein und der lief bei mir sofort. Prüfe noch mal ob du nicht doch einen Kurzschluss bei dem DAC gemacht hast. Stephan
Und nimm Hex, bei Dezimal sieht kein Schwein durch, welches Bit da nun gesetzt ist und welches nicht. [quote]VDD hängt an 5V, VSS an GND, Vout über 10k an Masse[/quote] Der Widerstand könnte sogar schon zu klein sein. Miss mal ohne R von OUT nach GND.
Guten Morgen, ok ich bin einfach blind gewesen. Hab den Fehler gefunden. Am D/A sind SCL und SDA vertauscht. Das kann also so nicht gehen :( Jetzt mal schaun ob ich das noch drehen kann. Danke für die anderen Tipps werde die gleich mal umsetzen. Bleibt noch eine Frage, ich habe den D/A nun ausgelötet, wobei mir dann die vertauschten Leitungen beim Nachmessen aufgefallen sind. Danach habe ich nochmal alle Bus Adressen geprüft. Es bleibt noch die Adresse: 0b1110000 0x70 Diese Antwortet auch mit einem ACK, ich weiß nur nicht wer das sein soll. Andi
Dann nehm ein Baustein raus, teste die Adresse und dann den nächsten. Bis du weiß wer es ist.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.