Forum: Mikrocontroller und Digitale Elektronik SPI Interrupt auf MEGA32U4


von Jan H. (janiiix3)


Lesenswert?

Hallo,

ich wollte jetzt mal vom Polling auf Interrupt umsteigen um eine saubere 
Kommunikation am SPI-Bus zu haben.

Mit dem "poll" Verfahren klappt soweit alles prima...
Aktiviere ich jetzt aber die dazugehörige "ISR" bricht alles zusammen 
und nichts funktioniert mehr.
Ich weiß nicht woran das liegt?! :(
Hat jemand eine Idee?

Main
1
int main(void)
2
{
3
  
4
  DDRD |= (1<<PD5);
5
    
6
  lcd_init(LCD_DISP_ON);
7
  spi_master_init(64,2);
8
  
9
    while (1) 
10
    {
11
    spi_master_transmit(0xFF);  
12
          
13
    sprintf(Buffer,"L1: %d", cnt);
14
    lcd_gotoxy(5,0);
15
    lcd_puts("           ");
16
    lcd_gotoxy(5,0);
17
    lcd_puts(Buffer);
18
          
19
    _delay_ms(800);  
20
                
21
    }
22
}

Master Init for MEGA32U4
1
void spi_master_init(uint8_t prescaler, uint8_t clock_option)
2
{  
3
  /* ONLY FOR MEGA32! */
4
  #if defined(__AVR_ATmega32__)
5
  {
6
    /* set MOSI and SCK output, all others input */
7
    MOSI_DDR |= (1<<MOSI_BIT);
8
    SCK_DDR   |=  (1<<SCK_BIT);
9
    SS_DDR   |= (1<<SS_BIT);
10
  
11
    /* enable SPI, Master */
12
    SPCR |= (1<<SPE) | (1<<MSTR);
13
    
14
    /* clear the bit´s (for multi init) */
15
    SPCR &= ~((1<<SPI2X) | (1<<SPR0) | (1<<SPR1)); // fclk/4
16
  
17
    /* config SPI Bus Speed fclk/prescaler */
18
    switch (prescaler)
19
    {
20
      case 2:   {SPCR |=  (1<<SPI2X);               };break;
21
      case 8:   {SPCR |=  ((1<<SPI2X) | (1<<SPR0));       };break;
22
      case 32:  {SPCR |=  ((1<<SPI2X) | (1<<SPR1));       };break;
23
      case 64:  {SPCR |=  ((1<<SPI2X) | (1<<SPR1) | (1<<SPR0));};break;
24
      default:  {SPCR |=  (1<<SPI2X);               };break;
25
    }
26
  }
27
  #endif  
28
  
29
  /* ONLY FOR MEGA32U4! */
30
  #if defined (__AVR_ATmega32U4__)
31
  {
32
      /* set MOSI and SCK output, all others input */
33
      MOSI_DDR  |= (1<<MOSI_BIT);
34
      SCK_DDR    |=  (1<<SCK_BIT);
35
      SS_DDR    |= (1<<SS_BIT);     // software slave select signal
36
      SS_HA_DDR  |= (1<<SS_HA_BIT); // hardware slave select signal
37
      
38
      /* enable SPI, Master */
39
      SPCR |= ((1<<SPE) | (1<<MSTR) | (1<<SPIE));      
40
      
41
      /* config "Clock Polarity and "Clock Phase" */
42
      switch(clock_option)
43
      {
44
        case 0 : {SPCR &= ~((1<<CPOL) | (1<<CPHA)); }break; // mode 1
45
        case 1 : {SPCR |=  (1<<CPHA);        }break; // mode 2
46
        case 2 : {SPCR |=  (1<<CPOL);        }break; // mode 3
47
        case 3 : {SPCR |=  ((1<<CPOL) | (1<<CPHA));  }break; // mode 4
48
      }
49
      
50
      /* config SPI Bus Speed fclk/prescaler */
51
      switch (prescaler)
52
      {
53
        case 2:   {SPSR |= (1<<SPI2X);                  }break; // prescaler 2
54
        case 8:   {SPSR |= (1<<SPI2X); SPCR |= (1<<SPR0);        }break; // prescaler 8
55
        case 32:  {SPSR |= (1<<SPI2X); SPCR |= (1<<SPR1);        }break; // prescaler 32
56
        case 64:  {SPSR |= (1<<SPI2X); SPCR |= (1<<SPR1) | (1<<SPR0); }break; // prescaler 64
57
        default:  {SPSR |= (1<<SPI2X);                  }break; // default = 2
58
      }
59
  }
60
  #endif
61
}

ISR
1
/* byte received */
2
ISR(SPI_STC_vect)
3
{
4
   static uint8_t i;
5
   PORTD ^= (1<<PD5);
6
   data[i++] = SPDR;
7
 }

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> um eine saubere Kommunikation am SPI-Bus zu haben.

Sauber ist die SPI-Kommunikation auch im polled mode.

Bei hinreichend hohem SPI-Takt lohnt sich Interruptbetrieb überhaupt
nicht.  Am ehesten wäre es noch sinnvoll, wenn du einige Daten „am
Stück“ übertragen musst, dafür DMA zu nutzen, sodass er am Ende eines
Transfers ohne CPU-Zutun den nächsten starten kann.

> Ich weiß nicht woran das liegt?! :(

Vielleicht daran, dass deine Indexvariable in der ISR über alle
Maßen wachsen kann, und somit der ganze Speicher zugemüllt wird?

von Jan H. (janiiix3)


Lesenswert?

Jörg W. schrieb:
> Jan H. schrieb:
>> um eine saubere Kommunikation am SPI-Bus zu haben.
>
> Sauber ist die SPI-Kommunikation auch im polled mode.
>
> Bei hinreichend hohem SPI-Takt lohnt sich Interruptbetrieb überhaupt
> nicht.  Am ehesten wäre es noch sinnvoll, wenn du einige Daten „am
> Stück“ übertragen musst, dafür DMA zu nutzen, sodass er am Ende eines
> Transfers ohne CPU-Zutun den nächsten starten kann.
>
>> Ich weiß nicht woran das liegt?! :(
>
> Vielleicht daran, dass deine Indexvariable in der ISR über alle
> Maßen wachsen kann, und somit der ganze Speicher zugemüllt wird?

Ich habe die ISR auch leer gelassen und genau den selben Effekt 
vorgefunden.
Daran kann es nicht liegen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> Daran kann es nicht liegen.

Wie geschrieben: überleg' dir erstmal, ob ein Interruptbetrieb
überhaupt irgendeinen Sinn hat.  Wenn du dein SPI mit f_CPU/2
taktest, dann hast du nach 16 CPU-Takten ein Byte komplett durch.
In dieser Zeit hat die ISR gerade mal die nötigen CPU-Register
gerettet.

von SPIProgrammierer (Gast)


Lesenswert?

Ich kann nicht so recht den Sinn erkennen bei einem SPI Master
den Recieve Interrupt zu nutzen. Ich weiss ja dass ich (sowieso)
ein Receive durch einen Transmit initiiere. Die Daten sind ja
"schon da" wenn ich auf den "Transmit-Knopf" gedrückt habe ...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

SPIProgrammierer schrieb:
> Ich kann nicht so recht den Sinn erkennen bei einem SPI Master
> den Recieve Interrupt zu nutzen.

Das ist ja ohnehin kein Receive-Interrupt, sondern ein "Transfer
complete".

Für sehr langsames SPI kann man sowas schon machen, wenn man in
der Zwischenzeit auf der CPU was anderes tun könnte.

von S. Landolt (Gast)


Lesenswert?

Wie sieht 'spi_master_transmit' aus?

von Jan H. (janiiix3)


Lesenswert?

SPIProgrammierer schrieb:
> Ich kann nicht so recht den Sinn erkennen bei einem SPI Master
> den Recieve Interrupt zu nutzen. Ich weiss ja dass ich (sowieso)
> ein Receive durch einen Transmit initiiere. Die Daten sind ja
> "schon da" wenn ich auf den "Transmit-Knopf" gedrückt habe ...

Mein "Problem" ist es so :
1
uint8_t spi_receive(void)
2
{  
3
  /* ONLY FOR MEGA32! */
4
  #if defined(__AVR_ATmega32__)
5
  {
6
    /* Wait for reception complete */
7
    while(!(SPSR & (1<<SPIF)));
8
  }
9
  #endif  
10
  
11
  /* ONLY FOR MEGA32U4! */
12
  #if defined (__AVR_ATmega32U4__)
13
  {
14
    /* Wait for reception complete */
15
    while(!(SPSR & (1<<SPIF)));        
16
  }
17
  #endif
18
  
19
  /* return data register */
20
  return SPDR;  
21
  
22
}

mehrere bytes hintereinander zu empfangen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> mehrere bytes hintereinander zu empfangen.

Hast du das Prinzip von SPI überhaupt verstanden?

SPI ist ein Schieberegister.  Du schiebst 8 Bits raus (indem du
das SPDR „abgehend“ beschreibst, die Hardware leiert dann die
Taktbits an), und gleichzeitig werden 8 Bits von MISO reingeschoben.
Die kannst du danach aus SPDR „ankommend“ einlesen.

Wenn du mehrere Bytes lesen willst, musst du auch genauso viele Bytes
schreiben.

von Jan H. (janiiix3)


Lesenswert?

Jörg W. schrieb:
> Jan H. schrieb:
>> mehrere bytes hintereinander zu empfangen.
>
> Hast du das Prinzip von SPI überhaupt verstanden?
>
> SPI ist ein Schieberegister.  Du schiebst 8 Bits raus (indem du
> das SPDR „abgehend“ beschreibst, die Hardware leiert dann die
> Taktbits an), und gleichzeitig werden 8 Bits von MISO reingeschoben.
> Die kannst du danach aus SPDR „ankommend“ einlesen.
>
> Wenn du mehrere Bytes lesen willst, musst du auch genauso viele Bytes
> schreiben.
1
  spi_master_transmit(reg); // register address
2
  spi_master_transmit(0x00); // dummy byte
3
  Buffer[0] = spi_receive(); // first byte
4
5
  spi_master_transmit(reg); // register address  
6
  spi_master_transmit(0x00);
7
  Buffer[1] = spi_receive(); // secound byte
8
  
9
  spi_master_transmit(reg); // register address
10
  spi_master_transmit(0x00);
11
  Buffer[2] = spi_receive(); // third byte

Das "dummy" reicht aus für 3 byte oder ?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wartest du am Ende des spi_master_transmit() auch, bis die
Übertragung fertig ist?

Zeig doch mal den kompletten Code.

von S. Landolt (Gast)


Lesenswert?

> Zeig doch mal den kompletten Code.
Darauf warte ich seit 17:17.

von Jan H. (janiiix3)


Lesenswert?

Jörg W. schrieb:
> Wartest du am Ende des spi_master_transmit() auch, bis die
> Übertragung fertig ist?
>
> Zeig doch mal den kompletten Code.
1
unsigned long ADE7758_read_uint32(uint8_t reg)
2
{
3
  Buffer[0] = 0; // default value
4
  Buffer[1] = 0; // default value
5
  Buffer[2] = 0; // default value
6
  
7
  spi_enable_chip();
8
  spi_disable_chip(); // start transmission condition
9
  
10
  spi_master_transmit(reg);  // register address
11
  spi_master_transmit(0x00); // dummy byte
12
  Buffer[0] = spi_receive(); // first byte
13
  
14
  spi_master_transmit(0x00);
15
  Buffer[1] = spi_receive(); // secound byte
16
  
17
  spi_master_transmit(0x00);
18
  Buffer[2] = spi_receive(); // third byte
19
  
20
  spi_enable_chip(); // stop transmission condition  
21
              /*     first byte      second byte      third byte */
22
  unsigned long result = ((16 << Buffer[0]) |  (8 << Buffer[1]) | Buffer[2]);
23
  
24
  return result;
25
}

Hier für meine 3 bytes.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> Hier für meine 3 bytes.

Immer noch nicht komplett …

„Komplett“ ist etwas, wenn man es compilieren kann.

Ich hab' keine Lust mehr, dir jedes Detail einzeln aus der Nase zu
ziehen.

: Bearbeitet durch Moderator
von Jan H. (janiiix3)


Lesenswert?

Jörg W. schrieb:
> Jan H. schrieb:
>> Hier für meine 3 bytes.
>
> Immer noch nicht komplett …
>
> „Komplett“ ist etwas, wenn man es compilieren kann.

Was willst du denn jetzt sehen?
In der Main rufe ich nur diese Routine auf...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> Was willst du denn jetzt sehen?

Ein komplettes, in sich schlüssiges, compilierbares Beispiel.

Nicht hier ein Stück, da ein Stück, und spi_master_transmit()
fehlt immer noch.

von S. Landolt (Gast)


Lesenswert?

Stimmt dieses '__AVR_ATmega32U4__'? In Assembler kenne ich es nur ohne 
'AVR', also z.B. '__ATmega1284P__'.

von Jan H. (janiiix3)


Lesenswert?

Master Transmit:
1
void spi_master_transmit(uint8_t cData)
2
{
3
  /* ONLY FOR MEGA32! */
4
  #if defined(__AVR_ATmega32__)
5
  {
6
    /* start transmission */
7
    SPDR = cData;
8
  
9
    /* wait for transmission complete */
10
    while(!(SPSR & (1<<SPIF)));
11
  }
12
  #endif
13
  
14
  /* ONLY FOR MEGA32U4! */
15
  #if defined (__AVR_ATmega32U4__)
16
  {
17
    /* start transmission */
18
    SPDR = cData;
19
20
    /* wait for transmission complete */
21
    while(!(SPSR & (1<<SPIF)));  
22
  }
23
  #endif
24
  
25
}

Main
1
int main(void)
2
{
3
  
4
  DDRD |= (1<<PD5);
5
    
6
  lcd_init(LCD_DISP_ON);
7
  spi_master_init(64,2);
8
  
9
    while (1) 
10
    {
11
    unsigned long test = ADE7758_get_U(2);
12
          
13
    sprintf(Buffer,"L1: %lu", test);
14
    lcd_gotoxy(5,0);
15
    lcd_puts("           ");
16
    lcd_gotoxy(5,0);
17
    lcd_puts(Buffer);
18
          
19
    _delay_ms(800);  
20
                
21
    }
22
}
1
unsigned long ADE7758_get_U(uint8_t phase)
2
{
3
  uint32_t voltage = 0;
4
5
  switch (phase)
6
  {
7
    case 1  : {voltage = ADE7758_read_uint32(REG_AVRMS);  }break; // L1       [Voltage]
8
    case 2  : {voltage = ADE7758_read_uint32(REG_BVRMS);  }break; // L2       [Voltage]
9
    case 3  : {voltage = ADE7758_read_uint32(REG_CVRMS);  }break; // L3       [Voltage]
10
    default  : {voltage = ADE7758_read_uint32(REG_AVRMS);  }break; // default = L1  [Voltage]
11
  }
12
13
  return voltage;
14
}

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

S. Landolt schrieb:
> Stimmt dieses '__AVR_ATmega32U4__'?

Ja, die werden so vom Compiler definiert.

Wobei ich mich schon frage, warum man (in spi_master_receive())
überhaupt dergestalt eine Fallunterscheidung machen möchte, wenn
dann beide Implementierungen gleich sind.

von Jan H. (janiiix3)


Lesenswert?

Jörg W. schrieb:
> S. Landolt schrieb:
>> Stimmt dieses '__AVR_ATmega32U4__'?
>
> Ja, die werden so vom Compiler definiert.
>
> Wobei ich mich schon frage, warum man (in spi_master_receive())
> überhaupt dergestalt eine Fallunterscheidung machen möchte, wenn
> dann beide Implementierungen gleich sind.

Es vebraucht keinen speicher auf meinem AVR, wieso sollte ich es nicht 
machen? Es kann bei einem anderen AVR auch ein anderes Register mal 
sein.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

OK, ist zwar immer noch blöd, dass du nicht mal einfach alles in
eine Datei packst, die man auch durch den Compiler schicken kann
(so muss ich mir all deine Puzzelsteine im Kopf zusammensetzen),
aber dein Problem wird es einfach sein, dass du zweimal auf das
Ende eines Transfers warten möchtest: einmal in spi_master_transmit()
und dann noch einmal in spi_master_receive().

Das Flag wird aber nur einmal gesetzt.

Entweder wartest du am Ende von transmit(), oder am Anfang von
receive().  Ersteres ist dahingehend sinnvoll, dass du auf diese
Weise zwei transmit() direkt hintereinander setzen kannst, ansonsten
müsstest du vor dem zweiten nochmal separat warten.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
>> Wobei ich mich schon frage, warum man (in spi_master_receive())
>> überhaupt dergestalt eine Fallunterscheidung machen möchte, wenn
>> dann beide Implementierungen gleich sind.
>
> Es vebraucht keinen speicher auf meinem AVR, wieso sollte ich es nicht
> machen?

Weil es den Code umständlicher macht (code obfuscation).

Fallunterscheidungen macht man dann, wenn man sie braucht, und
nicht „für den Fall der Fälle“.

Da du sowieso schon zwei verschiedene Klassen von AVRs hast (einmal
MegaAVR und einmal Xmega) und bei beiden Senden und Empfang gleich
sind, und die Routine jenseits von AVRs ohnehin völlig anders
aussehen dürfte, kannst du die Fallunterscheidung dort getrost
weglassen.  Dann blieben nur noch ein paar Bits in der
Initialisierung, für die man wirklich eine Unterscheidung braucht.
Der größte Teil davon ist selbst dort bei beiden Klassen gleich.

: Bearbeitet durch Moderator
von Jan H. (janiiix3)


Lesenswert?

Jörg W. schrieb:
> Jan H. schrieb:
>>> Wobei ich mich schon frage, warum man (in spi_master_receive())
>>> überhaupt dergestalt eine Fallunterscheidung machen möchte, wenn
>>> dann beide Implementierungen gleich sind.
>>
>> Es vebraucht keinen speicher auf meinem AVR, wieso sollte ich es nicht
>> machen?
>
> Weil es den Code umständlicher macht (code obfuscation).
>
> Fallunterscheidungen macht man dann, wenn man sie braucht, und
> nicht „für den Fall der Fälle“.
>
> Da du sowieso schon zwei verschiedene Klassen von AVRs hast (einmal
> MegaAVR und einmal Xmega) und bei beiden Senden und Empfang gleich
> sind, und die Routine jenseits von AVRs ohnehin völlig anders
> aussehen dürfte, kannst du die Fallunterscheidung dort getrost
> weglassen.  Dann blieben nur noch ein paar Bits in der
> Initialisierung, für die man wirklich eine Unterscheidung braucht.
> Der größte Teil davon ist selbst dort bei beiden Klassen gleich.

Du hast ja Recht. Habe es geändert.
Du meinst mit warten sicherlich die "while(bedingung" Abfrage.

Habe es im spi_receive(); rausgenommen
1
uint8_t spi_receive(void)
2
{  
3
  /* Wait for reception complete */
4
  //while(!(SPSR & (1<<SPIF)));        
5
6
  /* return data register */
7
  return SPDR;  
8
}

von S. Landolt (Gast)


Lesenswert?

Reden wir jetzt von Interrupt oder von Polling?

von Jan H. (janiiix3)


Lesenswert?

S. Landolt schrieb:
> Reden wir jetzt von Interrupt oder von Polling?

Vom Polling. Sorry!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> Du meinst mit warten sicherlich die "while(bedingung" Abfrage.

Yep.

von S. Landolt (Gast)


Lesenswert?

Jan H. schrieb:
> Mein "Problem" ist es so :
...
> mehrere bytes hintereinander zu empfangen.

Und dieses Problem besteht jetzt, trotz korrigiertem 'spi_receive', noch 
immer?

von Jan H. (janiiix3)


Lesenswert?

S. Landolt schrieb:
> Jan H. schrieb:
>> Mein "Problem" ist es so :
> ...
>> mehrere bytes hintereinander zu empfangen.
>
> Und dieses Problem besteht jetzt, trotz korrigiertem 'spi_receive', noch
> immer?

Ja.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> Ja.

Glaub' ich nicht.

Also, ein Problem wirst du wohl noch haben, aber ich denke nicht,
dass an den SPI-Transfers jetzt immer noch was foul ist.

Halt doch mal einen Oszi an die Leitungen und schau nach, was auf
dem Draht passiert.

Was ist denn dein Fehlerbild?

von Jan H. (janiiix3)


Lesenswert?

Jörg W. schrieb:
> Jan H. schrieb:
>> Ja.
>
> Glaub' ich nicht.
>
> Also, ein Problem wirst du wohl noch haben, aber ich denke nicht,
> dass an den SPI-Transfers jetzt immer noch was foul ist.
>
> Halt doch mal einen Oszi an die Leitungen und schau nach, was auf
> dem Draht passiert.
>
> Was ist denn dein Fehlerbild?

Ich kann nicht wirklich nachvollziehen ob mein Sensor mir wirklich 24 
Bit schickt oder ob ich die Rechnung falsch angehe.

von S. Landolt (Gast)


Lesenswert?

Auf die Gefahr hin, auf die Nerven zu fallen: das komplette Programm im 
aktuellen Stand wäre hilfreich, auch die Auskunft, wie das Problem 
aussieht.

von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

Da sind die einzelnen Daten.

von S. Landolt (Gast)


Lesenswert?

Nur ganz am Rande:
> SPCR &= ~((1<<SPI2X) | (1<<SPR0) | (1<<SPR1)); // fclk/4
Das klappt auch nur durch einen glücklichen Zufall, SPI2X steht in SPSR.

von S. Landolt (Gast)


Lesenswert?

Jetzt bin ich prompt drauf reingefallen, das gilt ja nur für den 
ATmega32.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wenn ich das richtig sehe, muss man den ADE7758 mit CPHA=1 CPOL=0
betreiben.

Dafür hat dein spi_master_init() beim ATmega32 keinen Code, und
der Wert 2 bei der Xmega-Initialisierung müsste wohl eher eine 1
sein, oder täusche ich mich da?

Ich versteh' auch nicht ganz, warum du so einen riesigien Prescaler
von 64 nimmst.  Der ADE7758 verkraftet doch maximal 10 MHz.

Wie schon geschrieben: ich würde mir die Signale jetzt auf einem Oszi
oder LA ansehen.

von Jan H. (janiiix3)


Lesenswert?

Jörg W. schrieb:
> Wenn ich das richtig sehe, muss man den ADE7758 mit CPHA=1 CPOL=0
> betreiben.
>
> Dafür hat dein spi_master_init() beim ATmega32 keinen Code, und
> der Wert 2 bei der Xmega-Initialisierung müsste wohl eher eine 1
> sein, oder täusche ich mich da?
>
> Ich versteh' auch nicht ganz, warum du so einen riesigien Prescaler
> von 64 nimmst.  Der ADE7758 verkraftet doch maximal 10 MHz.
>
> Wie schon geschrieben: ich würde mir die Signale jetzt auf einem Oszi
> oder LA ansehen.

Das mit CPHA=1 CPOL=0, kann sein. Habe es mit der aktuellen Einstellung 
getestet und kann div. Register die 8 Bit breit sind Erfolgreicht zurück 
lesen.

Den Prescaler hatte ich nur so hoch eingestellt, damit ich was testen 
konnte.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Was genau passiert denn nun bei den breiteren Registern?

von Jan H. (janiiix3)


Lesenswert?

Ich habe eine ~18VAC Spannung am Eingang 3 angelegt (PhaseC)
Mit entsprechenden Widerständen etc.

Ich bekomme keinen Wert der dazu passen könnte.

von S. Landolt (Gast)


Lesenswert?

Das Erraten, welcher Wert angezeigt, welcher erwartet wird, welche 
Spannung überhaupt anliegt, übersteigt meine Fähigkeiten. Ich schaue mir 
stattdessen die Eco-Verfilmung an. Einen schönen Abend allerseits.

von c-hater (Gast)


Lesenswert?

SPIProgrammierer schrieb:

> Ich kann nicht so recht den Sinn erkennen bei einem SPI Master
> den Recieve Interrupt zu nutzen.

???

Die dedizierte SPI-Hardware der AVR8 bietet überhaupt nur einen 
Interrupt, weder braucht sie mehr noch hat sie mehr. Leider... Das liegt 
nämlich schlicht daran, dass sie nicht double-buffered ist. Wie auch 
immer: der TO benutzt genau diesen einen überhaupt nur möglichen 
Interrupt. Er konnte also diesbezüglich garnichts falsch machen und hat 
es demgemäss auch nicht getan.

Allerdings stimmt seine Interrupt*logik* schlicht nicht. Man muss den 
SPI-Interrupt im geeigneten Moment erlauben, Bytes mitzählen und den 
Interrupt im passenden Moment wieder verbieten.

Üblicherweise liegen solche Fehler daran, dass der Delinquent SPI als 
Solches überhaupt nicht verstanden hat. Und/oder nicht die 
SPI-Hardware...

Dabei ist das überaus trivial. Ein wenig spannend wird es erst mit den 
double-buffer-fähigen UARTs im SPI-Master-Mode. Dann kann man nämlich 
tatsächlich zwischen drei potentiell möglichen Interrupts wählen. Und 
für den Fall des hier offensichtlich avisierten "Burst-Modell" des 
Datenaustauschs ist da der RXC-Interupt sicher nicht die schlechteste 
Wahl...

von Jan H. (janiiix3)


Lesenswert?

S. Landolt schrieb:
> Das Erraten, welcher Wert angezeigt, welcher erwartet wird, welche
> Spannung überhaupt anliegt, übersteigt meine Fähigkeiten. Ich schaue mir
> stattdessen die Eco-Verfilmung an. Einen schönen Abend allerseits.

Was müsste ich denn ca. für einen A/D Wert bekommen bei einer 
Wechselspannung von ~18V?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> Ich habe eine ~18VAC Spannung am Eingang 3 angelegt (PhaseC)
> Mit entsprechenden Widerständen etc.

Jan H. schrieb:
> Was müsste ich denn ca. für einen A/D Wert bekommen bei einer
> Wechselspannung von ~18V?

Das hängt von den „entsprechenden Widerständen“ ab.  Sicher von noch
weiteren Faktoren, wenn ich das sehe, dass es ein ganzes Kapitel über
die Kalibrierung gibt.

Das Datenblatt wirst du wohl selbst erstmal verstehen müssen.

Wichtig wäre es doch als erstes, dass bei konstanter angelegter
Wechselspannung ein (einigermaßen) konstanter Wert herauskommt, und
bei einer geringeren Spannung ein kleinerer.

von S. Landolt (Gast)


Lesenswert?

> Was müsste ich denn ca. für einen A/D Wert bekommen bei
> einer Wechselspannung von ~18V?
Soll das heißen, dass am ADE7758 18 V~ anliegen? Im Datenblatt lese ich 
unter Maximum Ratings: "Analog Input Voltage to AGND: –6 V to +6 V."

von Jan H. (janiiix3)


Lesenswert?

Nein. Das ist eine Schaltung die schon fertig ist.

Es liegen maximal 360mV an.
Mir scheint es wirklich so als würde ich die 3 Bytes nicht richtig 
bekommen. Ich kann es auch nicht wirklich nachvollziehen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> Mir scheint es wirklich so als würde ich die 3 Bytes nicht richtig
> bekommen. Ich kann es auch nicht wirklich nachvollziehen.

Dann musst du es nachvollziehen lernen.

Sorry, deine eigene Arbeit können wir dir schlecht abnehmen.

Die Methoden, die ich als nächstes anwenden würde, habe ich dir
ja genannt: LA um zu sehen, dass der eingelesene Wert auch dem
Bitmuster entspricht, und Plausibilitätstest um zu sehen, dass
der gemessene Wert was mit der Eingangsspannung zu tun hat.

von Jan H. (janiiix3)


Lesenswert?

Jörg W. schrieb:
> Jan H. schrieb:
>> Mir scheint es wirklich so als würde ich die 3 Bytes nicht richtig
>> bekommen. Ich kann es auch nicht wirklich nachvollziehen.
>
> Dann musst du es nachvollziehen lernen.
>
> Sorry, deine eigene Arbeit können wir dir schlecht abnehmen.
>
> Die Methoden, die ich als nächstes anwenden würde, habe ich dir
> ja genannt: LA um zu sehen, dass der eingelesene Wert auch dem
> Bitmuster entspricht, und Plausibilitätstest um zu sehen, dass
> der gemessene Wert was mit der Eingangsspannung zu tun hat.

Ich habe die Spannung mit einem Stelltrafo geändert und das 
entsprechende Register ausgelesen. Synchron dazu das Temperatur 
Register. Alles habe ich auf einem LCD dargestellt.

Temperatur passt. Spannung jedoch nicht. Ich zweifel immer noch daran 
das ich die 3 bytes richtig auslese.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Naja, dann musst du schon von vorn anfangen und dir erstmal die Bits
auf dem Bus angucken.

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.