Wie kann ich SPI mit Atmel Studio und C-Code für ARM-Prozessoren einrichten?

Ich versuche, den SAM3x8E-Chip auf dem Arduino Due über Atmel Studio zu programmieren. Ich möchte mit dem SAM3-Chip einen digitalen Widerstand über die SPI-Schnittstelle steuern können. Ich verwende Atmel Studio 6.2. Ich habe KEIN PROBLEM, Dinge auf der Arduino IDE zum Laufen zu bringen, aber ich möchte wirklich herausfinden, wie man dies auf die "harte Weise" in Atmel programmiert. Ich kann den Chip erfolgreich in Atmel Studio programmieren, indem ich eine Batch-Datei verwende, die bosssa.exe lädt.

Hier ist mein ARBEITENDER Arduino IDE-Code:

Code:

// inslude the SPI library:
#include <SPI.h>


// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 13;

void setup() {
  // initialize SPI:
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
 // SPI.setClockDivider(slaveSelectPin, 8);
  SPI.setBitOrder(LSBFIRST);
  pinMode (slaveSelectPin, OUTPUT);
}

void loop() {

  // Raise the volume from off to loud

  // Increase brightness of LED
  for (int i = 63; i>=0; i--) {
    digitalPotWrite(i, i);

    if(i>20)
    delay(10);
    else
    delay(100);
  }

      digitalPotWrite(0, 0);
       // delay(500);


  // Decrease brightness of LED
  for (int i = 0; i <= 63; i++) {
    digitalPotWrite(i, i);     

    if(i>20)
    delay(10);
    else
    delay(100);
  }
}

void digitalPotWrite(int left, int right) {
  // take the SS pin low to select the chip:
  digitalWrite(slaveSelectPin, HIGH);
  //  send in the address and value via SPI:
  SPI.transfer(left);
  SPI.transfer(right);
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin, LOW);
}

Nun (leider) ist dies mein Atmel-Code:

Code:

#include <asf.h>
#include "spi_master.h"


int main (void)
{
   /* Initialize the SAM system. */
   sysclk_init();
   board_init();

}

Wie Sie sehen können, habe ich nicht die geringste Ahnung, wie ich die SPI-Schnittstelle in Atmel Studio einrichten soll. Ich habe mir Beispielcode wie den eingebauten "SPI_EXAMPLE1" angesehen, aber ich verstehe ihn NICHT. Kann mir jemand helfen zu verstehen, wie Sie den SPI initialisieren? Woher weiß ich, welche Pins im Initialisierungscode verwendet werden sollen?

Sie sagen also, Sie haben überhaupt keinen Code für SPI in Atmel Studio erstellt. Haben Sie die SPI-Treiber mit Atmel Software Framework (ASF) eingebunden? Das kann sehr helfen. Es gibt online eine Dokumentation zur Verwendung des ASF-SPI-Treibercodes
Schnellstart zur Verwendung der ASF-Treiber für SPI: asf.atmel.com/docs/latest/sam.drivers.spi.example.arduino_due_x/…
Dokumentation für das Atmel Studio-Beispielprojekt, das Sie aus dem ASF-Beispielmenü anfordern / abrufen müssen, für den Arduino-Stil SAM3XE8 asf.atmel.com/docs/latest/sam.drivers.spi.example.arduino_due_x/…
Ich muss Ihnen jedoch zustimmen, es gibt schreckliche Anweisungen/Tutorials/Beispielcode und viel zu viel Fett, um es durchzuschneiden, damit etwas Einfaches funktioniert.

Antworten (2)

Sie haben hier zwei Möglichkeiten. Sie können die Konfigurationsregister direkt für das SPI-Peripheriegerät manuell festlegen oder das „Atmel Software Framework“ verwenden, das viele Details in einer übergeordneten API abstrahiert. In beiden Fällen müssen Sie sich um viele Dinge kümmern, die die Arduino-Umgebung für Sie erledigt.

Sie müssen die Uhr des Prozessors einrichten, was bedeutet, dass Sie eine Quelle auswählen (normalerweise haben Sie die Wahl zwischen einem internen Hochgeschwindigkeits-, einem internen Niedriggeschwindigkeits-, einem externen Hochfrequenz-Quarz, einem externen Niederfrequenz-Quarz oder einem externen Takt) und einer Kombination von Multiplikatoren /Teiler, die Ihre gewünschte Kerntaktfrequenz ableiten. Dann müssen Sie sicherstellen, dass das SPI-Peripheriegerät und die GPIO-Module ein Taktsignal empfangen (standardmäßig werden Taktsignale nicht an Peripheriegeräte geleitet, um Strom zu sparen) und dass das Taktsignal auf eine angemessene Geschwindigkeit heruntergeteilt wird (das MCU-Datenblatt wird Geben Sie das Min/Max-Timing sowie das Datenblatt Ihres externen ICs an, und Sie müssen sicherstellen, dass Sie die Anforderungen beider erfüllen).

