mikrocontroller.net

Forum: Compiler & IDEs falscher Rückgabewert aus SoftSPI


Autor: Gregor B. (gregor54321)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen!
Ich verwende das unten stehende Programm, um die SoftSPI am RFM12 
auszulesen. Am LogicAnalyzer kann ich gut sehen, wann und wie ausgelesen 
wird und was hätte auch im uC ankommen müssen.
Leider wird nicht der korrekte Wert unter der Variablen abgelegt sondern 
immer nur 0xFFFF. Woran kann das liegen? Ich suche mir daran schon seit 
Ewigkeiten einen Wolf, bis ich es nun schließlich endlich als Ursache 
identifizieren konnte!
unsigned int rf12_rxstatus(void)              {
  unsigned int werti=0;
  unsigned char i;
    uint8_t i_sreg = SREG;      // SREG sichern
    cli();                      // Interrupts unterbinden

  cbi(RF_PORT, CS);
    cbi(RF_PORT, SDI);

  for (i=0; i<16; i++) {  
    werti<<=1;
    if (RF_PIN&(1<<SDO))
      werti|=1;
    sbi(RF_PORT, SCK);
    _delay_us(0.3);
    cbi(RF_PORT, SCK);
  }
  sbi(RF_PORT, CS);
    SREG = i_sreg;
  return werti;
}

ISR (INT0_vect) {
  [...]
    rf12_int0_handler();
  [...]
}

void rf12_int0_handler() {
  uint16_t status_reg = 0;
  status_reg = rf12_rxstatus();
  [...]
  
  char buffa[30];
  sprintf(buffa, "Ergebnis: 0x%X\r\n",status_reg);
  uart_puts(buffa);
}

uint8_t main(void) {
  Activate_INT0;
  while(!) {
    nop();
  }
}

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ähm, normalerweise wird beim SPI in der Taktflanke gesampled, nicht 
davor.

>     _delay_us(0.3);
übrigends glaub ich nicht, dass das funktioniert. Was sagt der Compiler?

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
übrigends, lass als C-Progger das SREG in Ruhe. Wenn du Interrupts 
deaktivierst, dann brauchst du da nichts sichern.
:-)

Autor: Gregor B. (gregor54321)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Floh schrieb:
>>     _delay_us(0.3);
> übrigends glaub ich nicht, dass das funktioniert. Was sagt der Compiler?

Der Compiler nimmt's gelassen. Laut delay.h:
     void   _delay_us (double __us)
wird also gleich zu _delay_us(0) optimiert. Der High-Impuls dauert bei 
mir etwa 0.6us. ICH HAB'S ABER AUCH BLOß AUS 'NER LIBRARY KOPIERT... 
schäm
Die Sache mit dem SREG hab ich mir (aus alten ASM Zeiten) so angewöhnt. 
So kann ich solche Funktionen auch z.B. aus einer ISR anspringen, ohne 
das mir die INTs freigegeben werden.

Ich verstehe aber trotzdem nicht, warum bei SDO Dauer-Low 0xFFFF zurück 
gegeben wird. Stimmen denn die Übergaben der Variablenkopien und sind 
deren Typen kompatibel?

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schreib die Schleife mal testweise so um, damit du in der Taktflanke 
statt davor samplest:

Gregor B. schrieb:
> for (i=0; i<16; i++) {
>     werti<<=1;

>     sbi(RF_PORT, SCK);

>     _delay_us(0.3);

>     if (RF_PIN&(1<<SDO))
>       werti|=1;

>     _delay_us(0.3);

>     cbi(RF_PORT, SCK);

:-)

Autor: Edi R. (edi_r)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Obwohl ein paar Unschönheiten enthalten sind, sollte zumindest die 
Routine rf12_rxstatus funtionieren. Stimmt denn der Rest des Programms, 
speziell die defines für RF_PORT, RF_PIN, CS, SDI, SDO und SCK? Sind die 
Datenrichtungsregister richtig eingestellt (SDO als Eingang)?

Autor: Gregor B. (gregor54321)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In der Lib sind wahrlich noch mehrere Unschönheiten wie
RF_DDR  = (1<<SDI)|(1<<SCK)|(1<<CS);
anstelle von
RF_DDR  |= (1<<SDI)|(1<<SCK)|(1<<CS);
 Ich hab auch den Sample-Zeitpunkt geändert. Danke Floh!
Aber daran allein hat es hier nicht gelegen! Ich hab nochmal den 
Messkopf in die Hand genommen: ICH HASSE DAS BLÖDE JTAG-INTERFACE!!! 
Ich hab JTAG schon über die Software ausgeschaltet wenn PINx auf Low. 
Aber wenn der Stecker von Dragon noch drauf steckt, zieht der die 
Pegel(!!), die ich über Widerstände zum RFM gelegt hatte. LA natürlich 
am RFM angesteckt, an dem natürlich noch das Richtige rauskommt, nur 
eben nicht mehr beim uC rein...

ICH DAAAANKE EUCH !!

so, genug rumgebrüllt. ;o)

Autor: Rolf Magnus (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gregor B. schrieb:
> Floh schrieb:
>>>     _delay_us(0.3);
>> übrigends glaub ich nicht, dass das funktioniert. Was sagt der Compiler?

Warum sollte es nicht?

> Der Compiler nimmt's gelassen. Laut delay.h:
>      void   _delay_us (double __us)
> wird also gleich zu _delay_us(0) optimiert.

Kommt halt auf den Prozessortakt an. Bei z.B. 3,3 Mhz sind 0,3 µs ja 
gerade mal ein Taktzyklus.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.