Forum: Mikrocontroller und Digitale Elektronik Atmel SAM4S_EK2 Board und SPI mit SSD1351-LCD-Controller


von Martin Z. (mzeller)


Lesenswert?

Hallo,

zur Situation: ich bin zwar schon lange Softwareentwickler, beschäftige 
mich aber erst seit Kurzem mit Mikrocontroller-Programmierung. 
Entschuldigt daher, wenn ich nicht immer die korrekten Begriffe verwende 
(bitte korrigiert mich).

Ich arbeite gerade mit dem SAM4S_EK2-Evaluierungsboard und möchte eine 
SPI-Kommunikation mit einem SSD1351-LCD-Controller basteln. Es gibt von 
Atmel einiges an Material und Beispiele. Was ich aber nicht gefunden 
habe, wie ich die verwendeten Pins ändern kann. Am Board sind die Pins 
für die SPI-Kommunikation vorkonfiguriert:

http://asf.atmel.com/docs/latest/sam.drivers.spi.example.sam4s_ek2/html/index.html

Das Datenblatt stimmt damit überein:
http://www.atmel.com/Images/Atmel_11176_32-bit-Cortex-M4-Microcontroller-SAM4S-EK2_User-Guide.pdf


*** Frage 1: wie kann ich diese vorgegebenen Pins ändern?

*** Frage 2: aus dem Datenblatt des LCD-Controllers sehe ich, dass für 
das 4-wire-SPI-MCU-Interface folgende Pins nötig sind:

SDIN => MOSI
SCLK => SPCK
CS   => NPCS0
D/C  => ?
RES  => ?

Links seht ihr die Pin-Bezeichnungen aus dem LCD-Controller-Datenblatt, 
rechts davon, wie ich annehme, dass die Bezeichnungen aus dem 
Datenblatt/Beispiel von Atmel sind - stimmen diese und welche Zuordnung 
fehlen noch?


Danke
Martin

von Martin Z. (mzeller)


Lesenswert?

Hallo,

ich habe herausgefunden, dass ich auf meinem Board den SPI Master Driver 
verwenden kann.

Dazu gibt es auch ein Beispiel für xmega devices:
http://asf.atmel.com/docs/3.21.0/sam4s/html/spi_master_xmega.html

Dort sieht man, wie die Pins definiert werden:
1
void spi_init_pins(void)
2
{
3
    ioport_configure_port_pin(&PORTD, PIN1_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT);
4
    ioport_configure_port_pin(&PORTD, PIN4_bm, IOPORT_PULL_UP | IOPORT_DIR_INPUT);
5
    ioport_configure_port_pin(&PORTD, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT);
6
    ioport_configure_port_pin(&PORTD, PIN6_bm, IOPORT_DIR_INPUT);
7
    ioport_configure_port_pin(&PORTD, PIN7_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT);
8
}

Hat jemand vielleicht einen Tipp, wie ich das auf meinem Board machen 
könnte? Die Methode ioport_configure_port_pin gibt es in meiner ioport.h 
nicht.

Bin für jeden Hinweis dankbar.

LG
Martin

von D. F. (Firma: EDF) (derdan)


Lesenswert?

Mit welcher Entwicklungsumgebung arbeitest du denn?
Im Atmel Studio 7 sind unzählige Beispielprojekte.
Wenn man diese Anschaut, kommt man schon dahinter wie das alles 
zusammenhängt.

von D. F. (Firma: EDF) (derdan)


Angehängte Dateien:

Lesenswert?

Hier mal ein Beispiel aus dem Atmel Studio 8

von Martin Z. (mzeller)


Lesenswert?

Hallo,

danke für deine Hilfe! Ich arbeite mit Atmel Studio 7.
Dieses SPI-Beispiel (und auch andere) bin ich bereits durchgegangen und 
habe sie auch so einigermaßen verstanden.
In diesem SPI-Beispiel von Atmel werden die bereits definierten SPI-Pins 
verwendet. Was ich aber noch nicht gefunden habe ist, wie ich diese Pins 
ändere bzw. definiere. Ich könnte mir vorstellen, dass das so gehen 
könnte, wie ich in meinem zweiten Post geschrieben habe - aber ich bin 
mir nicht sicher.

