Forum: Mikrocontroller und Digitale Elektronik Simples SPI an AVR32 funktioniert nicht


von Marcel K. (viewer)


Lesenswert?

Hallo Forumgemeinde,
ich versuche mich seit einiger Zeit mit den AVR32 anzufreunden. Als 
Hardware habe ich das EVK1100 (UC3A 0512-U). Die Beispielprogramme von 
Atmel bekomme ich zum laufen. Jetzt wollte ich einfach mal ein simples 
SPI-Programm erstellen. Aber schon bei so einem läppischen Projekt bin 
ich am verzweifeln. Mein Code sieht wie folgt aus:

//////////////////////////////////
#include <avr32/io.h>

int main(void)
{
int i;

AVR32_SPI0.MR.mstr = 1;    // Master Mode

AVR32_SPI0.MR.modfdis = 1;  // Modul Fault detection disabled

AVR32_SPI0.CSR0.scbr = 1;  // Baudrate- Teiler

AVR32_SPI0.CR.spien  = 1;  // SPI einschalten

while(1)
{
// warten bis das Transmite Data Register leer ist
while (!(AVR32_SPI0.SR.tdre) )
{
asm("nop");
}

AVR32_SPI0.TDR.td = 0x44;  // Daten in das Transmit Data Register 
schreiben

for(i=0;i<10000;i++)
{
asm("nop");
}
}
return (0);
}
//////////////////////////////////

Um zu sehen ob es klappt, habe ich ein Oszi am SCK- Pin hängen. Da tut 
sich aber absolut gar nichts. Wenn ich das ganze debugge, werden alle 
Bits, außer das "spien" Bit im Register CR, gesetzt. Das lässt sich 
einfach nicht schalten. Dann hatte ich die Idee, dass sich das Bit nicht 
schalten lässt, weil noch etwas fehlt. Dann ist mir der Power Manager 
eingefallen. Dann habe ich folgende Zeilen noch eingefügt:

AVR32_PM.hsbmask = (1<<1);  // PBA bridge aktivieren
AVR32_PM.pbamask = (1<<5);  // Takt einschalten

Hat aber auch nicht zum Erfolg geführt!
Man findet im I-Net leider nur SEHR wenige Codeschnipsel über den AVR32. 
Das ist wirklich sehr schade! Ich hoffe, dass mir jemand hier im Forum 
weiter helfen kann. Was mache ich falsch?? Ich bin über jede Hilfe echt 
sehr dankbar!!
Viele Grüße,
Marcel

von Marcel K. (viewer)


Lesenswert?

Ach, die GPIO's habe ich auch noch aktivert...


#define CS  10
#define SCK  13
#define MISO  11
#define  MOSI  12

#define A  0

AVR32_GPIO.port[A].gpers |= (1<<CS) | (1<<SCK) | (1<<MOSI) | (1<<MISO); 
// Pins aktivieren

AVR32_GPIO.port[A].oders |= (1<<CS) | (1<<SCK) | (1<<MOSI);        // 
Pins als Ausgang

von Klaus (Gast)


Lesenswert?

Hallo,


läuft der Controller?
1
pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);

von Peter D. (peda)


Lesenswert?

Marcel K. schrieb:
> Man findet im I-Net leider nur SEHR wenige Codeschnipsel über den AVR32.

Ja, der wird eben selten verwendet.
Ich kenne ihn auch nicht.

Beim normalen AVR gibt es einen Standardfehler:
SS-Pin vorher nicht als Ausgang definiert.

Und das "warten bis das Transmite Data Register leer ist" dürfte auch 
erst funktionieren, nachdem was gesendet wurde.


Peter

von Marcel (Gast)


Lesenswert?

Hallo Klaus,
nein das habe ich nicht!!!

Hmmm, das muss ich heute Abend dann gleich ausprobieren wenn ich Heim 
kommen!!

Danke für den Tipp!!

Hallo Peter,
ich werde das auch noch mal überprüfen, vielen Dank!!!

