Forum: Mikrocontroller und Digitale Elektronik SPI auf XMEGA


von Engine H. (engine)


Lesenswert?

Hallo ,

ich versuche seit Stunde die SPI auf einen XMEGA zum Laufen zu bringen, 
leider vergeblich. hier ist mein Code :

#include <avr/io.h>
#define F_CPU 32000000UL
#define SPIPort PORTD
#define SPICTRL SPID
#define SPIMO   5
#define SPIMI   6
#define SPISC   7
#define SPISS   0

char SPIDir = 0 ;

void spiopen(void)
{
    SPIDir = SPIPort.DIR ;
    SPIPort.DIRCLR = (1<<SPIMI);
    SPIPort.DIRSET = (1<<SPIMO) | (1<<SPISC) | (1<<SPISS) ; // Make sure 
slave select is an output
    SPICTRL.CTRL = SPI_ENABLE_bm | SPI_MASTER_bm | SPI_MODE_0_gc | 
SPI_PRESCALER_DIV64_gc;
}



void spiclose(void)
{
    SPICTRL.CTRL = 0;
    SPIPort.DIR = SPIDir ;
    SPIPort.DIRSET = (1<<SPIMI);
}

uint8_t spi(uint8_t val)
{
    SPICTRL.DATA = val ;
    while(!(SPICTRL.STATUS & (1<<7)));
    return SPICTRL.DATA;
}


int main(){
 OSC.CTRL = OSC_RC32MEN_bm; /* Enabling the 32MHz RC oscillator */
    while (!(OSC.STATUS & OSC_RC32MRDY_bm)); /* wait for ready */
        CCP = CCP_IOREG_gc;/* allow changing CLK.CTRL */
        CLK.CTRL = CLK_SCLKSEL_RC32M_gc ;/* system clock is internal 
32MHz RC */
   spiopen();
while(1){
   spi('U');
}
return 0;
}


Ich kann  auf alle PINs ( MOSI SLC SS ) kein Signal messen ?  kann 
jemand mir verraten wo der Fehler ist ?
Danke

von Mitlesa (Gast)


Lesenswert?

>> Wichtige Regeln - erst lesen, dann posten!
>> ............
>> ............
>> Formatierung (mehr Informationen...)
>>
>>
1
C-Code

von Jim M. (turboj)


Lesenswert?

Ich hab jetzt keine Lust das Manual rauszupflücken, aber die Abfrage des 
Busy Bits sieht verkehrt herum aus.

von Engine H. (engine)


Lesenswert?

Hallo, Danke für den Hinweis,

ich weiss nicht ob es die richtige Zeile die du meinst , aber  das ist 
richtig :

while(!(SPICTRL.STATUS & (1<<7)));

von Gerhard G. (g_g)


Lesenswert?

Hallo,

uint8_t spi(uint8_t val)
{
    SPICTRL.DATA = val ;
    while(!(SPICTRL.STATUS & (1<<7)));
    return SPICTRL.DATA;
}


das Datenregister muss SPIC_DATA heißen!!

Nicht  SPICTRL.DATA


Gruß G.G.

von Gggast (Gast)


Lesenswert?

Die ganzen SPICTRL.xxx Register gibt es nicht! Sie müssen mit dem Namen 
des zu verwendenden SPI beginnen, also SPIC. oder SPID. und so weiter.

von Sascha W. (sascha-w)


Lesenswert?

die hat er doch am Anfang per define als Alias festgelegt.

Sascha

von Basti (Gast)


Lesenswert?

Einfach mal nen ASF SPI example Projekt generieren und schauen wie Atmel 
das gelöst hat... oder gleich ASF benutzen... find die nicht so 
verkehrt...

von Thomas F. (tomasf)


Lesenswert?

Basti schrieb:
> Einfach mal nen ASF SPI example Projekt generieren und schauen wie Atmel
> das gelöst hat... oder gleich ASF benutzen... find die nicht so
> verkehrt...

oder die dazugehörige application note "AVR1309: Using the XMEGA SPI" 
lesen und den dazugehörigen Beispielcode nehmen.

von FritzFrosch (Gast)


Lesenswert?

Hallo
Ich suche nun seit gut einem Nachmittag fehler beim XMega SPI Register. 
Ich will nicht die Application notes nehmen, da ich die SPI selbst 
Porgrammieren will. (challange & verständniss)
nun komme ich selbst aber nicht mehr vom Fleck und messe an den Pins des 
Xmega auch kein singnal oder CLk.

Hier der Code:

1
void init_SPI(void)
2
{  
3
  SPIE.CTRL = 0b11110010;  //Controllregister
4
5
  SPIE.INTCTRL = 0b00000010;  //Interrupt Control register
6
7
  SPIE.STATUS = 0b00000000;     //Status register
8
                      
9
  SPIE.DATA = 0b00000000;  //Send and Recive data       
10
}
11
12
void send_Data_SPI(unsigned char ucData);
13
{  SPIE.DATA = ucData;
14
  
15
  while(!(SPIE.STATUS & (1<<7)));
16
  
17
}


