BMA020 über TWI auslesen

Gast #3972794
Lesenswert?
• ▲
▼
Hallo.

Ich habe ein Problem damit, einen BMA020 über TWI auszulesen bzw Daten 
hinzusenden. Mein Problem liegt wahrscheinlich in der TWI_SEND bzw 
TWI_RECEIVE Funktion. Als Parameter übergebe ich bei TWI_SEND die 
SlaveAdress 0x38, RegisterAdress 0x70 sowie Data. Beim TWI_RECEIVE 
übergebe ich die SlaveAdress 0x38 und die RegisterAdress 0x71.

Könnte mir evtl jemand sagen, wo meine Fehler evtl liegen bei den 
Funktionen?

LG
Angehängte Dateien:
Gast #3972828
Lesenswert?
• ▲
▼
> Ich habe ein Problem damit, einen BMA020 über TWI
> auszulesen bzw Daten hinzusenden.

Welches Problem hast du, welche Symptome hast du beobachtet? Was hast du 
bereits getan, um den Fehler einzukreisen? Hast du ein dazu geeignetes 
Messgerät? Hast du überhaupt schonmal i2c verwendet?
Gast #3972864
Lesenswert?
• ▲
▼
Hi

>Als Parameter übergebe ich bei TWI_SEND die
>SlaveAdress 0x38, RegisterAdress 0x70 sowie Data. Beim TWI_RECEIVE
>übergebe ich die SlaveAdress 0x38 und die RegisterAdress 0x71.