Ich meld mich dann noch mal...

Grüße, Marcel

von Phil S. (zippi)


Lesenswert?

Hi,

Ja die SPI an einem AVR32 ist schon etwas komplexer als am normalen AVR. 
Hatte damit auch anfangs Probleme. Wenn du nicht weiter kommst, dann 
kann ich gerne auch mal meinen Code für die SPI posten.

Gruß
Zippi

von Marcel K. (viewer)


Lesenswert?

Hallo Phil,
also ich habe mich eben dran gesetzt. Es ist so, ich versuche das ganze 
recht konventionell in Betrieb zu nehmen. Damit meine ich, nicht die 
Codes von Atmel zu verwenden, sondern es selber zu versuchen. Ich finde 
die ganzen „einstellerrei“ über Strukturen sehr unübersichtlich. 
Zumindest im Moment noch. Vielleicht ändert sich das ja mal. Aber jetzt 
möchte ich aus lenzwecken gerne jedes einzelne Bit selber setzen damit 
ich auch genau weiß was ich überhaupt mache! Ich bin jetzt gerade dabei 
herauszufinden wie die Fkt. Im Beitrag oben auszuführen ist.
[pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);]

Also wenn dein Code nicht ganz so kompliziert ist, bin ich über jede 
Info dankbar  :o)
Grüße, Marcel

von Phil S. (zippi)


Lesenswert?

Hi,

Ja ich habe es auch konventionell gemeint.
1
  //*************************************************************
2
  //**************DISPLAY POWER INIT*****************************
3
  //*************************************************************
4
5
6
  AVR32_GPIO.port[0].oders = 1 << 11;        // The output driver is enabled for the corresponding pin
7
  AVR32_GPIO.port[0].gpers = 1 << 11;        // Set GPIO PA11 to output
8
9
  AVR32_GPIO.port[0].ovrc = 1 << 11;        // Display power on.
10
11
  //*************************************************************
12
  //**************DISPLAY SPI INIT*******************************
13
  //*************************************************************
14
15
  AVR32_SPI0.mr = 1 << AVR32_SPI_MR_MSTR_OFFSET |                  // SPI0 mode 0 = slave  1 = master
16
          1 << AVR32_SPI_MR_MODFDIS_OFFSET ;                // SPI0 mode fault detection  0 = enable  1 = disable
17
18
19
  int  csr =   0 << AVR32_SPI_CSR0_CPOL_OFFSET |                   // inactive clock is 0;
20
        1 << AVR32_SPI_CSR0_NCPHA_OFFSET |                   // Active Edge == rising
21
        0 << AVR32_SPI_CSR0_CSAAT_OFFSET |                   // deselect device
22
        8 << AVR32_SPI_CSR0_BITS_OFFSET |                   // (BITS+8)Bits per transfer
23
        2 << AVR32_SPI_CSR0_SCBR_OFFSET |                    // clk == MCLK / scbr;
24
        0 << AVR32_SPI_CSR0_DLYBS_OFFSET |                   // 0 = 1 clk delay when chip selected
25
        0 << AVR32_SPI_CSR0_DLYBCT_OFFSET;                   // 0 = No delay between 2 transfers.AVR32_SPI.csr0 = csr;
26
27
  AVR32_SPI0.csr0 = csr;
28
  AVR32_SPI0.csr1 = csr;
29
  AVR32_SPI0.csr2 = csr;
30
  AVR32_SPI0.csr3 = csr;
31
32
  AVR32_SPI0.cr = AVR32_SPI_CR_SPIEN_MASK;                    // Enable SPI0
33
34
  while((AVR32_SPI0.sr & AVR32_SPI_SR_SPIENS_MASK)!= AVR32_SPI_SR_SPIENS_MASK);  // Wait for enable status

Das hier ist meine Init. Ich habe aber den CS pin immer peer IO 
gesetzt(Hatte was mit dem Display zu tun)