Sie müssen die GPIO-Pins richtig konfigurieren, damit das SPI-Peripheriegerät sie steuern kann. Viele MCUs dieser Klasse verfügen über mehrere SPI-Einheiten, und das Datenblatt gibt an, welche Pins von welcher Einheit verwendet werden können. Die meisten Pins haben viele Peripheriegeräte, die ausgewählt werden können, also müssen Sie den Pin-Multiplexer einstellen, um die richtige SPI-Einheit auszuwählen. Sie müssen auch die Stiftrichtung und Pullups/Pulldowns nach Bedarf einstellen.

Schließlich müssen Sie das SPI-Peripheriegerät selbst konfigurieren. Dazu gehören die Einstellung der Taktgeschwindigkeit, die zu verwendenden Taktflanken, Master/Slave, Pin-Routing und viele andere Optionen, die im Datenblatt aufgeführt werden.

Wenn Sie gerade erst anfangen, dann ist ASF der richtige Weg. Es gibt Beispiele in der ASF-Dokumentation, die in früheren Kommentaren verlinkt sind, die Ihnen helfen sollten, und wenn Sie sie genau untersuchen, sollten Sie sehen, dass die Beispielanwendungen all die Dinge tun, die ich oben skizziert habe. Die ASF-Dokumentation erklärt jedoch außerordentlich schlecht, was vor sich geht und warum. Sie müssen also die Abschnitte des MCU-Datenblatts zu Takt, Energieverwaltung, GPIO und SPI sorgfältig studieren, um wirklich herauszufinden, was Sie tun . Leider erklärt das Datenblatt auch nur unzureichend, wie Peripheriegeräte verwendet werden sollen, sodass einiges zwischen den Zeilen gelesen werden muss. Als allgemeine Regel gilt, dass Hersteller-APIs und -Dokumentation für ARM-MCUs (nicht nur Atmels SAMs) nicht sehr gut sind. daher ist viel Lesen und Experimentieren erforderlich. Verwenden Sie die Funktion Rechtsklick -> "Zur Implementierung gehen" von Atmel Studio großzügig, um mehr darüber zu erfahren, was ASF unter der Haube tut. Ein Rückbezug auf die Datenblattbeschreibungen der Funktionen der verschiedenen Hardwareregister wird hilfreich sein.

Das alles ist also eine sehr allgemeine Antwort - Ihre spezifische Lösung hängt von der jeweiligen Hardwarekonfiguration ab, die Sie haben, also müssen Sie sich die Arduino Due-Schaltpläne ansehen, um herauszufinden, welche Pins Sie für SPI und verwenden müssen welche Uhreinstellungen angemessen sind. Die MCU wird standardmäßig von einem internen Oszillator gestartet, daher würde ich vorschlagen, dass Sie damit beginnen, nur den GPIO zum Laufen zu bringen – blinken Sie einfach eine LED, um sicherzustellen, dass Sie den GPIO im Griff haben, und beginnen Sie dann mit der Arbeit mit dem SPI-Modul .

Denken Sie vor allem daran, dass das Datenblatt Ihr Freund ist!

