SPI - A/D Wandler AD7124 Kommunikation

Da hast du meinen Quellcode wohl nicht richtig gelesen...
Hier baue ich das Kommando zusammen.
Müsste so wie ich es laut Datenblatt verstanden habe... eine 0x45 sein.

Ach ja ok,

stimmt ja, das war nun ein "Schnellschuss" von mir. Die Funktion hatte ich mir ja auch schon einmal angeschaut. :rolleyes:
Ja, da müssten 0x45 raus kommen, dies dürte dann richtig sein.

Bei der Software sehe ich im Moment kein Problem. Ich werde mir alles noch mal am WE ansehen, vielleicht habe ich ja mal einen Treffer ;)
 
Ich habe mir noch einmal genauer dein Atmel Studio Projekt, das Datenblatt des AD7124 und das Datenblatt des Evalboards angeschaut.

Mir fällt kein Fehler auf. Den SPI Mode hast du ja angepasst.

Die Übertragung des Inhalts vom ID Register müsste eigentlich funktionieren.

Nun wäre vielleicht noch interessant, wie du genau den ATmega32U4 mit dem Evalboard verbunden hast.
 
Habe das Netzteil vom AD EVAL Board mit dem EVAL Board verbunden und dann vom Digitalteil aus die 3,3VDC mit meinem ATmega verbunden.
Das restliche, wie man SPI halt verbindet...
 
Das restliche, wie man SPI halt verbindet...

Nur um ganz sicher zu gehen ...

ATmega32U4 --- Evalboard (AD7124)
PB1 (SCL) --- SCLK
PB2 (MOSI) --- DIN
PB3 (MISO) --- DOUT
PB6 (Software SS) --- CS\

(SYNC\ auf high, hat aber keinen Einfluss auf SPI)

Hast du es so angeschlossen?

EDIT:
Du solltest noch beachten: ATmega32U4 Systemclock 16MHz erst ab VCC 4,5V zulässig
 
Ja, genau so.
 
Du solltest noch beachten: ATmega32U4 Systemclock 16MHz erst ab VCC 4,5V zulässig
 
Okay... Aber Flanken sahen alle sauber und gut aus... Aber gut zu wissen.
 
So,

Ich bin endlich mal hier weiter gekommen. Nun klappt die Kommunikation schon mal. Habe jetzt nicht mehr das EVA Board sondern habe mir einen Adapter besorgt und den QFN so auf die Adapter Platine gelötet.

Jetzt kommt mir aber so einiges komisch vor. Ich weiß nicht genau ob es an der sende/schreib Routine liegt oder einfach nur weil es im Chip so ist.
Mein Problem jetzt...

Ich beschreibe das Register "Error_En" (0x07) mit einem Wert und lese diesen wieder zurück. Laut Datenblatt (so wie ich es verstehe) Kann ich in diesem Register alles setzen was ich möchte, also jedes Bit.

Schreibe ich in diesem Register eine "0x01" lese ich 256 aus.
Schreibe ich in diesem Register eine "0x02" lese ich 512 aus.
Schreibe ich in diesem Register eine "0x03" lese ich 768 aus.

Was kann das sein?

Hier ist meine schreib Routine ->



CodeBox C
void AD7124_write_uint24(uint8_t reg, uint32_t data)
{     
   SpiSlaveSelectLow();
 
   SpiMasterRxTx(AD7124_COMM_REG_WEN | AD7124_COMM_REG_WR | AD7124_COMM_REG_RA(reg));

   /* page13 */ 
   SpiMasterRxTx((data & 0x00FF0000) >> 16); // msb 
   SpiMasterRxTx((data & 0x0000FF00) >> 8 ); // ...  
   SpiMasterRxTx((data & 0x000000FF)      );   // lsb

   SpiSlaveSelectHigh();
}


Hier ist meine lese Routine ->



CodeBox C
uint32_t AD7124_read_uint24(uint8_t reg)
{
   uint32_t Result[3] = {0,0,0};

   SpiSlaveSelectLow();
 
   /* MSB */
   SpiMasterRxTx(AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD | AD7124_COMM_REG_RA(reg));
   Result[0] = (uint32_t)SpiMasterRxTx(0x00);
 
   /* ... */
   SpiMasterRxTx(AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD | AD7124_COMM_REG_RA(reg));
   Result[1] = (uint32_t)SpiMasterRxTx(0x00);
 
   /* LSB */
   SpiMasterRxTx(AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD | AD7124_COMM_REG_RA(reg));
   Result[2] = (uint32_t)SpiMasterRxTx(0x00);
 
   SpiSlaveSelectHigh();

   Result[0] <<= 16;
   Result[1] <<= 8;
   Result[0] |= Result[1] | Result[2];

   return (Result[0]);
}
 

