PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Soft I²C HIGH Signal



robo_tom_24
16.06.2012, 13:50
Hallo

Ich hab im Internet eine Software I²C Implementierung gefunden (-> MAIN: 22585 HEADER:22586)
Mein I²C Bus ist auf 3.3V ausgelegt und die Implementierung ist für den 5V Master. Hierfür hab ich externe Pull-Up Widerstände - somit muss ich die internen vom Master ja deaktivieren (auskommentieren):

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void sda_low()
{
I2C_PORT &= ~(1<<SDA); // internen Pull-Up aus
I2C_DDR |= (1<<I2C_DDR_REG_BIT); // Pin von SDA als Ausgang

}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void sda_high()
{
I2C_DDR &= ~(1<<I2C_DDR_REG_BIT); // Pin von SDA als Eingang
//I2C_PORT |= (1<<SDA); // internen Pull-Up an
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
////////////////////////////////////////////////////////////////////////////////////////////

#define I2C_SCL_LOW I2C_PORT &= ~(1 << SCL) // Clock Low Output
#define I2C_SCL_HIGH I2C_PORT |= (1 << SCL) // Clock High Output

Ist das richtig so? Oder muss ich da im eigentlichen Programmcode noch ändern?

Klebwax
16.06.2012, 22:34
Hallo

Ich hab im Internet eine Software I²C Implementierung gefunden (-> MAIN: 22585 HEADER:22586)
Mein I²C Bus ist auf 3.3V ausgelegt und die Implementierung ist für den 5V Master. Hierfür hab ich externe Pull-Up Widerstände - somit muss ich die internen vom Master ja deaktivieren (auskommentieren):

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void sda_low()
{
I2C_PORT &= ~(1<<SDA); // internen Pull-Up aus
I2C_DDR |= (1<<I2C_DDR_REG_BIT); // Pin von SDA als Ausgang

}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void sda_high()
{
I2C_DDR &= ~(1<<I2C_DDR_REG_BIT); // Pin von SDA als Eingang
//I2C_PORT |= (1<<SDA); // internen Pull-Up an
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
////////////////////////////////////////////////////////////////////////////////////////////

#define I2C_SCL_LOW I2C_PORT &= ~(1 << SCL) // Clock Low Output
#define I2C_SCL_HIGH I2C_PORT |= (1 << SCL) // Clock High Output

Ist das richtig so? Oder muss ich da im eigentlichen Programmcode noch ändern?

Ich kenne zwar den Prozessor nicht, im gezeigten Code kann ich aber nichts von Pullups erkennen. Ich sehe da nur Daten und Direction-Bits. Die Komentare scheinen mir falsch und machen auch keinen Sinn, die Pullups sind immer an, nur der Treiber wird an- und ausgeschaltet.

Was ich aber sehe, ist daß SCL und SDA unterschiedlich behandelt werden. SCL wird nicht über das Direction-Bit als "quasi Opencollector Ausgang" gesteuert, sondern direkt. Während man mit externen Pullups von wenigen k Ohm gegen 3,3V die internen Pullups von mehren 10k gegen 5V noch neutralisieren könnte, geht das so garnicht.

Was man aus diesen Macros aber sehen kann ist, das dieser Code in die Kategorie "works mostly" gehört. Sowohl SDA als auch SCL können und werden sowohl vom Master als auch vom Slave angesteuert. Bei SCL nennt man das Clock stretching. Wie das funktioniert, steht in der I2C Spec. Mit den gezeigten Macros für SCL läßt sich das nicht implementieren. Ich würde den Code daher nicht verwenden.

MfG Klebwax

robo_tom_24
17.06.2012, 11:32
Mahlzeit!

Der µC ist ein Mega32 auf dem RN-Control....

Gibt es sonst noch gute Soft I²C Master Lösungen? (Ja ich kenn Google, und die von Fleury ist teilweise in Assembler geschrieben von dem ich 0 Ahnung hab ;) )