In meinem Universitätsstudium haben wir also einige Quellcode-Beispiele erhalten, die mit einem OPT3001-Lichtsensor arbeiten. Unser Studium konzentriert sich nicht auf ingenieurwissenschaftliche Aufgaben im Allgemeinen, sondern es handelt sich um eine Vorlesung, die einige der Elektrotechnik-Fächer berührt. Ich studiere Physik, falls sich jemand fragt.
Ich bin mit den Kommunikationsprotokollen der Elektrotechnik nicht vertraut, habe aber online einige Anleitungen zur I2C-Kommunikation gelesen, um mir zu helfen, den angegebenen Quellcode zu verstehen. Ich habe nur einige Kenntnisse in der Android-Programmierung - aber auch Autodidakt.
Ich würde gerne mehr verstehen, deshalb frage ich Sie, ob Sie mir helfen können. Ich werde nur eine Funktion des gesamten Codes kopieren, damit es nicht zu lang wird, und wenn Sie mich mit einigen Kommentaren zu jeder Zeile anleiten können, was passiert, bin ich wirklich dankbar!
void UpdateLight(void)
{
uint8_t error = 0;
// start conversion
I2C_Start();
error |= I2C_Write(OPT_ADDR_W);
error |= I2C_Write(OPT_CONFIG_REG);
error |= I2C_Write(OPT_CONFIGURATION_H);
error |= I2C_Write(OPT_CONFIGURATION_L);
I2C_Stop();
// wait for conversion
_delay_ms(150);
// set result register
I2C_Start();
error |= I2C_Write(OPT_ADDR_W);
error |= I2C_Write(OPT_RESULT_REG);
I2C_Stop();
// read data and update scratchpad
I2C_Start();
error |= I2C_Write(OPT_ADDR_R);
if (error == 0)
{
scratchpad[1] = I2C_Read(1);
scratchpad[0] = I2C_Read(0);
}
else
{
// report error value
scratchpad[1] = 0xFF;
scratchpad[0] = 0xFF;
}
I2C_Stop();
}
Einige Definitionen, die im obigen Code verwendet werden:
volatile uint8_t scratchpad[9] = {0x50, 0x05, 0x0, 0x0, 0x7f, 0xff, 0x00, 0x10, 0x0}; // initial scratchpad
Dies ist an meiner Universität nicht erforderlich, es ist nur eine Übung, bei der es vom Professor vorgefertigt wurde, und alles, was wir tun müssen, ist, diesen Lichtsensor zu verwenden, um die Beleuchtung zu messen. Aber ich wollte mir möglichst noch etwas beibringen.
Ich kenne das Datenblatt von OPT3001, daher verstehe ich die erforderlichen Adressen ein wenig, aber auch nicht vollständig.
Hier ist ein Link zum Datenblatt, falls jemand benötigt: OPT3001-Datenblatt
Dankbar für jede Hilfe/Kommentar/Eingabe. Hoffe, das gilt immer noch für die StachExchange-Regeln - wusste nicht, wo ich diese Frage sonst posten sollte.
Es scheint sehr selbstverständlich zu sein, aber das muss meine Bestätigungsverzerrung sein ;D
Erstens sind die Zeilen, die mit // beginnen, Kommentare. Ganz zu Ihrem Vorteil. Ebenso wie jeder Text nach einem # (das hier nicht verwendet wird).
I2C Start hand shake
Write device's Address
Write device's configuration address
Write the higher byte of the configuration desired
Write the lower byte of the configuration desired.
I2C Stop hand shake
Wait a bit.
Start
write device address
switch to device's results address
stop
Start
Read from device address
if no error
read the first byte from the results
read the second byte
Stop.
Beachten Sie, dass der OPT3001 16-Bit-Register hat. Das sind zwei 8-Bit-Bytes. Standard i2c arbeitet in 8-Bit-Bytes. Sie müssen also zwei Bytes lesen, um die vollständigen Ergebnisse zu erhalten. Typischerweise werden bei einer höchstwertigen Byte-Reihenfolge die höheren Bits (15–8) als das hohe/erste Byte bezeichnet.
I2C funktioniert, indem es das Gerät im Schreibmodus adressiert, ihm sagt, dass es zu einem Register/einer internen Adresse wechseln soll, und dann von diesem Punkt aus schreibt oder liest. Dieses Gerät ist nicht anders. Das sind die Grundlagen von I2C
Ein typisches Muster für die Kommunikation mit I2C-Geräten besteht darin, dass man zum Schreiben von Informationen auf das Gerät einen "I2C-Start" an den Bus ausgeben sollte, ein Byte ausgeben sollte, das besagt, dass man auf ein bestimmtes Gerät schreiben möchte, zusammen mit einem oder zwei Bytes, die es identifizieren Adresse innerhalb des Geräts, das man schreiben möchte, und dann folgen all dem die zu schreibenden Daten. Nach all dem sollte man dem Bus ein "I2C Stop" ausgeben. Jedes Mal, wenn ein Byte auf ein I2C-Gerät geschrieben wird, meldet der Controller, ob das Gerät angezeigt hat, dass es es empfangen hat. Wenn das Gerät keinen erfolgreichen Empfang irgendeines Bytes anzeigt, sollte die gesamte Operation als fehlgeschlagen angesehen werden.
Um von I2C-Geräten zu lesen, beginnt man mit dem "Schreiben" der Adresse, von der man lesen möchte, unter Verwendung des obigen Verfahrens, aber ohne irgendwelche Daten nach der Adresse zu senden. Danach sollte man ein "I2C Stop" und "I2C Start" ausgeben, gefolgt von einem Byte, das besagt, dass man das Gerät lesen möchte, anstatt es zu schreiben. Darauf sollten wiederum Anfragen zum Auslesen der Daten und dann ein „I2C Stop“ folgen. Wie allgemein implementiert, muss der Controller der Byte-Lese-Routine anzeigen, ob jedes angeforderte Datenbyte das letzte sein wird. Es scheint, dass diese spezielle Read-Byte-Routine einen Parameterwert von 1 verwendet, um anzuzeigen, dass weitere Daten folgen werden, und 0, um die letzte Anforderung für eine Transaktion anzuzeigen.
Ich weiß nicht, wie genau Ihre Implementierung alles macht, aber es sieht so aus, als würde es dem oben beschriebenen Muster folgen. hoffentlich hilft dir das weiter.
uint8_t error = 0; //set error to 0, clear it
// start conversion
I2C_Start(); //call function to send start bit onto I2C bus to signify start of transaction
error |= I2C_Write(OPT_ADDR_W); //write device id of slave onto bus with write bit set remember that I2C is 7 bits with the last bit for read or write (well there are 10bit but lets assume this is 7 bit.
error |= I2C_Write(OPT_CONFIG_REG);//put the address of the 16bit config register in the slave onto the bus
error |= I2C_Write(OPT_CONFIGURATION_H);//put the high byte of the config register onto the bus to set it
error |= I2C_Write(OPT_CONFIGURATION_L);//put the low byte of the config register onto the bus to set it
I2C_Stop();//put the stop bit onto the I2C bus to signify the end of the transmission
// wait for conversion
_delay_ms(150); //wait for your slave device to do what it does
// set result register
I2C_Start(); //start another transaction on the I2C bus
error |= I2C_Write(OPT_ADDR_W); //put the device id of slave on the bus again with write bit set
error |= I2C_Write(OPT_RESULT_REG);//send slave the address for the result register, you are in effect prepping the device by giving it this address, in the next step you will read from it
I2C_Stop();//put the stop bit out on the bus again
// read data and update scratchpad
I2C_Start();//now put the start bit out again, I can't remember this may technically be a restart
error |= I2C_Write(OPT_ADDR_R); //put the device ID of the slave out onto the bus with the read bit set. You are telling the sensor I now want to read the 16bit result value from you
if (error == 0)//if none of the previous function calls resulted in any errors at all
{
scratchpad[1] = I2C_Read(1);//read 1 byte from the I2C bus and store in scratchpad
scratchpad[0] = I2C_Read(0);//read 2nd byte from the I2C bus and store in scratchpad
}
else
{ //whoops you had some kind of error previosly
// report error value
scratchpad[1] = 0xFF;//set scratch pad to known value
scratchpad[0] = 0xFF;//set scratch pad to known value
}
I2C_Stop();//put stop bit out to end transaction no matter what otherwise slave will think transaction never ended.
}
MathieuL
David Kasabji
Paebbels
restart
Handshake zwischen den Richtungswechseln.