Forum: Mikrocontroller und Digitale Elektronik SPI Probleme zwischen STM32 und ADT7310


von Boris S. (rosch7777)



Lesenswert?

Hallo Zusammen

Hat jemand Erfahrungen mit dem Temp.Sensor ADT7310 ?

Ich habe da probleme diesen via SPI schnittstelle zuverlässig zu 
programmieren !

Mit der Keil Entwicklungsumgebung (Debugging) bringe ich das Teil zwar
ab und zu zum laufen. sobald ich aber den Chip alleine ohne Debugging
laufen lasse funktioniert es nicht mehr !

Komischer weise geht es ab und zu auch ohne debugger, aber nur wenn ich 
den /CS in abhängigkeit von TXE und RXNE auf High schalte, was aber 
nicht
den timing spezifikationnen des ADT7310 entspricht !!!!!

Schalte ich den /CS genau nach timing spez. funktioniert das Teil
ohne Debugger gar nie !!!!

Was mache ich da blos falsch ??

Code:
void DTS_readData (int8_t dtsRegisterAddress)
{
  //  Description    :  This function read ADT7310 Data.
  //  Input          :  none
  //
  //  Output         :  none

int16_t DigitalTempDataReg16bit;

// SET Chipselect ADC nSS to low
IO_CLR_PIN(TSens_SPI2_GPIO, TSens_SPI2_nSS_PIN);
SPI_I2S_SendData(SPI2, 0x00);

while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
{

}

// SET Chipselect ADC nSS to High
IO_SET_PIN(TSens_SPI2_GPIO, TSens_SPI2_nSS_PIN);

DigitalTempDataReg16bit = SPI_I2S_ReceiveData(SPI2);
Temperatur_Case = (float)DigitalTempDataReg16bit/128;
} // End DTS_readData ()


void DTS_writeData (int8_t dtsRegisterAddress)
{
  //  Description    :  This function write command to ADT7310.
  //  Input          :  none
  //
  //  Output         :  none
uint8_t TxCounter;
SPI_InitTypeDef  SPI_InitStructure;

// Disable SPI
SPI_Cmd(SPI2, DISABLE);
// DeInit SPI
SPI_I2S_DeInit(SPI2);

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
                           // Full Duplex
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;          // Controller 
is SPI Master, ADC is slave
   SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;           // 16 Bit 
Data communication
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;               // accept 
Databit at positive clock edge
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;           // accept 
Data at first clock edge
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;               // manual 
chip select set
    SPI_InitStructure.SPI_BaudRatePrescaler = 
SPI_BaudRatePrescaler_16; //(64MHz/2) /16 = 2MHz
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;           // 
Start with MSB as first databit
    SPI_InitStructure.SPI_CRCPolynomial     = 7;             // CRC 
Polynomial

  // Disable CRC calculation in hardware.
    SPI_Init(SPI2, &SPI_InitStructure);                   // initialise 
SPI with above settings
    SPI_CalculateCRC(SPI2, DISABLE);                   // no CRC is need 
-> disable CRC

    SPI_Cmd(SPI2, ENABLE);                         // Enable SPI2.


TxCounter = 0;
// SET Chipselect ADC nSS to low
IO_CLR_PIN(TSens_SPI2_GPIO, TSens_SPI2_nSS_PIN);
SPI_I2S_SendData(SPI2, dtsRegisterAddress);
mg_u8TempSensorTxBuffer[TxCounter++] = dtsRegisterAddress;
// Wait until end of transmit
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==RESET)
{
}

  for (delay = 0; delay < 4; delay++);
  delay = 0;
  delay = 0;
  delay = 0;
  delay = 0;
  delay = 0;
  delay = 0;
  delay = 0;
  delay = 0;
  delay = 0;
  delay = 0;
  delay = 0;
  delay = 0;
  delay = 0;
  delay = 0;
  delay = 0;



// SET Chipselect ADT7310 nSS to High
IO_SET_PIN(TSens_SPI2_GPIO, TSens_SPI2_nSS_PIN);
for (delay = 0; delay < 16; delay++);
  // Disable SPI
     SPI_Cmd(SPI2, DISABLE);
  // DeInit SPI
     SPI_I2S_DeInit(SPI2);

    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; 
