www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik i2c Slave Problem


Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe einen Sensor mit dem I2C Bus, den ich abfragen möchte.
Hier ist mein Beispielprogramm:
$regfile = "M8def.dat"       
$crystal = 16000000                                        
$hwstack = 32                                               
$swstack = 10                                               '
$framesize = 40                                            
$baud = 9600


Dim Lesen1 As Byte


'SDA und SCL definieren
Config Sda = Portc.4
Config Scl = Portc.5

I2cinit


I2cstart
I2cwbyte &H54h
I2cwbyte &HB6
I2crbyte Lesen1 , Nack                                  
I2cstop

Print Err


Print "gelesen: "
Print Lesen1


End

Die Ausgabe sieht immer so aus:
----------------
1
gelesen:
255
----------------

Datenblatt des Sensors:
www.captured-dreams.de/temp/TSEV01C_Application_Note_0_6.pdf


Hat jemand eine Idee, was ich falsch mache? Ich vermute bei der 
Adressierung ist etwas falsch.

Danke!

Autor: John Small (linux_80)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
guten abend gemeinde.

ich habe eine frage bezüglich dem beschreiben von registern.
über meinen mikrocontroller möchte ich werte aus meinem sensor über I2c 
auslesen.
das ganze ist ein beschleunigungssensor von bosch (SMB380) und der 
controller ist der Atmega1281.lese ich nicht veränderbare register 
aus,passt das alles.ich nutze die I2c-ansteuerung von Peter Fleury.

mein problem ist,dass mir ziemlich schwankende beschleunigungswerte 
ausgibt,obwohl dieser eigentlich fest montiert ist.die werte schwanken 
so in einer spanne von ca. 30dezimal.

meine vermutung ist,dass ich aus versehen bei der einstellung des 
registers für den messbereich (register 0x14) etwas falsch gemacht 
habe.in diesem register sind die obersten 3 bit (bit 7:5) für wichtige 
kalibrierungen nötig und dürfen nicht beschrieben werden.

leider habe ich dies wahrscheinlich mit meinem quellcode

i2c_init();       // Bus initialisieren
i2c_write(0x14);  // Register auswählen
i2c_write(0x06);  // Daten reinschreiben
i2c_stop();       // Busverbindung beenden

getan.

im user manual steht:
"Bits 4,6 and 7 of register address 0x14 do contain critical sensor 
individual calibration data which must not be changed or deleted by any 
means.
In order to properly modify address 0x14 for range and(or bandwidth 
selection using bits 0,1,2,3 and 4, it is highly recommended to read-out 
the complete byte,perform bit-slicing and write back the complete byte 
unchanged bits 5,6 and7.Otherwise the reported acceleration data may 
show incorrect results."

meine frage ist nun ganz einfach:

wie stelle ich das an was in dem 2.absatz des auszuges aus dem user 
manual steht????also nur einzelne bits ändern und die bits 5,6 und 7 
nicht "anfassen"!

im forum bei der sensorkommunikation über spi standen so befehle wie:

bit_setzen(data,(1<<5)); -> ist das bei i2c ähnlich?

bin über jede hilfe dankbar!!!

Autor: ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
guten morgen.
kann mir hier niemand zu oben genannten problem einen tipp geben?

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
reg = ausgelesenes Einstellungsregister


reg2write = reg & 0b11100000;
reg2write = reg | 0b000XXXXX;

mit XXXXX die gewünschten Einstellungen

gibt wahrscheinlich auch noch bessere Möglichkeiten...

Autor: ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke erstmal für die antwort.

ich habe mir das so gedacht:

uint8_t aendern;
{
startI2c(0x70);                writeI2c(0x14);
rep_startI2c(0x71);
aendern = readAckI2c();
aendern &=~((1<<4)|(1<<2)|(1<<1)); // meine vorzunehmenden Einstellungen
writeI2c(aendern);
stopI2c();
}

mir stellt sich jetzt nur die Frage ob ich nach dem Auslesen des 
Registers und Ändern gleich einen write-Befehl anschließen kann,oder 
erst noch stop-Befehl und dann nochmal von vorn: start usw.??

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fokussieren wir mal diesen Design-Hinweis:
which must not be changed or deleted
und
it is highly recommended to read-out
the complete byte,perform bit-slicing and write back the complete byte
Damit dürftest du mit deiner Aktion
i2c_init();       // Bus initialisieren
i2c_write(0x14);  // Register auswählen
i2c_write(0x06);  // Daten reinschreiben
i2c_stop();       // Busverbindung beenden
Genau das gemacht haben was niemals hätte passieren dürfen:
du hast auf die oberen bits einfach Nullen geschrieben.
Besser wäre es entsprechend dem Datenblatt, erst das Register zu lesen, 
diesen Wert zu ändern, und dann wieder zurückzuschreiben.
uint8_t r14:

i2c_init();       // Bus initialisieren
i2c_write(0x14);  // Register auswählen
r14 = i2c_read();   // Daten auslesen -- wie auch immer diese funktion
i2c_stop();       // Busverbindung beenden

r14 &= 0xE0; // obere Bits behalten
r14 |= 0x06; // Daten dazu

i2c_init();       // Bus initialisieren
i2c_write(0x14);  // Register auswählen
i2c_write(r14);   // Daten reinschreiben
i2c_stop();       // Busverbindung beenden

Allerdings sind die schwankenden Werte doch eigenartig...
Lies doch mal das Versionsregister 0x01 (al_version und ml_version) aus.
Bekommst du dort richtige und stabile Werte?

BTW:
>... habe.in ...
>... ist,dass ...
Mach doch bitte nach Satzzeichen ein Leerzeichen, das erhöht die 
Lesbarkeit (mal abgesehen von der Groß- u. Kleinschreibung) ungemein.

EDIT:
> nach dem Auslesen des Registers und Ändern gleich
> einen write-Befehl anschließen kann
Probiers mal mit einem Repeated-Sart...
Ist dein i2c_init() das selbe wie ein i2c_start()?
/*************************************************************************
 Initialization of the I2C bus interface. Need to be called only once
*************************************************************************/
void i2c_init(void)
:
:

/*************************************************************************
  Issues a start condition and sends address and transfer direction.
  return 0 = device accessible, 1= failed to access device
*************************************************************************/
unsigned char i2c_start(unsigned char address)
:

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ingo wrote:
> danke erstmal für die antwort.

> aendern &=~((1<<4)|(1<<2)|(1<<1)); // meine vorzunehmenden Einstellungen

uns was ist mit den Bits 0 und 3? oder weisst du, dass die vorher 
richtig waren?

Autor: ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Lothar Miller:

Vielen Dank für die ausführliche Antwort! :)