Ich hoffe jemand weiss wo der Fehler liegt..

von Timmo H. (masterfx)


Lesenswert?

Einmal den kompletten Code bitte (Minimalbeispiel)

von FritzFrosch (Gast)


Lesenswert?

Da währe der komplette code

[c]
void PortInit(void)
{
  PORTE.DIR = 0b10011100; //SPI [7:4]
}
void init_SPI(void)
{
  SPIE.CTRL = 0b11110010;  //Controllregister

  SPIE.INTCTRL = 0b00000010;    //Interrupt Control register

  SPIE.STATUS = 0b00000000;  //Status register

  SPIE.DATA   = 0b00000000;  //Send and Recive data
}

void send_Data_SPI(unsigned char ucData)
{  SPIE.DATA = ucData;

   while(!(SPIE.STATUS & (1<<7)));

}

int main(void)
{ unsigned char i = 0;
  SetupExtOscPLL();
  PortInit();

  init_SPI();
  while(1)
  {  send_Data_SPI(i);
     wait_1ms(10);
     i++;
  }
}[c/]

von Sascha W. (sascha-w)


Lesenswert?

wenn du anstatt die eindeutigen Registernamen nochmals zu kommentieren 
lieber hingeschrieben hättest was du mit den Bitmasken eigenlich 
einstellen willst, dann könnte man auch sinnvoll nach einem Fehler 
suchen.

Sascha

von Timmo H. (masterfx)


Lesenswert?

> PORTE.DIR = 0b10011100; //SPI [7:4]

Ist PORTE Pin7 nicht SCK und PORTE Pin5 nicht MOSI...?

Chipselect hast du nicht? Solltest du beim Zugiff auf Low ziehen, das 
macht nicht die Hardware ("In master mode, the SPI interface has no 
automatic control of the SS line")

Bitte versuche die verständlichen Bitmasken zu vewenden, dann weiß man 
auch gleich was passiert:

SPIE.CTRL |= SPI_ENABLE_bm | SPI_MASTER_bm | SPI_MODE_2_gc | 
SPI_PRESCALER_DIV16_gc; // etc.

oder eben das _bp Äquivalent

: Bearbeitet durch User
von Matthias F. (frank91)


Lesenswert?

In einem früherem Projekt von mir wollte ich den SPI des Xmega 
verwenden, allerdings hatte ich die entsprechenden Pins nicht mehr frei.
Deswegen hab ich das ganze versucht softwaretechnisch zu lösen. Und das 
hat auch so funktioniert.
Ich kann dir gerne morgen ein Beispiel hier posten, wenn dir das eine 
Hilfe sein sollte.

von Timmo H. (masterfx)


Lesenswert?

Software SPI ist ja nicht das Prob:
1
#define CS_HIGH() PORTE.OUTSET = (1<<PIN1)
2
#define CS_LOW()  PORTE.OUTCLR = (1<<PIN1)
3
4
void Soft_SPI_init(){  
5
  
6
  PORTE.DIR = (1<<PIN2) | (1<<PIN1) |(1<<PIN0);  //MOSI & CSN & CE
7
  PORTA.DIR = (1<<PIN0);  //SCK
8
  
9
  PORTA.OUTCLR = (1<<PIN0); //SCK low
10
  
11
  CSN_HIGH();
12
  CE_LOW();
13
14
}
15
16
17
unsigned char SPI_transfer( unsigned char value )
18
{
19
20
  uint8_t bit_ctr;
21
  
22
  for(bit_ctr=0;bit_ctr<8;bit_ctr++)   // output 8-bit
23
  {
24
    if(value & 0x80)
25
    {
26
      PORTE.OUTSET = (1<<PIN2);
27
    }
28
    else
29
    {
30
      PORTE.OUTCLR = (1<<PIN2);
31
    }
32
33
    value = (value << 1);           // shift next bit into MSB..
34
    PORTA.OUTSET = (1<<PIN0);    // Set SCK high..
35
    if(PORTE.IN & (1<<PIN3))
36
      value |= 1;             // capture current MISO bit
37
    else
38
      value &= ~1;
39
    
40
    PORTA.OUTCLR = (1<<PIN0); // ..then set SCK low again
41
  }
42
  return(value);                 // return read UINT8
43
  
44
}
45
46
void SPI_Write_Reg(uint8_t reg, uint8_t value)                 
47
{
48
49
  CE_LOW();
50
51
  SPI_transfer(reg);  // select register
52
  SPI_transfer(value);  // ..and write value to it..
53
54
  CE_HIGH();
55
}      
56
57
uint8_t SPI_Read_Reg(uint8_t reg)                               
58
{                                                           
59
  uint8_t value;
60
61
  CE_LOW();
62
63
  SPI_transfer(reg);            // Select register to read from..
64
  value = SPI_transfer(0);    // ..then read register value
65
66
  CE_HIGH();
67
68
69
  return(value);        // return register value
70
}
Aber Hardware ist auch nicht schwieriger und ist halt noch etwas 
schneller und kann ggf. auch per DMA gemacht werden

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.