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


von Timo (Gast)


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:
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <avr/signal.h>
4
5
#define SS PB0
6
#define MOSI   PB2
7
#define SCK  PB1
8
#define CS  PE6
9
10
SIGNAL (SIG_SPI) {
11
  return;
12
}
13
14
void SPI_Master_TransmitInit(void)
15
{
16
  /* Set MOSI, SS und SCK als Ausgang */
17
  DDRB |= (1<<MOSI) | (1<<SCK) | (1<<SS);
18
  DDRE |= (1<<CS);      //Chip select als Ausgang  
19
  PORTB |=(1<<SS);      //Slave select High
20
  PORTE |= (1<<CS);      //Chip select High
21
  /* Enable SPI Interrupt, Enable SPI, Master, f = FCPU/16 */
22
  SPCR = (1<<SPIE) | (1<<SPE) | (1<<MSTR) | (1<<SPR0);
23
}
24
25
void SPI_MasterTransmit(void)
26
{
27
  PORTE &= ~(1<<CS);    //Chip select Low
28
  PORTB &= ~(1<<SS);    //Slave select Low
29
  SPDR = 0xA3;        //Erstes Byte senden
30
  while(!(SPSR & (1<<SPIF))); // warte bis Byte gesendet
31
  SPDR = 0xFC;          //Zweites Byte senden  
32
  while(!(SPSR & (1<<SPIF))); // warte bis Byte gesendet
33
  PORTE |=(1<<CS);      //Chip select High
34
  PORTB |=(1<<SS);      //Slave select High
35
}
36
37
int main (void)
38
{ 
39
  sei(); 
40
  SPI_Master_TransmitInit();
41
  SPI_MasterTransmit(); 
42
 
43
  while(1)  
44
  return 0;
45
}

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?

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


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.

von Timo (Gast)


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.

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


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.

von Timo (Gast)


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 ;)

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.