// Full Duplex
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;            // 
Controller is SPI Master, ADC is slave
   SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;             // 16 
Bit Data communication
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                 // 
accept Databit at positive clock edge
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;             // accept 
Data at first clock edge
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                 // manual 
chip select set
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; 
//(64MHz/2) /8 = 4MHz
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;             // 
Start with MSB as first databit
    SPI_InitStructure.SPI_CRCPolynomial     = 7;               // CRC 
Polynomial

  // Disable CRC calculation in hardware.
    SPI_Init(SPI2, &SPI_InitStructure);                     // 
initialise SPI with above settings
    SPI_CalculateCRC(SPI2, DISABLE);                     // no CRC is 
need -> disable CRC

    SPI_Cmd(SPI2, ENABLE);                           // Enable SPI2.

} // End DTS_writeData ()

von bjoern (Gast)


Lesenswert?

Hi Roger,

hab grad mal kurz drüber geschaut, also nicht alles im Code gelesen, 
aber wenn ich Dein Bild richtig interpretiere geht Dein CS zu früh auf 
"1". Versuch mal ein Delay auf dem CS, so dass CS deutlich nach der 
letzten Flanke clk auf eins geht. Ich denke wenn Du zu früh CS wegnimmst 
funtioniert das ganze nicht, wobei ein zu langer CS erstmal nicht 
schadet, kannst dann ja ausprobieren, wie viel Delay noch funktioniert.
Außerdem brauchten wir teilweise einen pull up auf MISO, könnte helfen.

Gruß Bjoern

von Boris S. (rosch7777)


Lesenswert?

Hallo Bjoern

Vielen Dank für Deine Antwort ! Ich bin froh um jeden Hinweis.
Trotz geballter engineering-Wissen in meiner Bude konnte mir bis jetzt 
noch keiner weiterhelfen.

Es ist aber auch verrückt ! Genau mit dem von Dir angesprochenen 
unzulässiger Vorgang auf welcher der /CS zu früh auf High geschaltet 
wird bringt den Chip zum laufen (aber nicht zuverlässig).

Wenn Du Dir auf dem PDF-File den Versuch 2 (Die nächsten 3 Plots)
anschaust kannst Du sehen, dass hier der /CS korrekt erst nach dem 
letzten Clock hochgezogen wird. Und das ist ja genau das unverständliche 
in diesem Zustand bring ich das Teil nicht mal mehr zufällig zum laufen 
!!

Aber das mit dem hinweis Pull-up auf MISO werde ich mal verfolgen.

Gruss
Roger

von Boris S. (rosch7777)


Lesenswert?

Pull up auf MISO hat leider auch nichts gebracht !

Gruss
Roger

von bjoern (Gast)


Lesenswert?

Ich meine aber einen wirklich externen 10k Ohm Widerstand an 3V, keinen 
programmierten auf dem STM32.

von bjoern (Gast)


Lesenswert?

uint16 SPI2_SendWord(uint16 word)
{
    /* Loop while DR register in not emplty */
    GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_RESET);  //Reset CS
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
   {
   }

    /* Send a Byte through the SPI peripheral */
    SPI_I2S_SendData(SPI2, word);

    /* Wait to receive a Byte */

   while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
    {

   }
   Delay(0x0F);

     GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_SET);  //Reset CS
    /* Return the Byte read from the SPI bus */
    return (uint16)SPI_I2S_ReceiveData(SPI2);
}

void Delay(__IO uint32_t nCount)
{
  while(nCount--)
  {
  }
}

So ist es bei uns, vielleicht hilfts ja irgendwie.

Gruß Bjoern

von holger (Gast)


Lesenswert?

>// Wait until end of transmit
>while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==RESET)
>{
>}

Auch hier solltest du auf RXNE warten, nicht auf TXE.
TXE sagt nur das das Transmit Register beschreibbar ist.
Es sagt nicht das der letzte Transfer beendet wurde.

von Boris S. (rosch7777)


Lesenswert?

bjoern schrieb:
> Ich meine aber einen wirklich externen 10k Ohm Widerstand an 3V, keinen
> programmierten auf dem STM32.

