SPI
SPI Master
Funktion
Das SPI-Master-Modul bietet die Möglichkeit, mit bis zu 15 Slave-Einheiten zu kommunizieren. Die Parameter CPOL und CPHA können frei programmiert werden und es kann aus dem Takt am Eingang clk_spi per Vorteiler der Sendetakt eingestellt werden. Ist das SPI Enable-Bit gesetzt, wird durch das Schreiben des Senderegisters der Übertragungsvorgang ausgelöst. Nach dem Beenden der Übertragung kann das Modul ein Interruptsignal auslösen. Das Signal wird zurückgesetzt durch einen Zugriff auf eines der Datenregister. Das Bit Transmit-Empty im Statusregister wird auf 1 gesetzt, wenn das Datenwort im Senderegister gesendet wurde und wird zurückgesetzt durch einen Schreibzugriff auf das Senderegister. Wenn kein neues Wort in das Senderegister geschrieben wird, wartet das Modul auf Daten.Register
Offset | Register | Funktion | Zugriff |
0 | SPI_CTRL | Steuerregister | read/write |
1 | SPI_DATO | Sendedaten | read/write |
2 | SPI_DATI | empfangene Daten | read |
3 | SPI_STAT | Statusregister | read |
Das Steuerregister SPI_CTRL enthält alle zur Steuerung der Funktionen des SPI Masters nötigen Bits. Bei einem Reset werden alle Bits mit Null initialisiert bis auf den Vorteiler und die Bitanzahl. Der Vorteiler wird auf den Maximalwert 2⁷ gesetzt und die Bitanzahl auf 8. Auf das Register kann lesend und schreibend zugegriffen werden.
Das Datenregister SPI_DATO enthält die Sendedaten. Bei einem Reset werden alle Bits mit Null initialisiert. Auf das Register kann lesend und schreibend zugegriffen werden.
Das Datenregister SPI_DATI enthält die empfangenen Daten. Bei einem Reset werden alle Bits mit Null initialisiert. Auf das Register kann nur lesend zugegriffen werden.
Das Statusregister enthält alle Bereitschafts- und Besetzt-Signale. Auf das Register kann nur lesend zugegriffen werden.
SPI_CTRL | Maske Hex | Funktion | Reset |
Bit 0: | 0x00001 | SPI enable: 0 = disable, 1 = enable | 0 |
Bit 1: | 0x00002 | Int enable: 0 = disable, 1 = enable | 0 |
Bit 2: | 0x00004 | cpol: cpol stellt den Idle-Pegel des Taktsignals ein | 0 |
Bit 3: | 0x00008 | cpha: 0 = Flanke von activ zu idle, 1 = Flanke von idle zu activ | 0 |
Bit 4 bis 7: | 0x00010 - 0x000F0 | Slave Adresse: 1 bis 15 ; 0 = deselect all Slaves | 0 |
Bit 8 bis 12: | Bit Anzahl | 01000 | |
0x00100 | 00001: 1 Bit | ||
0x00200 | 00010: 2 Bit | ||
0x00300 | 00011: 3 Bit | ||
0x00400 | 00100: 4 Bit | ||
0x00500 | 00101: 5 Bit | ||
0x00600 | 00110: 6 Bit | ||
0x00700 | 00111: 7 Bit | ||
0x00800 | 01000: 8 Bit | ||
0x00900 | 01001: 9 Bit | ||
0x00A00 | 01010: 10 Bit | ||
0x00B00 | 01011: 11 Bit | ||
0x00C00 | 01100: 12 Bit | ||
0x00D00 | 01101: 13 Bit | ||
0x00E00 | 01110: 14 Bit | ||
0x00F00 | 01111: 15 Bit | ||
0x01000 | 10000: 16 Bit | ||
0x01100 | 10001: 17 Bit | ||
0x01200 | 10010: 18 Bit | ||
Bit 13 bis 15: | Vorteiler: | 111 | |
0x00000 | 000: 2⁰ | ||
0x02000 | 001: 2¹ | ||
0x04000 | 010: 2² | ||
0x06000 | 011: 2³ | ||
0x08000 | 100: 2⁴ | ||
0x0A000 | 101: 2⁵ | ||
0x0C000 | 110: 2⁶ | ||
0x0E000 | 111: 2⁷ | ||
Bit 16 | clk_mode | 0=Normal 1=sclk immer aktiv (ltc1407) | 0 |
SPI_STAT | Maske Hex | Funktion | |
Bit 0: | 0x00001 | transmit empty: 1 = Sendedatenpuffer leer | |
Bit 1: | 0x00002 | Interrupt Flag | |
Bit 2: | 0x00004 | Ist 1 wenn noch SPI_SS Signale eingeschaltet sind. Die SPI_SS Signale werden erst zurückgesetzt, wenn der letzte Datentransfer beendet ist. | |
Bit 3: | 0x00008 | Ist 0 wenn die SPI_SS Signale nicht aktuell sind und wird wieder 1 wenn die letzte Slave Adresse eingestellt ist. |
Die Frequenz des SCLK Signals kann aus der Frequenz des Eingangssignals clk_spi und dem Wert des Vorteilers berechnet Werden.
SCLK = CLK_SPI / (4 * Vorteiler) = 50 MHz / (4 * 2⁰) = 12,50000000 MHz
SCLK = CLK_SPI / (4 * Vorteiler) = 50 MHz / (4 * 2²) = 3,12500000 MHz
SCLK = CLK_SPI / (4 * Vorteiler) = 50 MHz / (4 * 2⁷) = 0,09765625 MHz
Konfiguration und Instanziierung
Da bei einem System Takt größer gleich 60 MHz mit dem maximalen SPI-Vorteiler von 4*(2⁷) keine Frequenz kleiner gleich 100 kHz eingestellt werden können, hat der Master einen extra Eingang clk_spi für einen Takt aus dem das Signal SCLK gebildet wird. An diesem Eingang kann der Ausgang eines TIMER-Moduls oder USERCLK-Moduls angeschlossen werden. Damit sind dann auch Frequenzen kleiner 100 kHz einstellbar. Die Interruptleitung des Moduls muss an den gewünschten Eingang des Interruptkontrollers angeschlossen werden, die Output-Pins für MOSI, Slave-Select und SCLK an den Ausgang des Top Level Moduls sowie der Pin für MISO an den Eingang. Die Ports des Top Level Moduls müssen dann noch den Pins des FPGA im jConfig zugeordnet werden.Beispielprogramme zur Arbeit mit SPI Slave Modulen:
Lesen des ID, schreiben mit *.mcs Datei und ... vom EEPROM m25p32 in C auf dem ml507 Board:In diesem Beispiel wird der SpartanMC SPI-Master mit 25 MHz SPI-SCLK betrieben. Meim Senden von *.mcs Dateien muss im Minicom das Tool zum senden im ASCII Format auf einen Verzögerung von 2 ms am Zeilenende und 0 ms pro Zeichen eingestellt werden. Bei der alten Einstellung mit 2 ms am Zeilenende und 1 ms pro Zeichen dauert die Übertragung etwa 3 Stunden. Mit 0 ms pro Zeichen sind es nur etwa 15 Minuten.
Beschreibung zum m25p32 m25p32.pdf
C-Quelle des Test main.c
C-Quelle des Include m25p32.c
H-Quelle des Include m25p32.h
Assemblerliste des Test main.lst
Protokoll zum Test m25p32_prot.txt
Protokoll zum Test prot_m25p32_ml507.txt
BIT Datei für das ml507 Board mit dem Programm spartanmc.bit
MSK Datei für das ml507 Board mit dem Programm spartanmc.msk
SpartanMC Konfigurationsdatei für jConfig spi_sample.jc3
Bildschirmfoto 01 vom Minicom beim Vergleich mit Fehler
Bildschirmfoto 02 vom Minicom beim Vergleich mit Fehler
Bildschirmfoto 03 vom Minicom beim Vergleich mit Fehler und Anzeige des betroffenen Speicher
Bildschirmfoto 04 vom Minicom am Ende eines Programmierzyklus mit einer *.mcs Datei.
Bildschirmfoto 05 vom Minicom am Ende eines Programmierzyklus mit einer *.mcs Datei mit dem Fehlerstatus.
Bildschirmfoto 06 vom Minicom am Ende eines Vergleichs mit einer *.mcs Datei, die vorher programmiert wurde.
Bildschirmfoto 07 vom Minicom am Ende eines Vergleichs und Start der Anzeige aller belegten Seiten.
Bildschirmfoto 08 vom Minicom Ende der Anzeige aller belegten Seiten.
Einstellen von 4 Spannungen am DAC ltc2624 in C auf dem 3e Starter Kit Board:
Beschreibung zum ltc2624 ltc2624.pdf
C-Quelle des Test spi_ltc2624.c
Assemblerliste des Test spi_ltc2624.lst
Protokoll zum Test spi_ltc2624.txt
VSIM Bitverlauf der Datenübertragung VSIM1.png
VSIM mit der Periodendauer des SCK VSIM2.png
BIT Datei für das 3estk Board mit dem Programm spartanmc.bit
MSK Datei für das 3estk Board mit dem Programm spartanmc.msk
SpartanMC Konfigurationsdatei für jConfig spi_m_ltc2624.jc3
Funktionstest für den SpartanMC SPI-Slave in C auf dem 3e Starter Kit Board:
Beschreibung zum SpartanMC SPI spi.pdf
C-Quelle des Test spi_slave.c
Assemblerliste des Test spi_slave.lst
Protokoll zum Test prot_all_tests_1041khz.pdf
Protokoll zum Test prot_all_tests_3125khz.txt
BIT Datei für das 3estk Board mit dem Programm spartanmc.bit
MSK Datei für das 3estk Board mit dem Programm spartanmc.msk
SpartanMC Konfigurationsdatei für jConfig spi_ms.jc3
Funktionstest für den SpartanMC SPI-Slave in C auf dem sp601 Board:
Beschreibung zum SpartanMC SPI spi.pdf
C-Quelle des Test spi_slave.c
Assemblerliste des Test main.lst
Protokoll zum Test prot_all_tests_1667khz.pdf
Protokoll zum Test prot_spi_1666_6667mhz.txt
Protokoll zum Test prot_spi_5000mhz.txt
Protokoll zum Test prot_spi_5250mhz.txt (Bei der Synthese wurde ein Timing Error angezeigt!)
BIT Datei für das 3estk Board mit dem Programm spartanmc.bit
MSK Datei für das 3estk Board mit dem Programm spartanmc.msk
SpartanMC Konfigurationsdatei für jConfig spi_master_slave.jc3
Funktionstest für das Display OLED25664 in C auf dem SP601 Board:
Beschreibung zum SpartanMC SPI spi.pdf
Beschreibung zum Display NHD-3.12-25664UMB3.pdf
Beschreibung zum Display Kontroller SSD1322.pdf
C-Quelle des Test main.c
C-Include oled_25664.c
H-Include oled_25664.h
H-Include ascii57.h
C-Include spi_local.c
H-Include spi_local.h
Foto vom Test IMG_1242.JPG
Foto vom Test IMG_1241.JPG
BIT Datei für das SP601 Board mit dem Programm spartanmc.bit
MSK Datei für das SP601 Board mit dem Programm spartanmc.msk
SpartanMC Konfigurationsdatei für jConfig sp601_spi_oled25664.jc3
C-Quellen der SPI-Include Funktionen:
Programm | Beschreibung | ||
---|---|---|---|
* | spi_readwrite.c | - | spi_master_readwrite - Senden von Daten an den Slave und warten bis der Master wieder bereit ist
und dann die Rx Daten zurückgeben spi_slave_readwrite - Senden von Daten an den Master und warten bis der Slave wieder bereit ist und dann die Rx Daten zurückgeben |
* | spi_write.c | - | spi_master_write - warten bis der Master wieder bereit ist und dann Daten senden spi_slave_write - warten bis dammy Byte empfangen wurde, Byte senden und warten bis der Slave wieder bereit ist |
* | spi_read.c | - | spi_master_read - dummy Byte 0x55 senden und warten bis der Master wieder bereit ist und dann Daten lesen spi_slave_read - warten bis ein Byte empfangen wurde und dann empfangenes Byte zur Kontrolle zurueck senden |
* | spi_enable.c | - | spi_master_enable - SpartanMC SPI-Master-Device einschalten spi_slave_enable - SpartanMC SPI-Slave-Device einschalten |
* | spi_disable.c | - | spi_master_disable - SpartanMC SPI-Master-Device ausschalten spi_slave_disable - SpartanMC SPI-Slave-Device ausschalten |
* | spi_enable_irq.c | - | spi_master_enable_irq - Interrupt eines SpartanMC Master SPI-Device freigeben spi_slave_enable_irq - Interrupt eines SpartanMC Slave SPI-Device freigeben |
* | spi_disable_irq.c | - | spi_master_disable_irq - Interrupt eines SpartanMC Master SPI-Device sperren spi_slave_disable_irq - Interrupt eines SpartanMC Slave SPI-Device sperren |
* | spi_set_cpol.c | - | spi_master_set_cpol - Polarität des SPI Takt vom Master setzen (0 = Ruhezustand des Takt / 1 = Ruhezustand des Takt) spi_slave_set_cpol - Polarität des SPI Takt vom Slave setzen (0 = Ruhezustand des Takt / 1 = Ruhezustand des Takt) |
* | spi_set_cpah.c | - | spi_master_set_cpah - Phasenlage des SPI Takt vom Master setzen
(0 = Datenübernahme mit der 1. Flanke / 1 = Datenübernahme mit der 2. Flanke) spi_slave_set_cpah - Phasenlage des SPI Takt vom Slave setzen (0 = Datenübernahme mit der 1. Flanke / 1 = Datenübernahme mit der 2. Flanke) |
* | spi_set_bitcnt.c | - | spi_master_set_bitcnt - Anzahl der Bits des Datenworts vom Master einstellen (1 bis 18).
Rückgabe -1, wenn < 1 oder > 18. spi_slave_set_bitcnt - Anzahl der Bits des Datenworts vom Slave einstellen (1 bis 18). Rückgabe -1, wenn < 1 oder > 18. |
* | spi_master_set_div.c | - | Vorteiler für den SPI Takt setzen (20 bis 27) |
* | spi_master_activate.c | - | Aktivieren eines Slave und warten bis das SS-Signal eingeschaltet ist (es können nacheinander mehrere Slave aktiviert werden).
Es wird eine 0 zurückgegeben, wenn die Funktion erfolgreich war. Ist der Master nicht freigegeben, oder die Nummer des Slave
ist kleiner 1 oder größer 15 wird eine 1 zurückgegeben |
* | spi_master_deactivate.c | - | alle Slave Module deaktivieren und warten bis die SS-Signale ausgeschaltet sind. |
1. #include <spi.h>
... muss in der C-Quelle geladen werden, wenn man die Funktionen verwenden will.#ifndef __SPI_H #define __SPI_H #ifdef __cplusplus extern "C" { #endif #include <peripherals/spi_master.h> #include <peripherals/spi_slave.h> #include <bitmagic.h> //master only functions int spi_master_activate(spi_master_regs_t *spi,unsigned int device); // return = 1 if spi not enable or device<1 or device>15 void spi_master_deactivate(spi_master_regs_t *spi); void spi_master_set_div(spi_master_regs_t *spi, unsigned int div); //master duplicate functions unsigned int spi_master_readwrite(spi_master_regs_t *spi, unsigned int data); unsigned int spi_master_read(spi_master_regs_t *spi); void spi_master_write(spi_master_regs_t *spi, unsigned int data); void spi_master_enable(spi_master_regs_t *spi); void spi_master_disable(spi_master_regs_t *spi); void spi_master_enable_irq(spi_master_regs_t *spi); void spi_master_disable_irq(spi_master_regs_t *spi); void spi_master_set_cpol(spi_master_regs_t *spi, unsigned int cpol); void spi_master_set_cpah(spi_master_regs_t *spi, unsigned int cpah); int spi_master_set_bitcnt(spi_master_regs_t *spi, unsigned int bitcnt); // return = bitcnt or -1 if error (bitcnt > 18 or bitcnt < 1) //slave duplicate functions unsigned int spi_slave_readwrite(spi_slave_regs_t *spi, unsigned int data); unsigned int spi_slave_read(spi_slave_regs_t *spi); void spi_slave_write(spi_slave_regs_t *spi, unsigned int data); void spi_slave_enable(spi_slave_regs_t *spi); void spi_slave_disable(spi_slave_regs_t *spi); void spi_slave_enable_irq(spi_slave_regs_t *spi); void spi_slave_disable_irq(spi_slave_regs_t *spi); void spi_slave_set_cpol(spi_slave_regs_t *spi, unsigned int cpol); void spi_slave_set_cpah(spi_slave_regs_t *spi, unsigned int cpah); int spi_slave_set_bitcnt(spi_slave_regs_t *spi, unsigned int bitcnt); // return = bitcnt or -1 if error (bitcnt > 18 or bitcnt < 1) #ifdef __cplusplus } #endif #endif
2. #include <periperals/spi_master.h>
... wird immer automatisch vom SpartanMC System geladen. Der Include muss nicht in der C-Quelle erfolgen.#ifndef __SPI_MASTER_H #define __SPI_MASTER_H #ifdef __cplusplus extern "C" { #endif #include <peripherals/spi_common.h> // CONTROL #define SPI_MASTER_CTRL_EN SPI_CTRL_EN #define SPI_MASTER_CTRL_INT_EN SPI_CTRL_INT_EN #define SPI_MASTER_CTRL_CPOL SPI_CTRL_CPOL #define SPI_MASTER_CTRL_CPHA SPI_CTRL_CPHA #define SPI_MASTER_CTRL_SLAVE 0x000F0 // 00 0000 0000 1111 0000 #define SPI_MASTER_CTRL_BITCNT SPI_CTRL_BITCNT #define SPI_MASTER_CTRL_DIV 0x0E000 // 00 1110 0000 0000 0000 #define SPI_MASTER_CTRL_CLK_MOD 0x10000 // 01 0000 0000 0000 0000 //STATUS COMPATIBILITY SECTION FOR OLD PROJECTS #define SPI_MASTER_STAT_TRANS_EMPTY SPI_STAT_TRANS_EMPTY #define SPI_MASTER_STAT_INT SPI_STAT_INT #define SPI_MASTER_STAT_SS_ON SPI_STAT_SS_ON #define SPI_MASTER_STAT_SS_SET SPI_STAT_SS_SET typedef struct { spi_t spi; } spi_master_regs_t; #ifdef __cplusplus } #endif #endif
2. #include <periperals/spi_common.h>
... wird immer automatisch vom SpartanMC System geladen. Der Include muss nicht in der C-Quelle erfolgen.#ifndef __SPI_COMMON_H #define __SPI_COMMON_H #ifdef __cplusplus extern "C" { #endif // CONTROL #define SPI_CTRL_EN 0x00001 // 00 0000 0000 0000 0001 #define SPI_CTRL_INT_EN 0x00002 // 00 0000 0000 0000 0010 #define SPI_CTRL_CPOL 0x00004 // 00 0000 0000 0000 0100 #define SPI_CTRL_CPHA 0x00008 // 00 0000 0000 0000 1000 #define SPI_CTRL_BITCNT 0x01F00 // 00 0001 1111 0000 0000 //STATUS #define SPI_STAT_TRANS_EMPTY 0x00001 // 00 0000 0000 0000 0001 #define SPI_STAT_INT 0x00002 // 00 0000 0000 0000 0010 #define SPI_STAT_SS_ON 0x00004 // 01 0000 0000 0000 0100 #define SPI_STAT_SS_SET 0x00008 // 10 0000 0000 0000 1000 typedef volatile struct { volatile unsigned int spi_control; volatile unsigned int spi_data_out; volatile unsigned int spi_data_in; volatile unsigned int spi_status; } spi_t; #ifdef __cplusplus } #endif #endif