mikrocontroller.net

Forum: Compiler & IDEs SPI Master Rx Problem


Autor: Georg Bauerfeind (Firma: Devel Solutions) (shorsh)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo leute, folgendes Problem:
ich möchte von einem 16Bit ADC (AD977A) Datenempfangen. Dieser hat eine 
Art "halbes" SPI... D.h. er wird vom MCU (ATMega32-->Master) geklockt, 
und der ATMega empfängt mit MISO.

Die 16bit möchte ich auslesen in dem ich jeweils imner ein 8bit paket 
sende und direkt wieder auslese. Und das ganze 2mal hintereinander, 
wegen 16bit Wortbreite.
So bekomme ich aber für conv_data_H immer nur dasselbe heraus und höchst 
unterschiedl. Wert für die gleichen Eingangsspannungen am ADC.
Kann das so überhaupt funktionieren, was sagt ihr??

#include <avr/interrupt.h>
#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>

ISR(INT2_vect) //Conversion finished
{
cli();
uint8_t conv_data_H, conv_data_L;
conv_data_H = 0;
conv_data_L = 0;


PORTB |= (1<<PB7);     //Set SCK output
PORTB &= ~(1<<PB6);    //SET MISO input
PORTB |= (1<<PB5);    //SET MOSI Output(wird hier nicht  //gebraucht Pin 
hängt in der Luft)
SPCR = (1<<MSTR)|(1<<SPR0) | (1<<SPR1); /* Enable SPI, Master, set clock 
rate fck/128 */
SPCR |=(1<<CPHA);     //CPOL = 0, CPHA = 1
SPCR |= (1<<SPE);    //SPI_enable

SPDR = 0xF0;
conv_data_H = SPDR;
while(!(SPSR & (1<<SPIF)));
SPDR = 0xF0;
conv_data_L = SPDR;
sei();
}


int main()
{
cli();
GICR|=(1<<INT2); //INT2 ist Trigger für |Busy, steig. flanke
MCUCSR |= (1<<ISC2); //INT2(PB2) ein!
DDRB = 0b10100000;   //
PORTB |= ( 1<<PB0); //START_conv 1x DummyConversion
PORTB &= ~(1<<PB0);
PORTB |= ( 1<<PB0);
_delay_ms(1);
sei();               //Interupts an
PORTB &= ~(1<<PB0);
PORTB |= ( 1<<PB0);

while(1)
{
;
}

}

Ist der Ansatz Prinzipiell richtig?

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Woher kennst du denn den Inhalt der Variablen conv_data_H, ~_L ? Die 
sind doch nur lokal in der ISR... ;)

Im Datasheet gibt's die Kapitel "EXTERNAL DISCONTINUOUS CLOCK DATA READ
AFTER CONVERSION ..." und "EXTERNAL DISCONTINUOUS CLOCK DATA READ
DURING CONVERSION ..". Du willst scheinbar ersteres.

In beiden Fällen kann CS an GND angeschlossen werden und mit R\C wird 
die Wandlung gesteuert: RC muss vor dem auslesen auf high.

Das sieht soweit korrekt aus bei dir, ABER:
 - du brauchst kein cli()/sei() in der ISR
 - der AD-Wandler verträgt 15MHz SPI-takt, F_CPU/128 ist da bestimmt 
nicht notwendig/verlängert unnötig deine ISR
 - das SPIF flag ist nicht vom startweg gesetzt, sondern erst nach einer 
Übertragung, also besser grundsätzlich erst SPDR schreiben und danach 
auf das Flag warten
- warum schreibst du das DAC-Ergebnis nicht gleich in eine 16Bit 
Variable (int, int16_t)?
- Wenn du das Ergebnis in main() haben willst, musst du es dort 
hinbringen -> mit einer volatile globalen Variable

hth Jörg, der Datenblattleser ;)

ps.: wenn du noch mehr Probleme hast, poste bitte deine Schaltung (der 
ADC wird ja mit diversen Pins konfiguriert...)

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zusätzlich zu Jörg:

>conv_data_H = 0;
>conv_data_L = 0;

Kannst du dir komplett sparen. Werden beim lesen
von SPDR sowieso wieder überschrieben.

PB4/SS wird nicht auf Ausgang geschaltet.
Da wird der Master evtl. ganz schnell wieder zum Slave.

>PORTB |= (1<<PB7);     //Set SCK output
>PORTB &= ~(1<<PB6);    //SET MISO input
>PORTB |= (1<<PB5);    //SET MOSI Output(wird hier nicht  //gebraucht Pin

Das sollte wohl DDRB statt PORTB heissen.
Hat in der ISR aber auch nichts zu suchen.

Auch SPCR setzt man besser nicht in der ISR.

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achja, hab ich vorhin vergessen:
nimm die ganze SPI-Register- und Port-Initialisierung aus der ISR!
  Da musst du meistens gar nichts machen, es sei denn du hast mehrere 
SPi-Slaves mit unterschiedlichen Modi bzw. Geschwindigkeiten.

hth. Jörg

Autor: Georg Bauerfeind (Firma: Devel Solutions) (shorsh)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke erstmal für die schnellen comments!
es lag v.a. am nicht gesetzen |ss
sollte nur ein test sein ob das überhaupt funzt. werde eure hints morgen 
umsetzen.

gruß georg

Autor: Georg Bauerfeind (Firma: Devel Solutions) (shorsh)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg X. wrote:

> - warum schreibst du das DAC-Ergebnis nicht gleich in eine 16Bit
> Variable (int, int16_t)?

Weil SPDR nur 8bit breit ist, dachte ich! also, wenn ich das mit 
uint16_t auslese machen die werte wenig sinn, bzw. scheint so als würde 
er ein byte "abschneiden"...
wie kann ich das denn direkt auslesen, oder warum sollte das überhaupt 
direkt funzen?

mfg
g.brfd

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>wie kann ich das denn direkt auslesen,
uint16_t ergebnis; /* vielleicht auch besser int16_t, wenn der ADC auf
 2erkomplement eingestellt ist */
uint8_t tmp; // nicht wirklich notwendig, aber besser lesbar:
tmp = spi_put_byte(DUMMY);
ergebnis = ((uint16_t) tmp)<<8; /* bin mir hier mit den Klammern nicht
     ganz sicher */
tmp = spi_put_byte(DUMMY);
ergebnis |=  tmp;
//...
//wenn dich "tmp = spi_PUT_byte(DUMMY);" stoert:
#define spi_get_byte() spi_put_byte(DUMMY)
//;)

hth. Jörg

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.