Ich hab das auch so verstanden.
Habe einen 11k Ohm zu 3.3V angeschlossen

Aber eben hatte kein Wirkung. MISO geht zwar jetzt schneller auf High 
bei
/CS to High.

von Hauspapa (Gast)


Lesenswert?

Schreib doch mal das Kommunikationsregister und lies es dann zurück. 
Dann solltest du schon sehen ob Du z.B. bitweise verschoben 
interpretiert wirst.
Ob Du die Bits in der richtigen Reihenfolge rausschiebst wirst Du nur 
auf dem Oszi sehen können. Die Mühe nachzuzählen hab ich mir jetzt nicht 
gemacht.

Viel Erfolg
Hauspapa

von Boris S. (rosch7777)


Lesenswert?

holger schrieb:
>>// Wait until end of transmit
>>while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==RESET)
>>{
>>}
>
> Auch hier solltest du auf RXNE warten, nicht auf TXE.
> TXE sagt nur das das Transmit Register beschreibbar ist.
> Es sagt nicht das der letzte Transfer beendet wurde.

Danke mach ich auch mittlerweile. Aber immer noch ohne Erfolg

Gruss
Roger

von Boris S. (rosch7777)


Lesenswert?

Hab mal den Code ein wenig gereinigt und gemäss
Angaben von Björn angepasst.
Nütz Leider auch nichts

void DTS_readData (int8_t dtsRegisterAddress)
{
  //  Description    :  This function read 16bit data register from 
ADT7310
  //  Input          :  none
  //
  //  Output         :  none

int16_t DigitalTempDataReg16bit;

  IO_CLR_PIN(TSens_SPI2_GPIO, TSens_SPI2_nSS_PIN);        // SET 
Chipselect ADC nSS to low
  // send 16 clocks to SPI
  SPI_I2S_SendData(SPI2, 0x00);
  delay = 0;
  // read 16 bit data register ADT7310
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
  {
    if (delay < 150000)
    {
      delay++;
    }
    else
    {
      break;
    }
  }

IO_SET_PIN(TSens_SPI2_GPIO, TSens_SPI2_nSS_PIN);          // SET 
Chipselect ADC nSS to High
DigitalTempDataReg16bit = SPI_I2S_ReceiveData(SPI2);
Temperatur_Case = (float)DigitalTempDataReg16bit/128;
} // End DTS_readData ()


void DTS_writeData (int8_t dtsRegisterAddress)
{
  //  Description    :  This function write command byte to ADT7310
  //  Input          :  dtsRegisterAddress
  //
  //  Output         :  none
uint8_t TxCounter;
SPI_InitTypeDef  SPI_InitStructure;

  // Set SPI Data Size to 8b
  // Disable SPI
     SPI_Cmd(SPI2, DISABLE);
  // DeInit SPI
     SPI_I2S_DeInit(SPI2);

    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; 
// Full Duplex
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;          // Controller 
is SPI Master, ADC is slave
   SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;           // 16 Bit 
Data communication
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;               // accept 
Databit at positive clock edge
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;           // accept 
Data at first clock edge
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;               // manual 
chip select set
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; 
//(64MHz/2) /8 = 4MHz
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;           // 
Start with MSB as first databit
    SPI_InitStructure.SPI_CRCPolynomial     = 7;             // CRC 
Polynomial

  // Disable CRC calculation in hardware.
    SPI_Init(SPI2, &SPI_InitStructure);                   // initialise 
SPI with above settings
    SPI_CalculateCRC(SPI2, DISABLE);                   // no CRC is need 
-> disable CRC

    SPI_Cmd(SPI2, ENABLE);                         // Enable SPI2.
//  for (delay = 0; delay < 23000; delay++);

  TxCounter = 0;
  IO_CLR_PIN(TSens_SPI2_GPIO, TSens_SPI2_nSS_PIN);          // SET 
Chipselect ADC nSS to low
//  SPI_I2S_SendData(SPI2, dtsRegisterAddress);
  // Loop while DR register in not emplty
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
  {
  }

  // Send a Byte (0x054) through the SPI peripheral
  SPI_I2S_SendData(SPI2, dtsRegisterAddress);
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
  {
  }
//  for (delay = 0; delay < 4; delay++);
  IO_SET_PIN(TSens_SPI2_GPIO, TSens_SPI2_nSS_PIN);          // SET 
Chipselect ADT7310 nSS to High
  for (delay = 0; delay < 1200; delay++);

  // Set SPI Data Size to 16b
  // Disable SPI
     SPI_Cmd(SPI2, DISABLE);
  // DeInit SPI
     SPI_I2S_DeInit(SPI2);

    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; 
// Full Duplex
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;            // 
Controller is SPI Master, ADC is slave
   SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;             // 16 
Bit Data communication
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                 // 
accept Databit at positive clock edge
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;             // accept 
Data at first clock edge
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                 // manual 
chip select set
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; 
//(64MHz/2) /8 = 4MHz
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;             // 
Start with MSB as first databit
    SPI_InitStructure.SPI_CRCPolynomial     = 7;               // CRC 
Polynomial

  // Disable CRC calculation in hardware.
    SPI_Init(SPI2, &SPI_InitStructure);                     // 
initialise SPI with above settings
    SPI_CalculateCRC(SPI2, DISABLE);                     // no CRC is 
need -> disable CRC

    SPI_Cmd(SPI2, ENABLE);                           // Enable SPI2.

  mg_u8TempSensorTxBuffer[TxCounter++] = dtsRegisterAddress;

} // End DTS_writeData ()