Hier dann noch meine Sende funktion
1
    AVR32_SPI0.tdr =data[i];
2
3
    while((AVR32_SPI0.sr & AVR32_SPI_SR_TDRE_MASK)==0);    // The last data written in the Transmit Data Register has been transferred to the serialize

Gruß
Zippi

von Marcel K. (viewer)


Lesenswert?

Hallo Zippi,
erst mal vielen Dank für Deinen Code.
Kann es sein, dass ich den hier irgenwo schon mal gesehen hab? Bin mir 
nicht sicher. Kommt mir irgendwie bekannt vor. Kann mich aber auch 
irren. Egal. Echt super!! :o)
Ich werd mich mal dran setzen und mich wieder melden!!!
Schönen Abend noch und Grüße,
Marcel(",)

von Marcel K. (viewer)


Lesenswert?

Ach PS:
Wie sieht es denn mit dem Power-Manager aus? Habe ich es richtig 
erkannt, dass defaultmäßig alles aktiv ist? Du hast nichts im Code 
stehen?
Danke für die Info!!!

von Phil S. (zippi)


Lesenswert?

Ja kann sein das der schon mal hier ausgetaucht ist.
Defaultmäßig ist die SPI Clock aktiv im PM. Also brauchst du nich extra 
anschalten ;).

Gruß

von Marcel K. (viewer)


Angehängte Dateien:

Lesenswert?

