Forum: Mikrocontroller und Digitale Elektronik STM32F4 mit I2C-Sensor


von Christoph (Gast)


Lesenswert?

Hallo!

In meiner Schule haben wir derzeit ein Projekt mit unseren 
Mikrocontrollern (STM32F4 Discovery) zu machen. Wir sollen die 
Temperatur eines ADT7420-Temperatursensors einlesen und mit 
selbsteingegebenen Schwellenwerten vergleichen.

Wir sind damit ins kalte Wasser geworfen worden, da wir noch nie mit 
I2C-Komponenten gearbeitet haben. Auch aus den Datasheets o.Ä. bin ich 
nicht schlau geworden.

Mein Problem ist, dass ich den Temperaturwert, den der Sensor liefert, 
nicht auslesen kann. Ich habe mir im Internet viele Beispielcodes 
angesehen, bekomme aber keinen davon zum Laufen.

Meine Idee wäre, den STM32 als Master und den I2C-Sensor als Slave zu 
benutzen, aber auch mit dem Master/Slave-Prinzip bin ich noch nicht 100% 
vertraut.

Meine Initialisierungschaut im Moment wie folgt aus:
1
#include <stm32f4xx.h>
2
#include <stm32f4xx_i2c.h>
3
4
void init_I2C1(void){
5
6
  GPIO_InitTypeDef GPIO_InitStruct;
7
  I2C_InitTypeDef I2C_InitStruct;
8
9
  // enable APB1 peripheral clock for I2C1
10
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
11
  // enable clock for SCL and SDA pins
12
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
13
14
15
   //1. SCL on PB6 and SDA on PB7
16
17
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
18
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
19
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    
20
  GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
21
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
22
        GPIO_Init(GPIOB,GPIO_InitStruct);
23
24
  // Connect I2C1 pins to AF
25
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);  // SCL
26
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1); // SDA
27
28
  // configure I2C1
29
  I2C_InitStruct.I2C_ClockSpeed = 100000;     // 100kHz
30
  I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;      
31
  I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;  
32
  I2C_InitStruct.I2C_OwnAddress1 = 0x00;      
33
  I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;     
34
  I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; 
35
  I2C_Init(I2C1, &I2C_InitStruct);
36
37
  // enable I2C1
38
  I2C_Cmd(I2C1, ENABLE);
39
}

Ich würde mich über einen kleinen Denkanstoß oder Lösungsansatz sehr 
freuen.

MfG
Christoph

von Uwe B. (derexponent)


Lesenswert?

Hi Christoph,

deine Init-Funktion sieht ok aus (soweit ich das sehe)

was du noch brauchst (aus dem Datenblatt)
ist die Slave-Adresse von dem Temp-Sensor
und noch zwei Funktionen

eine zum schreiben von einem Byte und eine zum lesen
von einem Byte (per I2C)

häng mal das Datenblatt hier mit an
damit man das zur Hand hat

Gruss Uwe

von Christoph S. (intendis)


Angehängte Dateien:

Lesenswert?

Hab mich jetzt mal im Forum registriert, also nicht wundern warum mein 
Name geändert ist ;-)

Vielen Dank für deine schnelle Antwort. Ich werd mich mal an die beiden 
Funktionen machen.
Das Datasheet habe ich jetzt an meinen Post angehängt.

von Christoph S. (intendis)


Lesenswert?

Ich hab mir mit Hilfe des Internets mal eine Funktion zusammengereimt:
1
void I2C_write(I2C_TypeDef* I2Cx, uint8_t data){
2
  I2C_SendData(I2Cx, data);
3
  // wait for I2C1 EV8_2 --> byte has been transmitted
4
  while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
5
}
6
7
uint8_t I2C_read(I2C_TypeDef* I2Cx){
8
  uint8_t data;
9
  // enable acknowledge of recieved data
10
  I2C_AcknowledgeConfig(I2Cx, ENABLE);
11
  // wait until one byte has been received
12
  while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );
