91-SPI-DMA-Library (STM32F4)

Hier eine Library um die SPI-Schnittstelle im Master-Mode und per DMA-Betrieb nutzen zu könnnen.

ich habe wieder 3 identische Libs für SPI1, SPI2, SPI3 erstellt.

die SPI-Pins die benutzt werden sollen, müssen im C-File eingetragen werden
(im H-File kann der Clock-Vorteiler gewählt werden)

Das setzen der ChipSelect-Leitung muss von der Übergeordneten Funktion gemacht werden (event. muss das disable Signal in die ISR gepackt werden)

Beim initialisieren kann der Mode (Mode-0 bis Mode-3) und LSB oder MSB gewählt werden. Die Schnittstelle darf nur einmal initialisiert werden.

Zum senden und empfangen gibt es je ein Byte-Array dessen max. Größe im H-File eingestellt werden kann.

Vor dem senden müssen die Daten in das TX-Array kopiert werden. Beim senden muss die Anzahl der Daten zum senden mit übergeben werden. (1 bis Arraysize)

Das eigentliche senden/empfangen passiert dann per DMA und über eine Funktion kann geprüft werden ob das senden/empfangen fertig ist. Falls es fertig ist, wird die Anzahl der empfangenen Bytes zurückgegeben und die eigentlichen Daten stehen dann im RX-Array.

Falls die Senderoutine aufgerufen wird, aber das letzte senden noch gar nicht fertig ist, wird solange gewartet und erst im Anschluss daran gesendet.

im Beispiel wurde SPI2 benutzt mit dieser Pinbelegung :

1
2
3
SCK an PB13
MOSI an PB15
MISO an PB14

Voraussetzungen :

1
2
Benutzte Module der CooCox-IDE : GPIO, SPI, DMA, MISC
Benutzte Librarys : keine

Enumerationen (für SPI1) :

1
2
3
4
5
6
7
8
9
10
typedef enum {
  SPI_MODE_0_MSB = 0,  // CPOL=0, CPHA=0 (MSB-First)
  SPI_MODE_1_MSB,      // CPOL=0, CPHA=1 (MSB-First)
  SPI_MODE_2_MSB,      // CPOL=1, CPHA=0 (MSB-First)
  SPI_MODE_3_MSB,      // CPOL=1, CPHA=1 (MSB-First)
  SPI_MODE_0_LSB,      // CPOL=0, CPHA=0 (LSB-First)
  SPI_MODE_1_LSB,      // CPOL=0, CPHA=1 (LSB-First)
  SPI_MODE_2_LSB,      // CPOL=1, CPHA=0 (LSB-First)
  SPI_MODE_3_LSB       // CPOL=1, CPHA=1 (LSB-First) 
}SPI1_Mode_t;

Funktionen (für SPI1) :

1
2
3
ErrorStatus UB_SPI1_DMA_Init(SPI1_Mode_t mode);
ErrorStatus UB_SPI1_DMA_SendBuffer(uint32_t cnt);
uint32_t UB_SPI1_DMA_GetReceivedBytes(void);

Beispiel :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//--------------------------------------------------------------
// File     : main.c
// Datum    : 30.12.2014
// Version  : 1.0
// Autor    : UB
// EMail    : mc-4u(@)t-online.de
// Web      : www.mikrocontroller-4u.de
// CPU      : STM32F4
// IDE      : CooCox CoIDE 1.7.4
// GCC      : 4.7 2012q4
// Module   : CMSIS_BOOT, M4_CMSIS_CORE
// Funktion : Demo der SPI_DMA Library
// Hinweis  : Diese zwei Files muessen auf 8MHz stehen
//              "cmsis_boot/stm32f4xx.h"
//              "cmsis_boot/system_stm32f4xx.c"
//--------------------------------------------------------------
 
#include "main.h"
#include "stm32_ub_spi2_dma.h"
 
int main(void)
{
  SystemInit(); // Quarz Einstellungen aktivieren
 
  // SPI2 im Mode0 initialisieren
  UB_SPI2_DMA_Init(SPI_MODE_0_MSB);
 
  // TX-Puffer mit 3 Bytes Daten fuellen
  SPI2_DMA.tx_buffer[0]=0x55;
  SPI2_DMA.tx_buffer[1]=0xAA;
  SPI2_DMA.tx_buffer[2]=0x01;
 
  // 3Bytes per DMA senden
  UB_SPI2_DMA_SendBuffer(3);
 
  while(1)
  {
    if(UB_SPI2_DMA_GetReceivedBytes()>0) {
      // wenn senden fertig
      // hier die 3 Bytes vom RX-Buffer auswerten
    }
  }
}

Hier die Library zum Download :

ub_stm32f4_spi_dma_v100

Hier der komplette CooCox-Projektordner zum Download :

Demo_91_SPI_DMA


3 Antworten auf 91-SPI-DMA-Library (STM32F4)

  1. Lucas sagt:

    Hey Uwe!

    Wollte gerade mein EADOG-Display 1701 auf SPI-DMA umstellen, da ich für ein Programm eine Refreshzeit von 500ms des kompletten Displays brauche!

    Leider bin ich auf das Problem gestossen, dass die Funktion in der EADOG-Lib -> P_EADOG_SetCursor(…) den COMMAND/DATA-Pin umschaltet.

    Meine einziger “Lösungsansatz” ist, der aber nicht viel bringen wird, jeweils commands und data getrennt an den DMA zu übergeben….

    Hast du eine Idee, ob man das noch irgendwie anders machen kann. Eventuell hat der Display einen internen “Burst-mode” bei dem man keine Koordinaten angeben muss, sondern intern einfach pro empfangenen Byte automatisch die nächste Koordinate angesprungen wird? Oder kann man mit dem DMA vielleicht sogar einen normalen GPIOPin mit dem RICHTIGEN Timing zum SPI Transfer schalten(-> glaub ich nicht)?

    Würde mich freuen wenn du da helfen könntest!

    • Lucas sagt:

      Im Datenblatt vom Controller
      http://www.lcd-module.de/deu/pdf/grafik/dogs102-6.pdf
      hab ich gerade etwas gefunden, was sich sehr nach den vom mir betitelten “Burst-Mode” anhört.

      Seite 5:
      (25) Set Adv. Program Control 0

      Jetzt muss ich nur mal rausfinden wie ich die Lib dementsprechend umschreibe… Sollte aber nocht so heftig sein…

      • admin_ub sagt:

        ich hab für den ATMega eine Library für das EA-Dog Display geschrieben. Ein Byte setzt ja 8 Pixel vom LCD gleichzeitig
        (und das Display incrementiert die Adresse selbst)
        also kannst du nach jeder “Zeile” von 102 Pixel den Cursor
        um eine Page weiterschalten (das sind dann 8Pixel)
        somit brauchst du zum löschen vom kompletten LCD nur 8mal
        die Adresse neu setzen


Wie hat Dir dieser Artikel gefallen?

1 Stern2 Sterne3 Sterne4 Sterne5 Sterne (1 Bewertungen, Durchschnitt: 5,00 von 5)
Loading...

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.