Was vielleicht auch interessant ist zusätzlich zu dem Code von meinem 2. 
Post: mit diesem PORTD wird dann ein SPI-Device erstellt.
1
   struct spi_device spi_device_conf = {
2
       .id = IOPORT_CREATE_PIN(PORTD, 1)
3
   };

Was meinst du? Wenn ich diesen Weg weiterverfolge, müsste dieser Code 
genügen, um die SPI-Pins umzukonfigurieren? Und sollte dann diese 
Definition des SPI-Devices genügen, damit die SPI Master driver alle 
neuen Pins verwendet?

Danke!

von D. F. (Firma: EDF) (derdan)


Lesenswert?

Du kannst nicht jedem belibigen Pin jede Funktion zuordnen.
Ich fürchte du musst mal genauer in das Datenblatt schauen.

Die Belegung für dein EVK ist in der ASF in


src\ASF\common\boards\board.h
und
src\ASF\sam\boards\4s_ek2\sam4s_ek2.h

hintelegt.

entweder änderst du diese Dateien ab oder du stellst dein Project auf

BOARD == USER_BOARD

in den Tool setting um und definierst deine Portpins nach dem Muster aus 
den EVK2 Dateien

von Martin Z. (mzeller)


Lesenswert?

Das waren jetzt wichtige Hinweise. Ich habe da Konfigurationen, die SPI 
betreffen, in diversen Dateien gefunden - diese Settings stimmen auch 
mit den Angaben im Datenblatt überein:


1
/** SPI MISO pin definition. */
2
#define SPI_MISO_GPIO         (PIO_PA12_IDX)
3
#define SPI_MISO_FLAGS       (PIO_PERIPH_A | PIO_DEFAULT)
4
/** SPI MOSI pin definition. */
5
#define SPI_MOSI_GPIO         (PIO_PA13_IDX)
6
#define SPI_MOSI_FLAGS       (PIO_PERIPH_A | PIO_DEFAULT)
7
/** SPI SPCK pin definition. */
8
#define SPI_SPCK_GPIO         (PIO_PA14_IDX)
9
#define SPI_SPCK_FLAGS       (PIO_PERIPH_A | PIO_DEFAULT)
10
11
/** SPI chip select 0 pin definition. (Only one configuration is possible) */
12
#define SPI_NPCS0_GPIO         (PIO_PA11_IDX)
13
#define SPI_NPCS0_FLAGS           (PIO_PERIPH_A | PIO_DEFAULT)
14
15
16
  /* Configure SPI pins */
17
#ifdef CONF_BOARD_SPI
18
  gpio_configure_pin(SPI_MISO_GPIO, SPI_MISO_FLAGS);
19
  gpio_configure_pin(SPI_MOSI_GPIO, SPI_MOSI_FLAGS);
20
  gpio_configure_pin(SPI_SPCK_GPIO, SPI_SPCK_FLAGS);
21
22
  /**
23
   * For NPCS 1, 2, and 3, different PINs can be used to access the same NPCS line.
24
   * Depending on the application requirements, the default PIN may not be available.
25
   * Hence a different PIN should be selected using the CONF_BOARD_SPI_NPCS_GPIO and
26
   * CONF_BOARD_SPI_NPCS_FLAGS macros.
27
   */
28
29
#  ifdef CONF_BOARD_SPI_NPCS0
30
  gpio_configure_pin(SPI_NPCS0_GPIO, SPI_NPCS0_FLAGS);