von Boris S. (rosch7777)


Lesenswert?

Das read Data funktioniert ja einwandfrei wenn ich den Chip mal in den
cont.read mode bringe.

Aber das schreiben der commandos (0x54 und 0x50)
geht nicht.

Wie habt Ihr den die SPI schnittstelle configuriert ?

Oder habe ich etwa ein problem wenn ich diese für das senden des 
commando
auf 8b (sende 1 Byte) und dann wieder zurück auf 16b (lesen 2Byte)
jeweils umstelle ??

Gruss
Roger

von Boris S. (rosch7777)


Angehängte Dateien:

Lesenswert?

Hier noch einen Plott nach der Anpassung des Code gemäss bjoern

Die Pegel stimmen
es wird genau eine 0x54 gesendet gemäss diagramm vom Datenblatt

Ich verstehe nicht was da noch falsch sein soll ?

Gruss
Roger

von Hauspapa (Gast)


Lesenswert?

Du weisst ziemlich sicher das nach senden von 0x54 der Chip nicht macht 
was du möchtest. Status auslesen sagt Dir was er glaubt was er machen 
soll.

Hauspapa

von Eddy C. (chrisi)


Lesenswert?

Was mich im Datenblatt, Page 4, irritiert:

Alle Timingdiagramme zeigen Rising Edge als aktive Flanke, auch die 
Setup/Hold-Zeiten beziehen sich auf die steigende Flanke.

Nur die Fußnote 3 sagt, dass die aktive Flanke die fallende Flanke ist. 
Gibt's dazu eine Erklärung? Ich würde das nochmal checken, bzw. Hirn aus 
und probeweise die aktive Flanke umkonfigurieren.

von Hauspapa (Gast)


Lesenswert?

Page 12 zeigt contineous read mit CS dauerhat low.
Evtl. musst Du nach jedem CS die Übertragung neu starten. Das macht auch 
Sinn wenn Du eben etwas anderes auslesen willst als die Temperatur.

Allerdings ist unter diesem Gesichtspunt der entsprechende Absatz auf S. 
20 missverständlich.

viel Erfolg
Hauspapa

von Hauspapa (Gast)


Lesenswert?

Schreibfehler: Nach jedem Wechsel von CS.

Hauspapa

von Boris S. (rosch7777)


Lesenswert?

Hauspapa schrieb:
> Schreibfehler: Nach jedem Wechsel von CS.
>
> Hauspapa

Also Du meinst nach jedem wechsel von CS vorab wieder ein commando 
(0x54)
senden oder aber CS auf Low belassen und dann jeweils durch wiederholung
von 16 clocks packete den 16 bit Temp. Wert auslesen ?