Anhänge

  • ADE7124.jpg
    ADE7124.jpg
    148,7 KB · Aufrufe: 2
  • ADE7124_1.jpg
    ADE7124_1.jpg
    148,7 KB · Aufrufe: 2
In das Datenblatt habe ich jetzt nicht reingeschaut. Der Fehler liegt wahrscheinlich daran, weil du dreimal nach dem Kommando "Lesen aus Register" immer nur ein Byte empfängst. Insgesamt sind es drei Bytes (immer das selbe?!), die du dann zu einem uint32_t zusammenbastelst.

Richtig wäre wahrscheinlich:
Kommando "Lesen aus Register" senden, dann drei Byte empfangen, diese dann zu einem uint32_t "zusammenbasteln"
 
Wieso lese ich 3 mal das selbe? Wo siehst du das denn?
 
Aber um bei SPI 3 Bytes zu empfangen muss ich doch jedesmal Clocken... Sprich ihm ein Dummy Byte schicken?
 
Ja, Du clockst mit dem ersten Communications Register Byte aber sogar sechs, wenn ich Deine SpiMasterRxTx() richtig interpretiere:

In Zeile 5 beginnst Du die Kommunikation durch das /CS.
In Zeile 8 überträgst Du die Adresse des zu lesenden Registers ins Communication Register, was dabei empfangen wird, verwirfst Du - soweit korrekt.
In Zeile 9 überträgst Du ein Dummy-Byte an den Slave, und legst das empfangene Byte in "Result[0]" ab.
In Zeile 12 überträgst Du ein weiteres Byte, den Empfang verwirfst Du.
In 13 sendest Du einen Dummy, und empfängst.
...
In 19 beendest Du die Kommunikation durch CS.

Effektiv versuchst(!) Du also, nach dem (ersten) Communication-Byte fünf Bytes zu lesen - von denen Du das erste, dritte und letzte Deinen drei Results zuweist, das zweite und vierte verwirfst.
Nach einem Reset/PowerUp landet der erste Zugriff immer im CommRegister, das dabei/damit adressierte Register bestimmt (auch) die Anzahl der Bytes die danach übertragen werden müssen(!).
For read or write operations, after the subsequent read or write operation to the selected register is complete, the interface returns to where it expects a write operation to the communications register

Ich spekuliere mal, daß Du so das Data-Register (0x02) auslesen willst.
In Zeile 5 /CS..
In Zeile 8 teilst Du dem CommRegister mit, daß Du das Data lesen willst
In Zeile 9 läßt Du das erste Data-Byte übertragen -> Result[0]
In Zeile 12 läßt Du das zweite übertragen, und verwirfst es.
In Zeile 13 das dritte, welches Du in Result[2] ablegst. Damit hat der IC seine drei Bytes übertragen (weil Data ein Drei-Byte-Register ist), und erwartet einen neuen Zugriff auf das CommRegister (bzw interpretiert das nächste Byte als solchen ->Zitat) - dieser folgt sogar in Zeile 16 (auch wenn das so sicher nicht Deine Absicht war). Der Parameter "reg" hat sich sicher nicht geändert, Du forderst also einen weiteren Lesezugriff auf das DataRegister an.
In Zeile 14 wird also wieder das erste Data-Byte empfangen, und diesmal in Result[2] abgelegt.
Danach brichst Du die Kommunikation in Zeile 19 ab - das zweite DataByte hast Du nie gespeichert...
Ob das nächste /CS dann ein Reset der Kommunikation wäre, ist mir nicht ganz klar, mMn ist die während CS=1 nur unterbrochen - der IC wartet auf die anderen beiden DummyBytes (bzw die nächsten beiden übertragenen Bytes sind für ihn Dummies, er sendet dann die beiden ausstehenden DataBytes)...
 
Hallo Janiiix,

LotadaC hat das Problem genauer erklärt.

Vergleiche auch mal die Unterschiede bei deinen beiden Funktionen
void AD7124_write_uint24(uint8_t reg, uint32_t data)
und
uint32_t AD7124_read_uint24(uint8_t reg)


Probiere einmal folgendes:
(die Array-Variable habe ich geändert, dies finde ich so übersichtlicher)

(Ich hoffe ich liege hiermit richtig, ins Datenblatt habe ich jetzt nicht weiter geschaut. In deinem bisherigen Sourcecode kann ich leider nicht mehr ansehen, da der externe Link nicht mehr funktioniert, bzw. der Code ist weg.)



CodeBox C
uint8_t data1, data2, data3;
uint32_t d;

SpiSlaveSelectLow();

SpiMasterRxTx(AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD | AD7124_COMM_REG_RA(reg));
data1 = SpiMasterRxTx(0x00);  // MSB
data2 = SpiMasterRxTx(0x00);
data3 = SpiMasterRxTx(0x00);  // LSB

