I2c-bit-banging-Programmierung mit C
Bin ich zu schreiben versucht, einen c-code für I2c unter Verwendung von bit-banging. Ich habe überarbeitet, den Code von wiki(http://en.wikipedia.org/wiki/I%C2%B2C). Aber ich bin nicht in der Lage um ein Ergebnis zu erhalten. Gemäß meinem Verständnis der code im wiki ist nicht korrekt. Viele Veränderungen die ich gemacht habe, aber eine der wichtigsten änderung, die ich gemacht,wo wiki scheiterte sagen, richtig ist tagged/label, die Zeile mit /TBN/. Mein code ist unten
//Hardware-spezifische support-Funktionen, die angepasst werden MÜSSEN:
#define I2CSPEED 135
#define SCL P0_0
#define SDA P0_1
void I2C_delay() { volatile int v; int i; for (i=0; i < I2CSPEED/2; i++) v; }
bool read_SCL(void); //Set SCL as input and return current level of line, 0 or 1
bool read_SDA(void); //Set SDA as input and return current level of line, 0 or 1
void clear_SCL(void); //Actively drive SCL signal low
void clear_SDA(void); //Actively drive SDA signal low
void Set_SDA(void); //Actively drive SDA signal High;
void Set_SCL(void); //Actively drive SCL signal High
void Set_SCL(void)
{
//make P0_0 as OutputPort
SCL = 1;
}
void Set_SDA(void)
{
//make P0_1 as OutputPort
SDA = 1;
}
void clear_SCL(void)
{
//make P0_0 as OutputPort
SCL = 0;
}
void clear_SDA(void)
{
//make P0_1 as OutputPort
SDA = 0;
}
bool read_SCL(void)
{
//make P0_0 as InputPort
return SCL;
}
bool read_SDA(void)
{
//make P0_0 as InputPort
return SDA;
}
void i2c_start_cond(void) {
//set SDA to 1
Set_SDA();/*TBN*/
set_SCL();
//SCL is high, set SDA from 1 to 0.
I2C_delay();
clear_SDA();
I2C_delay();
I2C_delay();
clear_SCL();//make SCL Low for data transmission
started = true;
}
void i2c_stop_cond(void){
//set SDA to 0
clear_SDA();
I2C_delay();
//SCL is high, set SDA from 0 to 1
Set_SCL();/*TBN*/
I2C_delay();
Set_SDA();
}
//Write a bit to I2C bus
void i2c_write_bit(bool bit) {
if (bit) {
Set_SDA();/*TBN*/
} else {
clear_SDA();
}
I2C_delay();
clear_SCL();
}
//Read a bit from I2C bus
bool i2c_read_bit(void) {
bool bit;
//Let the slave drive data
read_SDA();
I2C_delay();
//SCL is high, now data is valid
bit = read_SDA();
I2C_delay();
clear_SCL();
return bit;
}
//Write a byte to I2C bus. Return 0 if ack by the slave.
bool i2c_write_byte(bool send_start,
bool send_stop,
unsigned char byte) {
unsigned bit;
bool nack;
if (send_start) {
i2c_start_cond();
}
for (bit = 0; bit < 8; bit++) {
i2c_write_bit((byte & 0x80) != 0);
byte <<= 1;
}
nack = i2c_read_bit();
if (send_stop) {
i2c_stop_cond();
}
return nack;
}
//Read a byte from I2C bus
unsigned char i2c_read_byte(bool nack, bool send_stop) {
unsigned char byte = 0;
unsigned bit;
for (bit = 0; bit < 8; bit++) {
byte = (byte << 1) | i2c_read_bit();
}
i2c_write_bit(nack);
if (send_stop) {
i2c_stop_cond();
}
return byte;
}
Dieser code ist für einen master in einem bus. Ich bitte die Experten zu überprüfen, meinen code und lassen Sie mich wissen, mein Fehler.
die I2C-clock stabil sein Rad, als bus-Aktivität, so unberechenbar timing hemmen das Kind aus verriegeln auf das signal. Ihre Nutzung von Funktionsaufrufen wird im Ergebnis nur solche erratischen timing. I. E. alle Elemente sollten Makros aneinander gereiht, nicht nur die eigentliche manipulation der i/o-pins.
die Daten müssen stabil sein, für jedes bit, während die Taktleitung übergänge hoch und hinten zu niedrig. START ist die Uhr hoch, während Daten, die übergänge von hohen zu niedrigen STOP-Uhr hoch, während Daten, die übergänge von low nach high. Es gibt bestimmte Zeiten für jeden Teil der Kommunikation.
jedes Gerät im bus muss eine Probe von der Datenleitung mindestens zweimal (und vorzugsweise 16 mal) für jede taktperiode um sicher zu sein zu erkennen, ein start-oder stop-event.
der master ist immer der Antrieb der Uhr, wenn der master will, dass jede Kommunikation mit einem slave. Der Meister der Eingeweihten immer die Kommunikation, die meist mit einem START, slave-Adresse, STOP slave xmits ack nach jedem byte, Master xmits STARTEN, Befehl, zu STOPPEN. slave xmits ack nach jedem byte, Wenn die Daten gesendet werden, um die slave -, master xmits START-DATEN...DATEN HALT nach jedem byte, slave xmits ACK. Wenn Sie Daten senden slave (nach slave erhält Befehl zu senden, master xmits START slave xmits Daten...Daten -, master-xmits zu STOPPEN, wenn jede Kommunikation nicht verstanden wird, dann wird NAK gesendet, statt ein ACK
InformationsquelleAutor user3844884 | 2014-07-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es gibt eine Menge von flat-out falsch-Informationen in den Kommentaren.
Zuerst, Ihre read_bit () - Funktion nie schaltet die Uhr. Das ist wohl das problem, zusammen mit @user3629249 Kommentar, dass der master sendet ein ACK-bit nach jeweils 8 bits vom slave. Sie müssen diese Adresse in Ihrem read_byte () - Funktion.
Zweite: I2C kümmert sich nicht um clock-jitter; es definiert nur, dass die Daten stabil sein muss, wenn die Uhr fällt. Es wird einige Nanosekunden auf beiden Seiten der Uhr Kante, wo die Daten nicht verändern darf, aber das ist nicht das Thema hier. I2C-slaves nicht "lock on", um die Uhr. In der Tat ist die I2C-Spezifikation nicht definieren eine untere Grenze von zu hohen oder zu niedrigen SCL-Zeiten. Sie könnte unter Umständen warten, Tage oder Jahre, zwischen Uhr tickt. SMB hat definieren Sie ein Zeitlimit, aber das ist nicht dein problem hier.
Schließlich: oversampling nicht wirklich für I2C. Lesen Sie die bit-ein paar mal, um sicherzustellen, es hat sich nicht geändert, aber eine richtig funktionierende I2C-slave werden nicht die Daten zu verändern, bis irgendwann nach der steigenden Flanke des SDA-signal, das viele Tausende von Nanosekunden entfernt von der kritischen fallende Flanke. I2C ist nicht asynchron, wie Sie Ihre übliche serielle Schnittstelle/UART.
InformationsquelleAutor akohlsmith
Erste bit-banging I2C ist viel komplizierter als bit-banging SPI.
Also erstmal würde ich ein SPI-EEPROM wie der 25AA1024 und versucht mein bit-banging skills.
Dann versuchen, eine einfache Adadfruit I2C-Gerät wie dieses
https://www.adafruit.com/products/1855
Es erfordert nur I2C aus und du einfach port der Arduino-code zu C oder C#.
Ich weiß, dass das USB-Gerät Nusbio Implementierung von I2C-und SPI bit-banging in C# geschrieben.
Finden Sie Ihre source-code in https://github.com/madeintheusb/Nusbio.Samples
InformationsquelleAutor DesdmondMantes
Müssen Sie implementieren
P0_0
undP0_1
irgendwie. Die Anrufe, die Sie markiert schließlich beinhalten Sie, und ich bin nicht zu sehen, Sie in Ihrem code nohow.Wenn Sie dieses entwickeln, die auf einer realen hardware dann, um zu beeinflussen, entsprechende Stifte in Ihre hardware, die Sie benötigen, implementieren P0_0 und P0_1 Makros mit code Zugriff auf das jeweilige Steuerelement Register zur Steuerung der logischen Ebenen, auf diese beiden Zeilen.
Ich kann Euch nur sagen, dass ich früher einmal einen solchen code, schien es wie das Ihre, damit es funktioniert für mich in einem echten hardware. Ich habe es in einigen Gerät auf Allgemeinen I/O-ports statt der I2C-controller. Für weitere überlegungen, die ich beraten Sie verbinden die Reale Belastung für die bus -, real-I2C-slave, prüfen, wie es funktioniert, und dann Fragen stellen, insbesondere Fragen, wenn überhaupt.
InformationsquelleAutor Ruslan Gerasimov
InformationsquelleAutor FrankP