31
#  endif
32
33
34
/* ========== Pio definition for SPI peripheral ========== */
35
#define PIO_PA12A_MISO     (1u << 12) /**< \brief Spi signal: MISO */
36
#define PIO_PA13A_MOSI     (1u << 13) /**< \brief Spi signal: MOSI */
37
#define PIO_PA11A_NPCS0    (1u << 11) /**< \brief Spi signal: NPCS0 */
38
#define PIO_PA9B_NPCS1     (1u << 9)  /**< \brief Spi signal: NPCS1 */
39
#define PIO_PA31A_NPCS1    (1u << 31) /**< \brief Spi signal: NPCS1 */
40
#define PIO_PB14A_NPCS1    (1u << 14) /**< \brief Spi signal: NPCS1 */
41
#define PIO_PC4B_NPCS1     (1u << 4)  /**< \brief Spi signal: NPCS1 */
42
#define PIO_PA10B_NPCS2    (1u << 10) /**< \brief Spi signal: NPCS2 */
43
#define PIO_PA30B_NPCS2    (1u << 30) /**< \brief Spi signal: NPCS2 */
44
#define PIO_PB2B_NPCS2     (1u << 2)  /**< \brief Spi signal: NPCS2 */
45
#define PIO_PA3B_NPCS3     (1u << 3)  /**< \brief Spi signal: NPCS3 */
46
#define PIO_PA5B_NPCS3     (1u << 5)  /**< \brief Spi signal: NPCS3 */
47
#define PIO_PA22B_NPCS3    (1u << 22) /**< \brief Spi signal: NPCS3 */
48
#define PIO_PA14A_SPCK     (1u << 14) /**< \brief Spi signal: SPCK */

Aber das Seltsame ist, dass keine dieser Definitionen sonstwo im Code 
vorkommen - also ich finde keinen Code, der sagt, dass z.B. PA11 eben 
als NPCS0 genommen werden soll - nur in dieser Zeile (ist auch oben 
drin):
1
gpio_configure_pin(SPI_NPCS0_GPIO, SPI_NPCS0_FLAGS);

==> das würde bedeuten, dass genau mit diesen Methoden die SPI-Pins 
definiert werden. Sehe ich das richtig?

Aber dann frage ich mich, wozu gibt es diese Zeile:
1
#define PIO_PA11A_NPCS0    (1u << 11) /**< \brief Spi signal: NPCS0 */
=> PIO_PA11A_NPCS0 wird z.B. im Code sonst nirgends verwendet

: Bearbeitet durch User
von Martin Z. (mzeller)


Lesenswert?

Habe gerade etwas Passendes gefunden. Diesen Weg werde ich nun 
beschreiten ;-) und dann von meinem Erfolg bzw. Mißerfolg berichten:

http://electronics.stackexchange.com/a/194184

Danke.

von D. F. (Firma: EDF) (derdan)


Lesenswert?

1
#define SPI_NPCS0_GPIO         (PIO_PA11_IDX)

verwendet einen Index der alle verfügbaren Portpins durchnummeriert.
Und damit für Funktionen passt, welche einen solchen Index erwarten. 
Interne wird dann wieder auf den Port und eine Bitmaske umgerechnet um 
die entsprechenden SFR anzusteuern.

während durch
1
/* ========== Pio definition for SPI peripheral ========== */
2
#define PIO_PA12A_MISO     (1u << 12) /**< \brief Spi signal: MISO */
3
#define PIO_PA13A_MOSI     (1u << 13) /**< \brief Spi signal: MOSI */
4
#define PIO_PA11A_NPCS0    (1u << 11) /**< \brief Spi signal: NPCS0 */
5
#define PIO_PA9B_NPCS1     (1u << 9)  /**< \brief Spi signal: NPCS1 */
6
#define PIO_PA31A_NPCS1    (1u << 31) /**< \brief Spi signal: NPCS1 */
7
#define PIO_PB14A_NPCS1    (1u << 14) /**< \brief Spi signal: NPCS1 */

eine Bitmaske definiert wird. Dies kann ja auch mal nützlich sein.
Vor allem wenn man mal selber direkt auf die SFR zugreifen will.

Über nichtbenutzte Defines, die vom Hersteller geliefert werden, würde 
ich mir keine allzu große Gedanken machen.

