Forum: Mikrocontroller und Digitale Elektronik Globales Array über SPI ausgeben


von Johann (Gast)


Lesenswert?

Hi @ all

Ich habe ein globales unsigned char array mit 512 Elemente. Dieses 
möchte ich über die SPI-Schnittstelle ausgeben. Mein Code ist aber um 
Faktor 2 zu langsam. Ich benutze einen ATMEGA 2561 µC von Atmel. Laut 
meinen Berechnungen muss es locker möglich sein dies um Faktor 2 zu 
beschleunigen, jeoch ist mein C-Code wohl zu schlecht. Vielleicht kann 
mir ja jemand weiterhelfen.

Ich löse alle 7,8µs einen Timerinterrupt aus. (dies funktioniert auch 
bereits) In der Timerinterruptserviceroutine setze ich mir dann das Flag 
modus auf 1 und beende die Serviceroutine. Im Hauptprogramm frage ich 
dann das Flag immer ab. Ist dieses 1 so gebe ich 4 Elemente aus dem 
globalen Array über die SPI-Schnittstelle aus und setze anschließend das 
Modus-Flag auf 0 zurück.

// hier st mein globales Array und meine anderen globalen Variablen
volatile unsigned char spiegelpositionen[512];
volatile unsigned char modus;
volatile unsigned int aktuelle_scanspiegelposition;


// jetzt zum Hauptprogramm

while (1)
   {

      if(modus == 1)
      {
         // CS für die SPI Übertragung auf 0 setzen
         CS_DAC_SIGNAL = 0;
         SPDR = spiegelpositionen[aktuelle_scanspiegelposition];
         aktuelle_scanspiegelposition = aktuelle_scanspiegelposition + 
1;
         while(!(SPSR & 0x80));
         SPDR = spiegelpositionen[aktuelle_scanspiegelposition];
         aktuelle_scanspiegelposition = aktuelle_scanspiegelposition + 
1;
         while(!(SPSR & 0x80));
         SPDR = spiegelpositionen[aktuelle_scanspiegelposition];
         aktuelle_scanspiegelposition = aktuelle_scanspiegelposition + 
1;
         while(!(SPSR & 0x80));
         SPDR = spiegelpositionen[aktuelle_scanspiegelposition];
         aktuelle_scanspiegelposition = aktuelle_scanspiegelposition + 
1;
         while(!(SPSR & 0x80));
         CS_DAC_SIGNAL = 1;

         if(aktuelle_scanspiegelposition == 512)
         {
            aktuelle_scanspiegelposition = 0;
         }

         modus = 0;

         TestPin0 = 0;
      }
      else
      {
         //Leerlaufmodus
      }


Im Hauptprogramm gebe ich 4 Arrayelement aus und zähle die Position 
hoch. Jedoch dauert es zu lange. Kann man dies besser lösen?

von manateemoo (Gast)


Lesenswert?

Wieso Timer Interrupt und nicht "SPI Ready" oder wie auch immer das beim 
ATMEGA heisst?

von Mi M. (mike123)


Lesenswert?

Hallo,

welche Taktfrequenz hat dein System?
Welche Optimierungsstufe hat dein System?


@16 MHz braucht dein System alleine für die Übertragung der 4Byte 2µs, 
aber das soll es net sein...

auf die schnelle diese Lösung!
1
         // CS für die SPI Übertragung auf 0 setzen
2
         CS_DAC_SIGNAL = 0;
3
4
         SPDR = spiegelpositionen[aktuelle_scanspiegelposition++];
5
         while(!(SPSR & 0x80));
6
         SPDR = spiegelpositionen[aktuelle_scanspiegelposition++];
7
         while(!(SPSR & 0x80));
8
         SPDR = spiegelpositionen[aktuelle_scanspiegelposition++];
9
         while(!(SPSR & 0x80));
10
         SPDR = spiegelpositionen[aktuelle_scanspiegelposition++];
11
         while(!(SPSR & 0x80));
12
         CS_DAC_SIGNAL = 1;
13
14
         if(aktuelle_scanspiegelposition == 512) 
15
         {
16
               aktuelle_scanspiegelposition = 0;
17
         }
18
19
bzw.: unsigned int *ptr;
20
21
ptr = spiegelpositionen[aktuelle_scanspiegelposition];
22
23
         SPDR = *ptr++;
24
         while(!(SPSR & 0x80));
25
         SPDR = *ptr++;
26
         while(!(SPSR & 0x80));
27
         SPDR = *ptr++;
28
         while(!(SPSR & 0x80));
29
         SPDR = *ptr++;
30
         while(!(SPSR & 0x80));

du musst dann natürlich noch die aktuelle "aktuelle_scanspiegelposition" 
behandeln...


sorry, hab grad keine zeit mehr, muss weg.
keine Richtigkeit für evtl. schreibfehler!!

ansonsten anylisiere den code im assembly-listing, bzw. schreib den code 
direkt in Assembler!!

Gruß,
Michel

von (prx) A. K. (prx)


Lesenswert?

Diese ganzen volatiles sind nur dort nötig, wo die ISR auch drauf 
zugreift. Sind ein ziemlicher Knüppel zwischen die Beine des Compilers.

von holger (Gast)


Lesenswert?

Nutze das SPI Modul einfach besser aus. Solange rausgetaktet wird
kann man schon mal Daten aus dem Speicher holen und Zähler
inkrementieren.

         // CS für die SPI Übertragung auf 0 setzen
         unsigned char c;
         CS_DAC_SIGNAL = 0;

         SPDR = spiegelpositionen[aktuelle_scanspiegelposition++];
         c=spiegelpositionen[aktuelle_scanspiegelposition++];
         while(!(SPSR & 0x80));
         SPDR = c;
         c=spiegelpositionen[aktuelle_scanspiegelposition++];
         while(!(SPSR & 0x80));
         SPDR = c;
         c=spiegelpositionen[aktuelle_scanspiegelposition++];
         while(!(SPSR & 0x80));
         SPDR = c;
         while(!(SPSR & 0x80));
         CS_DAC_SIGNAL = 1;

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.