Danke! Ich werde die Dinge vereinfachen, indem ich mich auf ein GPIO-LED-Blinken konzentriere, wie Sie erwähnt haben. Ich habe nicht die Absicht, Atmel zu verprügeln, aber ich muss zustimmen, ihre Dokumentation enthält so viele Zeilen unsichtbarer Tinte .... =( Ich wünschte, sie würden diese Lücken etwas besser ausfüllen, wenn Sie verstehen, was ich meine. Es ist schwierig für einen absoluten anfänger danke für die hilfe!!
Wie bereits erwähnt, ist die ASF-Dokumentation ein komplettes Durcheinander. Ich habe zuvor SPI-Treiber für den AVR geschrieben und wechsle zum ARM und dachte, ich würde durch die Übernahme des ASF ein wenig Zeit sparen. Großer Fehler! Es ist so schwierig herauszufinden, was angesteuert wird, was Sie zur Konfiguration der Treiber bereitstellen müssen und was sie tatsächlich tun, dass es tatsächlich schneller geht, nur das Datenblatt zu lesen und Ihre eigenen Treiber zu schreiben (insbesondere wenn Sie nicht alle benötigen Konfigurationskomplexität und kann die Einstellungen, die Sie benötigen, einfach festverdrahten).

Obwohl erfahrene Entwickler sagen, dass Anfänger mit ASF gehen sollten (was tatsächlich stimmt), bedeutet das nicht, dass Sie mit weniger Aufwand dasselbe erreichen können. Sie brauchen nur eine andere Art von Anstrengung. (siehe: http://sam4dev.blogspot.co.at/2015/10/should-i-use-asf.html )

Wie auch immer, um die Frage zu beantworten: Ich habe SPI mit ASF im Master-Modus implementiert, SPI-Modus 0 auf SAM4S16C. Schauen Sie sich diesen Beitrag für Details an: http://sam4dev.blogspot.co.at/2015/10/spi-with-asf.html Ich stelle hier die wesentlichen Teile zur Verfügung.

Fügen Sie Ihrem Projekt mit ASF Wizard die folgenden Dienste/Treiber hinzu:

  • GPIO
  • IOPORT
  • SPI
  • Interrupt-Management
  • Steuerung der Systemuhr

Initialisieren Sie in Ihrer init.c-Datei die Treiber und Dienste.

#include <asf.h>
#include <board.h>
#include <conf_board.h>

void board_init(void)
{

 WDT->WDT_MR = WDT_MR_WDDIS; //switch off watchdog

 sysclk_init();
 ioport_init();
 irq_initialize_vectors();
 cpu_irq_enable();

 //Set Led Pin directions
 ioport_set_pin_dir(LED0_PIN,IOPORT_DIR_OUTPUT);
 ioport_set_pin_dir(LED1_PIN,IOPORT_DIR_OUTPUT);
}

SPI-Init: Diese Init-Methode richtet SPI im Master-Modus ein, der SPI-Modus ist der SPI-Modus 0, die Taktrate liegt bei etwa 1 MHz.

#define SPI_ID            ID_SPI
#define SPI_MASTER_BASE     SPI
#define SPI_MISO_GPIO  (PIO_PA12_IDX)
#define SPI_MISO_FLAGS (PIO_PERIPH_A | PIO_DEFAULT)
#define SPI_MOSI_GPIO  (PIO_PA13_IDX)
#define SPI_MOSI_FLAGS (PIO_PERIPH_A | PIO_DEFAULT)
#define SPI_SPCK_GPIO  (PIO_PA14_IDX)
#define SPI_SPCK_FLAGS (PIO_PERIPH_A | PIO_DEFAULT)
#define SPI_NPCS0_GPIO            (PIO_PA11_IDX)
#define SPI_NPCS1_GPIO            (PIO_PA31_IDX)
#define SPI_NPCS1_FLAGS           (PIO_PERIPH_A | PIO_DEFAULT)
#define SPI_CHIP_SEL 1    //Use SPI Chip Select 1 (SPI_NPCS1_GPIO) for CS
#define SPI_CHIP_PCS spi_get_pcs(SPI_CHIP_SEL)

/* Clock polarity. */
#define SPI_CLK_POLARITY 0

/* Clock phase. */
#define SPI_CLK_PHASE 0

/* Delay before SPCK. */
//#define SPI_DLYBS 0x40
#define SPI_DLYBS 0xFF

/* Delay between consecutive transfers. */
#define SPI_DLYBCT 0x10
/* SPI clock setting (Hz). */
static uint32_t gs_ul_spi_clock = 1000000;

//Paramteres:
//  data: data to be sent
//  last_byte: either 0 or 1. 
//   0-There are following bytes to be sent. The following bytes and the current byte composes one data-unit, CS should be kept low after sending out the current byte
//   1-Last byte of a data unit. CS will be set to HIGH when the current byte has been sent out.
void spi_tx(uint8_t data,uint8_t last_byte)
{
 spi_write(SPI,data,SPI_CHIP_SEL,last_byte);
 while ((spi_read_status(SPI) & SPI_SR_RDRF) == 0);/* Wait transfer done. */
}

uint8_t spi_rx(void)
{
 uint8_t tmp;
 spi_read (SPI,&tmp,SPI_CHIP_SEL);
 return tmp;
}

void spi_init(void)
{
        //Assign I/O lines to peripheral
 gpio_configure_pin(SPI_MISO_GPIO, SPI_MISO_FLAGS);
 gpio_configure_pin(SPI_MOSI_GPIO, SPI_MOSI_FLAGS);
 gpio_configure_pin(SPI_SPCK_GPIO, SPI_SPCK_FLAGS);
 gpio_configure_pin(SPI_NPCS1_GPIO, SPI_NPCS1_FLAGS);

 spi_enable_clock(SPI_MASTER_BASE);
 spi_disable(SPI_MASTER_BASE);
 spi_reset(SPI_MASTER_BASE);
 spi_set_lastxfer(SPI_MASTER_BASE);
 spi_set_master_mode(SPI_MASTER_BASE);
 spi_disable_mode_fault_detect(SPI_MASTER_BASE);
 spi_set_peripheral_chip_select_value(SPI_MASTER_BASE, SPI_CHIP_PCS);
 spi_configure_cs_behavior(SPI, 1, SPI_CS_RISE_NO_TX);
 spi_set_clock_polarity(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_CLK_POLARITY);
 spi_set_clock_phase(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_CLK_PHASE);
 spi_set_bits_per_transfer(SPI_MASTER_BASE, SPI_CHIP_SEL,
 SPI_CSR_BITS_8_BIT);
 spi_set_baudrate_div(SPI_MASTER_BASE, SPI_CHIP_SEL,(sysclk_get_cpu_hz() / gs_ul_spi_clock));
 spi_set_transfer_delay(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_DLYBS,SPI_DLYBCT);
 spi_enable(SPI_MASTER_BASE);
}