: Bearbeitet durch User
von Martin Z. (mzeller)


Angehängte Dateien:

Lesenswert?

Ok, verstehe. Danke!

Und weil du gesagt hast, dass ich vielleicht gar nicht beliebige Pins 
verwenden kann. Ich habe im Datenblatt z.B. Angaben wie im angehängten 
Screenshot datenblatt-pins.png .

Diese Pins sind ja schon belegt mit diversen "Aufgaben". Nur die Spalte 
bei "Peripheral C" ist leer. Das heißt doch, dass pro Peripheral die 
"Aufgabe" eines Pins eine andere ist und dass diese Pins für Peripheral 
C unbelegt sind. Stimmt das so? Und - ich weiß nicht, ob ich mich 
technisch richtig ausdrücke - wenn ich diese Pins auf Peripheral C 
schalten würde, dann könnte ich sie nutzen wie ich möchte?

Stimmt das so oder bedeutet der Ausdruck Peripheral etwas ganz anderes? 
Ich habe schon danach gegoogelt, aber keine zufriedenstellenden 
Antworten bekommen.

von D. F. (Firma: EDF) (derdan)


Lesenswert?

Mann kann pro Pin desen Funktion auf A, B oder C festlegen.

Welche Funktion dann gemeint ist steht in der Tabelle. Wenn in einer 
Zelle  nichts steht, dann wird auch nichts funktionieren.
1
#define SPI_SPCK_FLAGS       (PIO_PERIPH_A | PIO_DEFAULT)

hier sieht man das die Funktion auf "A" (PIO_PERIPH_A) festeglegt wird.

Also kannst du z.b. für SPCK nur die Pins benutzen für die es in der 
Tabelle hinterlegt ist. Andere gehen nicht

von D. F. (Firma: EDF) (derdan)


Lesenswert?

Überleg ma wie groß eine Matrix sein müsste, die jeden Pin mit jedem 
beliebigen Peripherie Signal verbinden könnte.

Und diese Matrix würde man pro Pin benötigen.

von Martin Z. (mzeller)


Lesenswert?

Ok, verstehe ich das richtig:
1. wenn im Datenblatt eine Zelle der Pin-Belegung leer ist, dann kann 
ich dort auch nichts belegen, weil dieser Pin nicht mit dieser 
Peripherie verbunden ist?
2. Ich kann nur die Pins für SPI verwenden, die im Datenblatt dafür 
definiert sind?

=> wenn 2. mit Ja zu beantworten ist, dann frage ich mich, ob das nun 
durch die Konstruktion des Boards vorgegeben ist oder durch die 
Konstruktion des Microcontrollers. Gibt es also am SAM4S-Microcontroller 
Pins, die speziell für SPI konstruiert sind?

Danke für deine Geduld! Mir kommen erst langsam die ganzen 
Zusammenhänge...

von D. F. (Firma: EDF) (derdan)


Lesenswert?

Martin Z. schrieb:
> => wenn 2. mit Ja zu beantworten ist, dann frage ich mich, ob das nun
> durch die Konstruktion des Boards vorgegeben ist oder durch die
> Konstruktion des Microcontrollers. Gibt es also am SAM4S-Microcontroller

Das gibt der Mikrocontroller vor.

Nochmal zum Klarstellen:

Die GPIO können 3 unterschiedliche alternative Funktionen haben. und 
zwar bis zu 3. Welche das jeweils sind steht im Datenblatt des 
Bausteins.

die 3 sind auch nicht in Stein gemeiselt. Es gibt andere  Kontroller mit 
mehr oder weniger Alternativen Funktionen je Pin. Auch bei den STM ist 
das ähnlich gelöst.
Man ist in der Auswahl einfach eingeschränkt.

Wenn keine Altenative Funktion ausgewählt ist kann man den Pin als 
"einfacher" IO Pin benutzen

von Martin Z. (mzeller)


Lesenswert?

Danke für die vielen wichtigen Informationen. Ich denke, jetzt habe ich 
mal alles, um weiter zukommen.

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.