Deine twi.c erwartet als Adresse die um ein Bit nach links geshifteten 
0x38, also 0x70.
1
void TWI_SendAddress(uint8_t Adress, uint8_t Direction)
2
{
3
  if (Direction==0)
4
  {
5
    Adress&=0xFE;
6
  }
7
  else
8
  {
9
    Adress|=0x01;

Das RW-Bit wird mit 'Direction' festgelegt. Die Registeradresse des 
BMA020 liegen im Bereich 0x00...0x15.

MfG Spess
Gast #3972880
Lesenswert?
• ▲
▼
Ich habe bisher noch nie mit I2C gearbeitet, die Funktionen waren alle 
schon gegeben bis auf die Receive und Send, diese sollte ich 
programmieren mit Hilfe der vorgegebenen Funktionen. Ich habe bisher 
alle möglichen Parameter verändert usw. ich denke, dass mein Ablauf vom 
Send (Start->Adresse und Registeradresse (wirte-bit) senden->Daten 
senden->Stop) und Receive (Start->Adresse und Registeradresse 
(write-bit) senden->neuer Start->Adresse und Registeradresse (read-Bit) 
senden->Register lesen->Stop) passt, jedoch klappt irgendeine 
kleinigkeit nicht und ich komme einfach nicht drauf...
Gast #3972929
Lesenswert?
• ▲
▼
Hi

>uint8_t TWI_ReciveData(uint8_t SlaveAdress, uint8_t RegisterAdress)
>{
>  //uint8_t ReceiveData;              //Variable fuer die empfangenden Daten
>  TWI_StartCondition();              //Start der TWI Kommunikation
>  TWI_SendAddress(SlaveAdress, 0); //Senden der Slave- und
>                                     Registeradresse, write senden
>  TWI_RepeatedStartCondition();      //Erneuter Start der TWI Kommunikation
>  TWI_SendAddress(SlaveAdress, 1);        //Senden der Slave- und
>                                          Registeradresse, read senden
>  TWDR=RegisterAdress;  ?????????
>  TWI_ReadData();                  //Lesen der zu empfangenden Daten
>  TWI_StopCondition();              //Beenden der TWI Kommunikation
>  return (0);                    //Rückgabe der empfangenen Daten
>}

Was soll das 'TWDR=RegisterAdress;' machen? Die Registeradresse des 
BMA020 (0x00...0x15), die du lesen willst, muss nach 
'TWI_SendAddress(SlaveAdress, 0);' gesendet werden. Siehe Figure 16 auf 
S.35.

MfG Spess
Gast #3972946
Lesenswert?
• ▲
▼
ah stimmt danke der Ausdruck sollte heißen, dass ich da zeige, welches 
register gelesen werden soll

TWI_StartCondition();
TWI_SendAddress(SlaveAdress, 0);
TWDR=RegisterAdress;
TWI_WriteData(Data);
TWI_StopCondition();

Was ist denn an diesem Konstrukt falsch beim Send? Ich gebe ja nen Start 
vor, anschließend sende ich die Adresse und das write-Bit, danach die 
Registeradresse zB 0x14, anschließend die Daten, die ich senden will und 
zum schluss das Stop
Gast #3972960
Lesenswert?
• ▲
▼
Hi

>danach die Registeradresse zB 0x14,

Mit 'TWDR=RegisterAdress;'?

Deine Senderoutine sieht so

>void TWI_WriteData(uint8_t Data)
>{
>  TWDR=Data;            // legt Data ins Senderegister
>  TWCR=(1<<TWINT)|(1<<TWEN); // Setzt TWI interrupt flag zurueck, Enable TWI
>  while (!(TWCR & (1<<TWINT)));  // wartet bis TWDR uebertragen ist
>  while((TWSR & 0xF8) != 0x28);  // prueft acknoledgement
>}

aus. Dort wird als erstes TWDR mit Data überschrieben. Also ist 
TWDR=RegisterAdress; sinnlos.

MfG Spess
Gast #3972969
Lesenswert?
• ▲
▼
Hi

>wie wird es denn gemacht? also die send funktion?
1
TWI_StartCondition();
2
TWI_SendAddress(SlaveAdress, 0);
3
TWI_WriteData(RegisterAdress);
4
TWI_WriteData(Data);
5
TWI_StopCondition();

Was setzt du für 'SlaveAdress' ein?

MfG Spess
Gast #3973014
Lesenswert?
• ▲
▼
ah okay also mein send sieht nun so aus:

void TWI_SendData(uint8_t SlaveAdress, uint8_t RegisterAdress, uint8_t 
Data)
{
  TWI_StartCondition();
  TWI_SendAddress(SlaveAdress, 0);
  TWI_WriteData(RegisterAdress);
  TWI_WriteData(Data);
  TWI_StopCondition();
}

Parameter: Slaveadress: 0x70 , RegisterAdress: 0x14, Data =Data

Ist es denn dann nun so richtig?

Und passt die Receive so:

uint8_t TWI_ReciveData(uint8_t SlaveAdress, uint8_t RegisterAdress)
{
  TWI_StartCondition();
  TWI_SendAddress(SlaveAdress, 0);
  TWI_WriteData(RegisterAdress);
  TWI_RepeatedStartCondition();
  TWI_SendAddress(SlaveAdress, 1);
  TWI_ReadData();
  TWI_StopCondition();
  return (0);
}

Paramter: SlaveAdress: 0x70, RegisterAdress: 0x14?
Gast #3973068
Lesenswert?
• ▲
▼
Hi

Ich kann eigentlich kein c. Aber dein TWI_ReadData(void) gibt ein einen 
Wert zurück:

uint8_t TWI_ReadData(void)

Also sollte es etwa so

...
 uint8_t ReceiveData;
...
...
 ReceiveData=TWI_ReadData();
 TWI_StopCondition();
 return (ReceiveData);
}

aussehen.

Abgesehen davon kann Leseroutine immer nur ein Byte auslesen. Eine 
Koordinate besteht aber aus 2 Bytes.

MfG Spess
Gast #3973388
Lesenswert?
• ▲
▼
Alternativ könntest du es mal mit meiner TWI Routine versuchen:

http://stefanfrings.de/mikrocontroller_buch/index.html Kapitel 11.4.

uint8_t register=2;
uint8_t buffer[6];
uint8_t count=i2c_communicate(0x38,&register,1,buffer,6);

Anschließend hast du im Buffer die 6 Bytes der drei Achsen X, Y und Z.

Nachtrag: Jetzt, wo die Aufgabenstellung klar ist, sehe ich, dass du die 
vorgegebenen TWI Funktionen nutzen sollst.
Gast #3973401
Lesenswert?
• ▲
▼
Beachte, dass die vorgegebenen TWI Funktionen die 7 Bit Slave Adresse 
NICHT nach links schieben, wie es das TWI Protokoll verlangt. Du musst 
das daher selbst erledigen:

uint8_t slaveAddress=(0x38 << 1);

Die 6 Messwerte (2 pro Bytes Achse) stehe in den Registern 0x02 bis 
0x07.

Für die ersten Versuche kannst du diese Register einfach auslesen. Denn 
nach dem Power-On Reset arbeitet der Chip schon mit sinnvoller 
Konfiguration.

Erst wenn das klappt, würde ich versuchen, den Chip mit irgendwelchen 
Konfigurations-Settings zu beladen.
Gast #3973412
Lesenswert?
• ▲
▼
> aber es hat auch nicht funktioniert

Ich habe meinen Code mit diesem Chip verifiziert, das war meine erste 
konkrete Anwendung für den Code.

Wenn bei Dir die Slave Adresse stimmt (muss bei meinem Code 0x38 sein) 
und die Registeradresse auch stimmt, dann hast du möglicherweise 
Probleme wegen einem Hardwarefehler.

> aber es funktioniert immer noch nicht

WAS funktioniert nicht? Hat die Steckdose keinen Strom? Macht dein Radio 
komische Geräusche? Wird der Sensor Heiß? Hängt die I2C Kommunikation 
(wenn ja, wo)? Bekommst du unplausible Werte (wenn ja, welche)?

Beantworte diese Frage mal etwas detaillierter, damit wir nicht blind 
raten müssen.

Welches Problem hast du, welche Symptome hast du beobachtet?
Hast du ein dazu geeignetes Messgerät?
Gast #3973423
Lesenswert?
• ▲
▼
Im Anhang einmal die Matlab-GUI. (Treiber R2012a muss installiert werden 
32 Bit)

Sensor angeklemmt wie folgt:
PC0 -> SCK PC1 -> SDI
INT -> INT0 (PD2)
Spannung (3,2V oder 5V) auf UIN, UPullup, CSB
Masse auf GND und SDO

USART: PD0 -> RXD PD1 -> TXD
RS232 SPare über Adapter an PC angeschlossen

Werte kommen gar keine an! Kann die Gui mit dem Controller verbinden, es 
geschieht jedoch nichts

Sensor wird leicht warm
Angehängte Dateien:
Gast #3973452
Lesenswert?
• ▲
▼
> Spannung (3,2V oder 5V) auf UIN, UPullup, CSB

Also verwendet du scheinbar nicht den nackten Chip, sondern das Modul 
vom ELV Verlag. Zwei Sachen dazu:

Die Pegelwandler auf diesem Modul sind relatisch schwach. Du darfst sie 
nicht durch weitere Pull-Up Widerstände (z.B. auf dem 
Mikrocontroller-Board) belasten.

korrekt: SDO musst du mit GND verbinden, im Datenblatt des Chips steht 
das leider irreführend anders. Aber im Datenblatt des ELV Moduls ist es 
unmissverständlich dargestellt.

> Spannung (3,2V oder 5V)

Was heisst oder? Du must schon die gleiche Spannung verwenden, wie beim 
Mikrocontroller.

> Sensor wird leicht warm

Wird der BMA020 Chip warm, oder andere Bauteile in dessen Nähe? Die 
Stromaufnahme des Sensors ist so gering, dass er unmöglich spürbar warm 
werden kann.

> Werte kommen gar keine an! Kann die Gui mit dem Controller verbinden
Moment mal, ich dachte wir sind dabei, deinen Programmcode zu prüfen. 
Diese EXE Datei darf und will nicht ausführen.

beschreibe, was auf der I2C Schnittstelle passiert. Welche Signale 
treten dort auf?

Hast du ein dazu geeignetes Messgerät?

Ich glaube, du hast hier zu viele Baustellen auf einmal. Du hast eine 
Hardware, bei der nu nicht sicher bist, ob sie funktioniert. Und due 
hast mehrere Softwarekomponenten, bei denen du nicht sicher bist. Und 
dann bist auch nicht sicher, ob dein eigener Programmcode Ok ist.

Kreise das problem ein, und fange mit einem leeren Programm an:

Schließe an einen I/O Port acht LED's an und gebe ein Byte aus. Prüfe, 
ob die LED's wie erwartet leuchten. Wiederholde dies mit 
unterschiedlichen Werten.

Wenn das klappt, dann lese nur das Register 0 aus, zeige den Wert mit 
den LED's an und prüfe, ob er mit dem Datenblatt überein stimmt.

Dann sehen wir weiter.

Den ganzen Kram mit der Ablaufsteuerung und PC Kommunikation lässt du 
erstmal aus. Das stört nur.
Gast #3973463
Lesenswert?
• ▲
▼
Also auf die Pullup doch keine Spannung drauf? habe im internet mehrere 
Anschlusspläne gefunden und dort war immer Spannung auf den Pullups

Diese ganze Kommunikation funktioniert laut Prof., nur die TWI_INIT, 
TWI_SEND, TWI_Receive und USART_INIT, USART_SEND sollte neu geschrieben 
werden das sind die einzigen 5 Funktionen, wo etwas falsch sein kann, 
die anderen Funktionen (Data_Sync usw funktionieren alle einwandfrei). 
An Matlab muss auch nichts geändert werden, dort muss nur ein COM-Port 
ausgewählt werden...

Das was ich mit einem Messgerät überprüft habe, waren der CLK Pin und 
der SDA Pin für das TWI, diese waren beide auf einem High-Pegel
Gast #3973471
Lesenswert?
• ▲
▼
> Also auf die Pullup doch keine Spannung drauf?

Das habe ich nicht geschrieben. Ich habe geschrieben, dass du die 
Leitungen nicht durch Zusätzliche Pullups auf der 
Mikrocontroller-Platien belasten darfst.

> Diese ganze Kommunikation funktioniert laut Prof., nur die TWI_INIT,
> TWI_SEND, TWI_Receive und USART_INIT, USART_SEND sollte neu geschrieben
> werden

Wie gesagt, zu viele Unbekannte auf einen Schlag. Reduziere den Code auf 
das absolute Minimum. Wenn ein pferd sich nicht bewegt, fängst du auch 
nicht damit an, das Futter zu untersuchen, sondern schaust zuerst nach, 
ob das Herz noch schlägt.

> Das was ich mit einem Messgerät überprüft habe, waren der CLK Pin
> und der SDA Pin für das TWI, diese waren beide auf einem High-Pegel

Wann waren sie auf High Pegel? Wenn diese beiden Leitungen ständig auf 
High stehen, findet gar keine Kommunikation statt. Jerdoch ist ein 
normales Multimeter kaum dazu geeignet, dies zu untersuchen. Ein 
Logikanalyzer oder notfalls ein Oszilloskop eignen sich schon eher.

Abgesehen davon durchsuche nochmal den ganze Thread nach Fragezeichen. 
Du hast mehr als die Hälfte aller Rückfragen noch nicht beantwortet. So 
können wir Dir nicht weiter helfen.

ich klinke mich jetzt erstnal aus - bis morgen.
Gast #3973557
Lesenswert?
• ▲
▼
Habe meinen Fehler gefunden....

Und zwar lag es daran, dass ich die switch - case Struktur auch im main 
aufrufen muss und dort alle Funktionen pro case ausführen muss, nicht 
bei den cases im Interrupt...

Vielen Dank euch allen für die hilfreichen Tipps :)

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.