Hallo,
also ich habe meine Code jetzt nach Deinen Angaben geändert. Die 
Ansteuerung mit dem Dispaly brauch ich jetzt noch nicht, kommt aber 
hoffentlich noch ;)
Statdessen habe ich eine LED mit in das Programm genommen die durch sein 
blinken mit signalisier, dass das Programm läuft!
Ich kann am SPI0/SCK (beim EVK1100 = J6) aber gar nichts messen. Wenn 
ich mit das ganze mit dem debugger anschaue, wird immer noch nicht das 
SPIEN Bit gesetzt. Das gibt es doch nicht?! Den LED- Pin sehe ich immer 
toggeln aber das .CR.SPIEN- Bit ändert sich einfach nicht :o(

Grüße,
Marcel

von Marcel K. (viewer)


Angehängte Dateien:

Lesenswert?

Hallo Forumgemeinde,
also ich habe jetzt die letzten zwei Tage mit dem SPI verbracht und bin 
einfach nicht weiter gekommen :o(
Also ich habe meinen Code mal so geändert, dass ich über ein Define die 
MOSI- und MISO- Leitungen intern brücken kann. Dann funktioniert 
zumindest das blinken der zwei LED’s. Dies bestätigt mir zumindest, dass 
der SPI mit einem Takt versorgt wird.
Was aber immer noch nicht geht, ist der SPI- Takt so wie der 
Chip-Select! Ich habe erwartet, dass ich mit dem schreiben 
[AVR32_SPI0.MR.pcs = 0/1] den Chip-Select auswählen kann. Aber am SS-Pin 
von J6 tut sich absolut gar nichts. SCK bleibt low bzw. SS bleibt high.
Was mache ich falsch? Kann mir jemand weiterhelfen?
Viele Grüße,
Marcel

von Jens A. (micro)


Lesenswert?

Hallo,

hast du den für jedes Chip Select den passendne Takt konfiguriert.
Wie das sPI funktioniert weist du?
Es ist ein Hardware SPI. Du  muss für jeden Channel
alles einstellen. Dann wen du z.B. über SPI0 mit dem CHipselect 0
senden willst muss du als erstes den Chip selectieren,
dann schreiben oder lesen und dann wieder das Chipselect wegnehmen.
Man kann das SPI Modul auch so konfigurieren das das CS automatisch 
weggenommen wird.

von Marcel K. (viewer)


Lesenswert?

Hallo Jens,
Danke erst mal für deine Antwort. Naja, wie das SPI richtig 
funktioniert, weiß ich anscheinend nicht, sonnst würde es ja jetzt bei 
mir laufe :.(
Also bevor ich ja in die main-Schleife komme, wird das csr0-Register mit 
den gewünschten Parametern geladen.  Über das CSAAT- Bit kann man 
eistellen, ob dass CS nach jeder Übertragung selbständig deaktiviert 
wird oder nicht. Ich habe beide Versionen probiert, ohne Erfolg. Das CS0 
wird bei meiner Senderoutine vor dem schreiben in das TDR, mit 0 
aktiviert und nach erfolgreichen senden wieder mit 1 deaktiviert. Ich 
denke dass so ein Sendeablauf funktionieren sollte. Abe da liege ich 
wohl falsch.
Gruß Marcel

von Phil S. (zippi)


Lesenswert?

Hi,

Ich sehe grade, du solltest vll vorher mal die PLL programmieren. Es 
kann sein das du sonst die SPI garnet nutzen kannst.
Weißt du wie du die PLL einstellst? Sonst poste ich mal meinen CPU_CLK 
code. Dem musst du dann nur noch sagen mit wieviel MHz die CPU laufen 
soll.

Gruß
Zippi

von Marcel K. (viewer)


Lesenswert?

Hallo Zippi, schön von Dir zu höhren.
Also wie man die PLL programmiert, weiß ich im Moment noch nicht! Auf 
die schnelle habe ich mal im Atmel-Beispiel geschaut. Aber das möchte 
ich nur ungerne verwenden. Ich muss mir das Kapitel "Power-Manager" wohl 
noch etwas genauer durchlesen! Die Formel für den PLL sieht für mich im 
Moment doch recht komplex aus. Über einen Codeschnipsel von dir würde 
ich mich sehr freuen.
Ich dachte mir nur, wenn mein Test-Mode (MOSI &  MISO sind intern 
gebrückt) funktioniert, dann läuft auch der zuständige Takt für die SPI.
Ich sehe schon es gibt echt noch viel zu lernen beim 32-Bit Prozessor!!!

Grüße, Marcel

von Phil S. (zippi)


Lesenswert?

HI,

Hier Habe ich den Code schonmal gepostet gehabt:
Beitrag "Re: AVR32: Wie Ausgänge/Eingänge schalten/einlesen"

Kannst den einfach so bei dir hineinkopieren und die Funtkion ausrufen. 
24Mhz sind erstmal ok.

>Ich dachte mir nur, wenn mein Test-Mode (MOSI &  MISO sind intern
>gebrückt) funktioniert, dann läuft auch der zuständige Takt für die SPI.
>Ich sehe schon es gibt echt noch viel zu lernen beim 32-Bit Prozessor!!!
Ich bin mir nicht ganz sicher ob es wirklich an der PLL liegt. Aber der 
Interne Takt ist sowieso nicht zu gebrauchen(125khz) ;).

Gruß

von Marcel K. (viewer)


Angehängte Dateien:

Lesenswert?

Hi zippi,
also an der PLL scheint es nicht zu liegen. Sowohl der SCK als auch der 
SS ändern sich immer noch nicht!
Also ich muss echt sagen, ich verliere so langsam echt die Lust!!! Das 
kann doch nicht so schwer sein!!
Was mir noch einfällt; es ist ja immer das Problem, wenn man selber ein 
Projekt erstellt, das dieses ja nicht an der Adresse 0x80002000 startet. 
Das muss man, glaub ich, irgendwie über ein "trampolin.c" machen. Dies 
habe ich aber nicht gemacht!  Ich muss immer erst mal den Reset-Knopf 
drücken bevor mein Programm läuft. Kann es vielleicht daran liegen?
Grüße,
Marcel

von Phil S. (zippi)


Lesenswert?

Womit Programmierst du dein Board? Mit JTAG oder mit dem USB bootloader?

Also wenn du nur mit dem Bootloader programmierst, dann kann dein 
Projekt nicht funktionieren wenn du keine trampolin.c oder kein 
Linkerskript im Projekt hast. Sonst kann sich dein Controller im undef 
zustand befinden.

Gruß

von Marcel K. (viewer)


Lesenswert?

Ne, ich programmiere mit dem Dragon über JTAG!
Ich habe da noch mal ne Frage...
Es wird ja bei mir auf den "SPI-Enable-Status" gewartet. Was sagt dieser 
denn genau aus? Heißt dass, wenn der Status gesetzt ist, dass SPI dann 
voll funktionstüchtig ist? Oder nur dass SPI bereits ist aber noch ein 
paar Paramter fehlen?

Grüße,
Marcel

von Phil S. (zippi)


Lesenswert?

>Ne, ich programmiere mit dem Dragon über JTAG!
Gut, Ich hoffe du hast vorher ein Chip Erase gemacht, sonst ist der 
bootloader noch drauf und du kannst den bereich von 
0x80000000-0x80001FFF nicht überschreiben.

Der SPI-Enable-Status, sagt nur aus, das die SPI jetzt angeschaltet ist.
0 = SPI is disabled.
1 = SPI is enabled.

Hast du mal meinen Code ohne CS getestet? Hast du eigentlich ein Oszil 
da um den MOSI ausgang zu messen?

Gruß

von Marcel K. (viewer)


Angehängte Dateien:

Lesenswert?

Hallo zippi,
was meinst Du mit „ohne CS“? Ich habe ja Deinen Code übernommen (siehe 
Anhang) Dort hast Du ja das „AVR32_SPI_CSR0_CSAAT_OFFSET“- Bit auf 0 
stehen. Somit wird ja das CS-Bit automatisch gesetzt, bzw. gelöscht. 
(ich hoffe ich habe das so richtig verstanden) Ich habe es aber mit 
beiden Versionen probiert. Also auch mit dem manuellen setzten des 
CS-Bits.
Ja, ich habe ein Oszi. Damit überwach ich sowohl den SS-Pin als auch das 
SCK-Bit.
Marcel

von Phil S. (zippi)


Lesenswert?

Ich hab dir mal ne PN geschrieben.

Bin aber heut abend nicht mehr on.

Gruß
Zippi

von Marcel K. (viewer)


Lesenswert?

Ich habe das ganze jetzt endlich zum laufen bekommen. Ein großes 
DANKESCHÖN geht an zippi, der hat sich echt bemüht mir zu helfen. ECHT 
klasse, vielen DANK!!
Ich habe das ganze Mal in der Rubrik „Codesammlung“  gepostet.

Beitrag "SPI0 am AVR32 für Anfänger ;o)"

Vielen Dank auch den anderen Helfern in diesem Forum.

Grüße,
Marcel

von Peter D. (peda)


Lesenswert?

Woran lags denn?


Peter

von Marcel K. (viewer)


Lesenswert?

Hoppla, das habe ich ganz vergessen zu erzählen...

Ich benutze als OSZI ein PCS64i von Voltcraft. (schließt man an den 
parallel-Port des Rechners an)

Ich habe dann den Code von zippi verwendet. Darin wird der PLL verwedet. 
Der hat dann so hoch getaktet, dass ich am SCK nichts mehr gesehen habe. 
Als ich mir dann aus der Firma ein Oszi mitgenommen habe, konnte ich 
eine Frequenz von 40kHz messen. Das war dann zu viel für mein 
Basteloszi.
Ich muss sagen, dass ich in den letzten Jahren sehr zufrieden mit dem 
PCS64i war. Ich hatte aber auch nie Frequenzen über 10kHz. Naja, jetzt 
bin ich schon am überlegen, ob ich mit ein anderes Oszi zulegen soll. Da 
habe ich aber die Qual der Wahl. Hier im Forum gibt es ja genügend 
Beiträge zu diesem Thema. Ich weiß nicht so genau auf was ich da achten 
muss. Daher werd ich mich erst mal etwas einlesen in diese Thema :o)

Grüße,
Marcel

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.