Hab mich bis jetzt nach Seite 20 Orientiert

Danke

Gruss Roger

von Hauspapa (Gast)


Lesenswert?

Ja, so hab ich Seite 12 verstanden. Einfach ausprobieren.

Viel Erfolg
Hauspapa

von bjoern (Gast)


Lesenswert?

Hi Roger,

in Deinem SPI init schreibst Du:

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

Ich nehme jetzt mal an, das das die 2te Flanke bedeuten soll, wäre wohl 
die negative Flanke, versuchs doch mal mit SPI_CPHA_1Edge.

Gruß Bjoern

von Hauspapa (Gast)


Lesenswert?

Wie ist die Geschichte nun ausgegangen?

Gruss
Hauspapa

von Boris S. (rosch7777)


Lesenswert?

Hallo Zusammen

Komme erst jetzt wieder dazu mich der Sache anzunehmen.

Ich hatte gestern noch versucht dass ganze umzukrempeln und
nach dem command Byte (0x54) /CS Low zu belassen um dann mit senden
von zwei Bytes (0x00,0x00) die 16 clocks zum einlesen des Datenregister 
zu Erzeugen (gemäss Seite 20). Leider bis jetzt ohne Erfolg !

Gruss
Roger

PS: Das Teil bringt mich noch ins Grab !?!?!

von Boris S. (rosch7777)


Angehängte Dateien:

Lesenswert?

bjoern schrieb:
> Hi Roger,
>
> in Deinem SPI init schreibst Du:
>
> SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
>
> Ich nehme jetzt mal an, das das die 2te Flanke bedeuten soll, wäre wohl
> die negative Flanke, versuchs doch mal mit SPI_CPHA_1Edge.
>
> Gruß Bjoern

Hallo Bjoern

Hab das mal kurz ausprobiert. Ohne Erfolg !
Aber SPI_CPHA_2Edge erachte ich als korrekt da SPI_CPOL_High gesetzt 
ist.
Bei SPI_CPOL_High muss ich ja SPI_CPHA_ auf 2Edge stellen damit auf die 
erste positive Flanke ein Bit gelesen werden kann ! ansonsten fällt die 
erste positiv Flanke ja genau auf die Flanke des Datenbits ?

Siehe Plot

von Boris S. (rosch7777)


Lesenswert?

Hallo Bjoern

Ihr scheint ja den ADT7310 mit einem STM32 zum laufen gebracht zu haben.

Wie habt Ihr den die SPI Schnittstelle eingestellt ?

Und wie liest Ihr das Temp Register ?

Mein Ansatzt war:

Zuerst ADT7310 in den cont. read mode setzten:
Schnittstelle auf 8bit setzten und das 0x54 Byte senden.
Schnittstelle wieder auf 16bit setzten.

Auslesen der Daten:
Durch senden von 0x0000 die 16bit clock erzeugen um
den 16 bit Datenwert einlesen zu können.

Gruss
Roger

von Boris S. (rosch7777)


Lesenswert?

Hallo Leute

Endlich Endlich es funzt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Analog Device hat mir folgendes geschrieben:
1. Power-up ADT7310 and reset the serial interface (load 32 consecutive 
1s on DIN). This ensures all internal circuitry is properly initialized.

Nach dem ich dies implementiert hatte, funktioniert es nun einwandfrei!!

Blöd nur das dies nicht so explizit im Datenblatt steht!
Es steht da nur man kann den Chip resetieren in dem man ......bla bla.

Es sollte stehen man muss den Chip beim power-up unbedingt
als erstes resetieren !!!!

Nun was sollst hauptsache das Teil läuft jetzt.

Vielen herzlichen dank an alle welche sich die Mühe gemacht hatten mir 
zu antworten !

Gruss
Roger

von Boris S. (rosch7777)


Lesenswert?

Hab noch in der zwischenzeit von Analog Device folgende Antwort 
bekommen:

I will update the  datasheet to make the serial reset requirement 
clearer in future.

Hmm hattet Ihr keine probleme mit diesem Chip ?
Oder war dies für Euch klar das man den Chip nach power-on
zuerst reseten muss ?

Gruss
Roger

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.