>Ist dein i2c_init() das selbe wie ein i2c_start()?
Nein, in meiner init wird nur das Register TWBR auf den entsprechenden 
Wert gesetzt, sonst nichts weiter. Die i2c_start() ist halt die aus der 
lib von Peter Fleury.

>Lies doch mal das Versionsregister 0x01 (al_version und ml_version) aus.
>Bekommst du dort richtige und stabile Werte?

Ja hab ich gemacht und nicht nur diese Register. Außer den 
Achsenregistern sind meine Werte 100% zuverlässig/genau.
Das liegt aber sicher auch daran, dass die nichts mit 
Einstellungsregistern zu tun haben.

Ich denke mit dem Code den du mir gepostet hast werde ich es versuchen. 
Das repeated_start lasse ich erstmal weg.

Justus Skorps wrote:
>uns was ist mit den Bits 0 und 3? oder weisst du, dass die vorher
>richtig waren?

Naja, dass Register hat einen default-Wert. Da steht das die Bist 0 und 
3 beide "0" sind. Ändern will ich die ja nicht.

Autor: ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also langsam verzeifle ich. :(

Hab nun auf ein 2.Modul einen neuen SMB380 draufgelötet und das Programm 
draufgeflasht wie Lothar Miller das vorgeschlagen hat (so hatte ich mir 
das auch überlegt).
Trotzdem driften die dezimalen Werte auseinander,was eigentlich nicht 
sein sollte.
Hab echt keine Ahnung mehr woran das liegen kann. Zum Test hab ich 
nochmal voreingestellte Register ausgelesen, d.h. Register 0x12 und 0x13 
und die Werte die erwartet werden (162 und 13) kommen immer nach dem 
Sensorauslesen raus.
Die Achsendaten werden vom Sensor periodisch mit 3KHz erneuert. Aber 
durch das Bit "shadow_dis" wird verhindert, dass MSB und LSB von 
unteschiedlichen Samples kommen können.
Ich weiss nicht so recht,ob es evtl an den "new_data *flags" liegen 
kann,aber eigentlich signalisieren diese nur,ob die Achsendaten 
ausgelesen wurden.

"...new data*flags... can be used to detect if acceleration values have 
already been read out."

Autor: ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Niemand noch eine Idee?

Autor: Tommy Tacker (tommy776)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Wenn ich folgenden Ablauf auf dem I2c-Bus habe, müsste ich doch im 
I/O-Fenster des AVR-Studio im TWSR-Register am Ende auch die Statuse 
0x50 bzw. 0x58 sehen oder?

initI2c();
startI2c(0x70);
writeI2c(0x02);
rep_startI2c(0x71);
inclination = readAckI2c();
inclination1 = readNakI2c();
stopI2c();

Nach dem Status 0x40 steht nach dem Einlesen der Werte 0xF8!
Ich habe die Library von Peter Fleury.

Autor: Tommy Tacker (tommy776)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ist das normal,dass nach einem STOP-Befehl das Statusregister irgendwann 
0xF8 anzeigt bevor eine neuerliche START-Bedingung gesendet wird?

Ich versuche hier mit der lib von Peter Fleury ein EEPROM-Register eines 
Sensors zu beschreiben. Um überhaupt Zugriff auf das Register zu 
bekommen, muss ich vorher noch in einem anderen Register ein Bit auf "1" 
setzen um überhaupt Zugriff auf dem EEPROM zu haben.

initI2c();
startI2c(0x70);
writeI2c(0x0A);         // Registeradresse wo Bit4 auf 1 soll
writeI2c(0x10);         // beschreibe Bit4 mit 1
erlauben = readAckI2c();
stopI2c();

startI2c(0x70);
writeI2c(0x14);        // Image von EEPROM-Register
rep_startI2c(0x71);
aendern = readAckI2c();
stopI2c();

aendern &=0xE0;
aendern |= 0x01;

startI2c(0x70);
writeI2c(0x34);        // EEPROM-Register;nur schreiben
writeI2c(aendern);
stopI2c();

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.