13
  // read data from I2C data register and return data byte
14
  data = I2C_ReceiveData(I2Cx);
15
  return data;
16
}

Statt dem erwarteten Wert : 3xxx bekomme ich aber immer den Wert "20" in 
das DR geschrieben... Fehlt mir da noch was oder bin ich mit den 
Funktionen am Holzweg?

von Christoph S. (intendis)


Lesenswert?

Sorry für den Mehrfachpost... Editieren meiner vorigen Posts war leider 
nicht mehr möglich.

Den Wert "20" habe ich im DR stehen, weil ich vorher ein
1
SendData(I2C, 0x20)
gemacht habe, um zu sehen, ob das funktioniert.

Mein Problem ist jetzt, dass ich in dieser while-Schleife hängen bleibe:
1
void I2C_write(I2C_TypeDef* I2Cx, uint8_t data){
2
  I2C_SendData(I2Cx, data);
3
  // wait for I2C1 EV8_2 --> byte has been transmitted
4
  while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
5
}

Als mögliche Slave-Adressen habe ich:
0x48
0x49
0x4A
0x4B

aus dem Datasheet geschlossen. Ist das richtig?

von A. B. (funky)


Angehängte Dateien:

Lesenswert?

es gibt da noch generateStart und generateStop Funktionen in der Lib. 
Hast du dir das mal angeschaut?
gerade bei dem 10bit Beispiel sieht die Write Funktion etwas 
umfangreicher aus.(das angehängte File ist aber vom STM32F2...ich weiss 
nich was sich da zum F4 geändert hat.) Die Beispiele für den F4 in der 
Lib sind aber ziemlich Müll wie ich nach kurzem nachschauen festgestellt 
habe

Hier der Link zur F4 Lib
http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/PF257901

von mit vereinten Kräften (Gast)


Lesenswert?

>Als mögliche Slave-Adressen habe ich:
>0x48
>0x49
>0x4A
>0x4B
>aus dem Datasheet geschlossen. Ist das richtig?

Jetzt bräuchte man einen I2C Slave Address Scanner, gell?
Rate mal wofür die Anschlüsse A0 und A1 am Sensor gedacht sind.

von Uwe B. (derexponent)


Lesenswert?

@Christoph S,

I2C ist leider ein "Protokoll"

also einfach 0x20 über den BUS senden geht da nicht

du brauchst zum senden eines Bytes
an eine Adresse vom Slave:

1. START-Sequenz
2. Slave-Adresse senden
3. Ziel-Adresse senden
4. Daten senden
5. STOP-Sequenz


und wenn du eh schon Sourcen kopierst,
versuchs mal mit meiner LoLevel-Lib unter

http://mikrocontroller.bplaced.net/wordpress/?page_id=720

wie "mit vereinten Kräften" schon geschrieben hat,
die Slave-Adresse wird festgelegt durch die Beschaltung
von A0 bis A1

also wenn A0 bis A1 = Lo-Pegel dann ist die Slave-Adr = 0x48

kommt jetzt halt drauf an wie diese Pins bei dir verdrahtet sind


und als erster Test würde ich versuchen das
Device-ID-Register (0x0B) auszulesen (siehe Datasheet Seite 23)
da muss als Antwort 0xCB zurückkommen



Gruss Uwe

von Marc Rupprath (Gast)


Lesenswert?

Hallo;
das mit dem Wert 0x20 hatte ich auch.
Bei mir war der Sensor nicht richtig konfiguriert.
Beispiel:

Siehe das Config Register im Datenblatt:

Bei mir war der Sensor auf continuierliche Messung eingestellt.
Dennoch musste ich die Messung nach dem Starten 1 mal triggern.

Also als hätte der Sensor im one shot Modus "gestanden"
einfach nochmal mit dem Config Register probieren
Gruß

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.