SpiSlaveSelectHigh();

d = (uint32_t)data1<<16;
d |= (uint32_t)data2<<8;
d |= data3;

return d;
 
Ich danke euch beiden. Es funktioniert!
Eine Frage habe ich jedoch noch. Eher an die C Freaks.



CodeBox C
static inline void SBIT (uint32_t *x, uint32_t bitNum)
{
   (*x) |= (1U << bitNum);
}


Was sagt mir noch mal das "U" hinter der "1" und wo finde ich die passenden Abkürzungen?
Das mit dem Bit setzen klappt nicht, ich vermute das es irgendwie überläuft?!
 
Ein U, L oder UL (..) hinter einer Konstanten zeigt dem Compiler, wie er diese Konstante zu interpretieren hat.

Im oberen Fall ist es ein U, das steht für uint16_t. Das ist also zu wenig, da bis 32 Bit geschoben werden soll.
Verwende 1UL (unsigned long, uint32_t), schau auch mal bei stdint.h.

bitNum ist als uint32_t definiert. Ich denke es reicht hier uint8_t ;)
 
> 18 mal schieben, klappt nicht. Ist das richtig?



CodeBox C
void SBIT (uint32_t *x, uint8_t bitNum)
{
   (*x) |= (1UL << bitNum);
}
 
Es sollte normal funktionieren.

Was hast du vor und nach Funktionsaufruf für einen Code in Bezug auf die Parameter?
 
So klappt es nicht ->



CodeBox C
static inline void SBIT (uint32_t *x, uint8_t bitNum)
{
   (*x) |= (1UL << bitNum);
}

void AD7124_readOutAll(ad7124_t *AD_ptr);

int main(void)
{
   /* init cpu clk and wait is ready */
   system_clock_init_32MHz();       
   
   /* init lcd module */
   LCD_init();
   
   /* config spi module */
   spi_t SPI;
   SPI.PORT = &PORTC;
   SPI.MISO = MISO_bp;
   SPI.MOSI = MOSI_bp;
   SPI.SCK  = SCK_bp;
   SPI.SS   = SS_bp;
   SpiMasterInit(&SPI,128,3,0,0,3);
   
   /* yellow state led output */
   PORTR.DIR = (1<<1);       
       
   sei();   
   
   BACKLIGHTPORT.DIR |= 1<<BACKLIGHTPIN;
   BACKLIGHTPORT.OUT |= 1<<BACKLIGHTPIN;
   
   AD7124_reset();

   uint32_t x = 0;
   SBIT(&x,19);

   AD7124_write_uint24(0x07,x);


So klappt es ->



CodeBox C
static inline void SBIT (uint32_t *x, uint8_t bitNum)
{
   (*x) |= (1UL << bitNum);
}

void AD7124_readOutAll(ad7124_t *AD_ptr);

int main(void)
{
   /* init cpu clk and wait is ready */
   system_clock_init_32MHz();       
   
   /* init lcd module */
   LCD_init();
   
   /* config spi module */
   spi_t SPI;
   SPI.PORT = &PORTC;
   SPI.MISO = MISO_bp;
   SPI.MOSI = MOSI_bp;
   SPI.SCK  = SCK_bp;
   SPI.SS   = SS_bp;
   SpiMasterInit(&SPI,128,3,0,0,3);
   
   /* yellow state led output */
   PORTR.DIR = (1<<1);       
       
   sei();   
   
   BACKLIGHTPORT.DIR |= 1<<BACKLIGHTPIN;
   BACKLIGHTPORT.OUT |= 1<<BACKLIGHTPIN;
   
   AD7124_reset();

   uint32_t x = 0;
   SBIT(&x,19);

   AD7124_write_uint24(0x07,0b00000000000010000000000000000000);
 
Hast du es auch mal so probiert ...



CodeBox C
x = (1UL<<19);
AD7124_write_uint24(0x07,x);
// zurücklesen und prüfen


Ich denke nicht, dass es an der Funktion SBIT liegt. Wenn es so nicht funktioniert, liegt es an AD7124_write_uint24

Wenn du dir nicht sicher bist, ob einzelne Programmbereiche fehlerfrei sind, würde ich erst mal diese Bereiche überprüfen.
Bei der SBIT Funktion zB. so...



CodeBox C
uint32_t x;
x=0;
SBIT (&x, 19);

if (x == (1UL<<19))
LED_AN; // ist in Ordnung
else
LED_AUS; // da stimmt was nicht



Mit der Funktion
void AD7124_readOutAll(ad7124_t *AD_ptr);
liest du zurück und testest du?! Die kennen wir nicht.
 
Okay, schönen Sonntagabend noch.
 
Zuletzt bearbeitet:

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)