mikrocontroller.net

Forum: Compiler & IDEs AT90CAN128 -> SPI -> DA-Wandler MAX5105


Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich versuche gerade einen DA-Wandler über SPI anzusprechen. Bis jetzt 
leider ohne Erfol.

Der DA-Wandler erwartet ein 14-bit Wort nach dem Scheme:

1 Startbit, 2 Controlbits, 3 Adressbits und 8-Datenbits.

folgendes möchte ich Übertragen:

1 0 1 0 0 0 1 1 , 1 1 1 1 1 1

Das wäre meine 14-bit Information, um das zweite Byte vollzubekommen 
häng ich noch 2 0er an. Die letzten zwei Stellen sind ja eh don`t care 
für den DA-Wandler(?).

Also übertrage ich 0xA3 und 0xFC mit folgendem Program:
#include <stdlib.h>
#include <avr/io.h>
#include <avr/signal.h>

#define SS PB0
#define MOSI   PB2
#define SCK  PB1
#define CS  PE6

SIGNAL (SIG_SPI) {
  return;
}

void SPI_Master_TransmitInit(void)
{
  /* Set MOSI, SS und SCK als Ausgang */
  DDRB |= (1<<MOSI) | (1<<SCK) | (1<<SS);
  DDRE |= (1<<CS);      //Chip select als Ausgang  
  PORTB |=(1<<SS);      //Slave select High
  PORTE |= (1<<CS);      //Chip select High
  /* Enable SPI Interrupt, Enable SPI, Master, f = FCPU/16 */
  SPCR = (1<<SPIE) | (1<<SPE) | (1<<MSTR) | (1<<SPR0);
}

void SPI_MasterTransmit(void)
{
  PORTE &= ~(1<<CS);    //Chip select Low
  PORTB &= ~(1<<SS);    //Slave select Low
  SPDR = 0xA3;        //Erstes Byte senden
  while(!(SPSR & (1<<SPIF))); // warte bis Byte gesendet
  SPDR = 0xFC;          //Zweites Byte senden  
  while(!(SPSR & (1<<SPIF))); // warte bis Byte gesendet
  PORTE |=(1<<CS);      //Chip select High
  PORTB |=(1<<SS);      //Slave select High
}

int main (void)
{ 
  sei(); 
  SPI_Master_TransmitInit();
  SPI_MasterTransmit(); 
 
  while(1)  
  return 0;
}

Nicht wundern wegen SS und CS, CS geht an den DA-Wandler, SS ist über 
Widerstand auf Masse, ist Hardwaremäßig so vorgegeben.

Weiß vielleciht jemand einen Rat was Faul sein könnte?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum aktivierst du den SPI-Interrupt, wenn du dann einen leeren
Handler dafür hast?  Ich denke, dass du auf diese Weise nicht auf
das SPIF pollen kannst, da das vom sofort eintreffenden Interrupt
,,verschluckt'' wird.  Entweder schaltest du SPIE ab und pollst,
oder du setzt im SPI-Interrupthandler eine Flagvariable, die du
dann pollst.

Slave select benutzt man normalerweise als chip select, wenn man
SPI-Master ist.  Da du ein anderes Pin benutzen willst, brauchst
du dich damit auch gleich gar nicht erst herumzuschlagen.  Solange
das Pin ein Ausgang ist, ist es für den Master uninteressant.

Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der SPI Interrupt ist aktiviert weil beim Aufruf des Handlers 
automatisch SPIF gelöscht wird. Ich habe leider noch keine andere 
Möglichkeit gefunden SPIF zu löschen. Dies Methode hab ich aus einem 
Codebeispiel übernommen.
Wie könnt man die SPIF so noch löschen? Aus dem Datenblatt bin ich da 
nicht schlau geworden.
"...SPIF is cleared by hardware when executing the
corresponding interrupt handling vector. Alternatively, the SPIF bit is 
cleared by first reading the
SPI Status Register with SPIF set, then accessing the SPI Data Register 
(SPDR)...."

Den Slave select hab ich nur mit reingenommen um sicherzugehen das die 
SPI funzt. Die Zeile stört ja nicht weiter.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Timo wrote:

> Der SPI Interrupt ist aktiviert weil beim Aufruf des Handlers
> automatisch SPIF gelöscht wird.

Aber wenn es automatisch gelöscht wird, kannst du nicht drauf
warten, dass es je gesetzt wird.  Das Ding hat nur einen so kurzen
Moment den Wert 1, dass du das mit deiner Abfrage nicht sehen
wirst.

> Wie könnt man die SPIF so noch löschen? Aus dem Datenblatt bin ich da
> nicht schlau geworden.
> "...SPIF is cleared by hardware when executing the
> corresponding interrupt handling vector. Alternatively, the SPIF bit is
> cleared by first reading the
> SPI Status Register with SPIF set, then accessing the SPI Data Register
> (SPDR)...."

Naja, du liest das Statusregister, bis SPIF gesetzt ist (das machst
du ja sowieso schon), und greifst danach entweder lesend oder
schreibend auf SPDR zu.  In deinem Fall wird also das nächste
Beschreiben des SPDR (um das nächste Byte zu senden) das SPIF wieder
löschen.

Nimm das SPIE raus, und ich denke, dass es dann geht.

Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich kann nur sagen das das Program vom Ablauf her funktioniert hat, 
d.h. das die Schleife while(!(SPSR & (1<<SPIF))); sauber abgebrochen 
hat. Ich debugge über JTAG und das Program ist sauber Zeile für Zeile 
abgearbeitet worden.

In meinem ersten Versuch hab ich das ganze ohne Interrupt versucht, hat 
aber auch nicht funktioniert...

Ich verzweifel noch mit dem Scheiß hier ;)

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.