Forum: Mikrocontroller und Digitale Elektronik 8Mbit/s Manchester Code codieren und decodieren mit STM32F407


von Hans (Gast)


Lesenswert?

Hallo liebe Forengemeinde,

ich möchte serielle asynchrone Daten mit 4MBit/s senden (Daten+CRC). 
Diese müssten Manchester codiert werden und mit 8MBit/s den µC 
verlassen.

Desweiteren soll das ganze auch rückwärts geschehen (simplex). 
Asynchonen Manchestercode empfangen, decodieren, CRC check durchführen 
und Daten verwenden.

Passt das ganze Vorhaben einigermaßen adäquat in einen STM32F407? 
(Nebenbei soll noch eine Ethernetschnittstelle betrieben werden) 
Ansonsten könnte ich mir auch vorstellen einen Zync zu verwenden, wenn 
es mit dem µC zu eng wird.

Habt ihr diesbezüglich Erfahrungen/Ratschläge?

Beste Grüße

Hans

von Stefan (Gast)


Lesenswert?

Wie oft willst Du die Daten senden? Bei durchgehend 8mbit/s ist der 
STM32F4 wohl etwas überfordert, falls nicht andauernd Daten 
gesendet/empfangen werden, sollte das so gehen:

Senden bekommst Du über DMA hin:
* DMA über Timer mit 16Mhz triggern
* und für jede Flanke (high->low und low->high) einen vorberechneten 
Bitwert
  aus einer Tabelle per DMA auf das GPIOx_BSRR ausgeben

Nachteil:
Du brauchst für jedes Bit 2 * 32Bit als AusgabePuffer für das 
GPIOx_BSRR. Aber der STM32F4 hat ja etwas RAM.


Empfangen sollte über 2 Input-Capture Register, die per DMA eingelesen 
werden, realsisierbar sein.


Gruß, Stefan

von Stefan (Gast)


Lesenswert?

bdw:
Die Manchster-Ausgabe kannst Du auch mit einer SPI und einem externen 
XOR-Gatter erreichen.

Gruß, Stefan

von Falk B. (falk)


Lesenswert?

@ Stefan (Gast)

>Senden bekommst Du über DMA hin:
>* DMA über Timer mit 16Mhz triggern
>* und für jede Flanke (high->low und low->high) einen vorberechneten
>Bitwert
>  aus einer Tabelle per DMA auf das GPIOx_BSRR ausgeben

Geht einfacher, mit SPI. DMA ist natürlich zusätzlich nett.

>Empfangen sollte über 2 Input-Capture Register, die per DMA eingelesen
>werden, realsisierbar sein.

Ich würde lieber per Timer und DMA den Datenstrom einfach abtasten und 
dann per CPU dekodieren. Wenn man es clever macht, könnte man sogar 
einen dauerhaften Datenstrom empfangen und nebenbei noch andere Dinge 
erledigen. Die DMA arbeitet dabei auf einen FIFO.

von Falk B. (falk)


Lesenswert?

@ Stefan (Gast)

>Die Manchster-Ausgabe kannst Du auch mit einer SPI und einem externen
>XOR-Gatter erreichen.

Wozu das Gatter? Das kann die CPU locker vorher berechnen, im 
einfachsten und schnellsten Fall über eine Tabelle mit 256 16 Bit 
Einträgen.

von Stefan (Gast)


Lesenswert?

Ok, Du willst nur den SPI-Datenpin benutzen und zwar mit der doppelten 
Bitrate. Geht auch, clever.

Die eigendliche Herausforderung dürfte das Empfangen sein. Und da kommt 
es etwas darauf an, wieviel Daten der TS empfangen will.


Gruß, Stefan

von Hans (Gast)


Lesenswert?

Vielen Dank für die zahlreichen Antworten.

Das Senden über SPI finde ich eine sehr gute Idee, so werde ich das 
denke ich auch machen.

Das Empfangen wird da sicherlich nicht ganz so einfach. Die zu 
empfangenen Pakete sind 36Bit lang. Die Häufigkeit der Pakete werde ich 
in Erfahrung bringen. Das Abtasten des Datenstreams ist halt nicht so 
einfach. Der Takt ist bekannt, jedoch ist die Phasenlage unbekannt. 
Könnte ich nicht im einfachsten Fall mit der ersten steigenden oder 
fallenden Flanke einen Timer starten und dann den Datenstream auslesen? 
Anschließend dekodieren und CRC-Checken. Ist die interne CRC-Check 
Routine des STM 32F4 brauchbar?

Besten Dank...

von Hans (Gast)


Lesenswert?

PS: Die Datenlänge die ich per SPI senden kann ist frei definierbar? Zu 
senden sind ebenfalls 36Bit Pakete.

von Falk B. (falk)


Lesenswert?

@Hans (Gast)

>Das Empfangen wird da sicherlich nicht ganz so einfach.

Fast! Das machst du acuh mit SPI, nur halt mit höherer Datenrate. 
8Mbit/s sollte man mindestens mit 32 MHz abtasten, besser 64 MHz. Schau 
mal ob deine SPI so schnell arbeiten kann. Die DMA schafelt dazu die 
Daten in den RAM.

> Die zu
>empfangenen Pakete sind 36Bit lang.

Also praktisch nix.

> Die Häufigkeit der Pakete werde ich
>in Erfahrung bringen.

36 Bit @ 8MHz = 4,5us. Selbst wenn die alle 100us kommen, schafft das 
deine CPU locker. SOOO lange dauert die Dekodierung nicht.

> Das Abtasten des Datenstreams ist halt nicht so
>einfach.

Doch, siehe oben. Wenn es deine SPI nicht schnell genug abtasten kann, 
kann man auch einen Timer + DMA versuchen, der einfach einen 
Eingangsport in den Speicher schreibt.

> Der Takt ist bekannt, jedoch ist die Phasenlage unbekannt.
>Könnte ich nicht im einfachsten Fall mit der ersten steigenden oder
>fallenden Flanke einen Timer starten und dann den Datenstream auslesen?

Vergiss es, nicht bei 8 Mbit/s. Abtasten heißt das Zauberwort. So machen 
es alle. RS232, CAN, USB etc. Clock & Data Recovery.

>Anschließend dekodieren und CRC-Checken. Ist die interne CRC-Check
>Routine des STM 32F4 brauchbar?

Kann sein, bei 36 Bit lohnt das aber kaum.

von Falk B. (falk)


Lesenswert?

@ Hans (Gast)

>PS: Die Datenlänge die ich per SPI senden kann ist frei definierbar? Zu
>senden sind ebenfalls 36Bit Pakete.

Niemand hindert dich, 36 Bit als 5x8 Bit zu senden. Die letzten 4 Bit 
hängt man Dummydaten an. Beim Empfang ebenso.

von Hans (Gast)


Lesenswert?

Eine Sache hab ich bezüglich dem Einlesen über SPI noch nicht ganz 
nachvollzogen.

Ich habe nur eine Leitung an der ich die Manchestercodierten Daten 
empfange. Es ist keine SCLK oder SS Leitung vorhanden. Der Dateneingang 
wird auf MISO gelegt und dann abgetastet. Wann weiß der SPI Controller 
ab wann er abtasten soll. Erfolgt die Abtastung automatisch mit der 
ersten Flanke mit dem eingestellten Takt und für die Dauer der gewählten 
Datengröße?

Besten Dank...

von Falk B. (falk)


Lesenswert?

@ Hans (Gast)

>Ich habe nur eine Leitung an der ich die Manchestercodierten Daten
>empfange.

Reicht doch.

> Es ist keine SCLK oder SS Leitung vorhanden.

Brauchst du auch nicht.

> Der Dateneingang
>wird auf MISO gelegt und dann abgetastet. Wann weiß der SPI Controller
>ab wann er abtasten soll.

Er macht es einfach dauerhaft mit der eingestellten Bitrate. Dass dabei 
weder SCK noch CS eine Rolle spielt, ist dem SPI-Modul egal. Es tastet 
die Daten ab, schreibt sie ins Eingangsschieberegister und von dort 
landen sie per DMA im RAM. Einkanal Logicanalyzer für Arme ;-)

von Hans (Gast)


Angehängte Dateien:

Lesenswert?

Wenn die Daten mit 8Mbit/s empfangen werden und ich mit 32MHz Abtaste 
erhalte ich vier Abtastwerte je Bit. Wenn die Nachrichtenbreite von 
36Bit vierfach abgetastet wird, so erhalte ich 144Bit je SPI-Frame. Aber 
wie stelle ich sicher, dass sich genau dort dann auch eine Nachricht von 
Anfang bis Ende befindet, wenn ich dauerhaft einlese?

Ist es dann nicht einfacher ein 16Bit Schieberegister mit (SPI1) zu 
füllen und auf 0x000F abzufragen (Siehe Anhang), das würde den Beginn 
einer Nachricht kennzeichnen? Dann ein (SPI2) mit dem (SPI1) triggern um 
den Payload auszulesen. Hat das Aussicht auf Erfolg oder übersehe ich 
etwas? SPI3 würde ich dann zum senden benutzen.

von Falk B. (falk)


Lesenswert?

@Hans (Gast)

>wie stelle ich sicher, dass sich genau dort dann auch eine Nachricht von
>Anfang bis Ende befindet, wenn ich dauerhaft einlese?

Gar nicht. Du musst mehr Daten lesen und dann intelligent den Anfang 
erkennen.

>Ist es dann nicht einfacher ein 16Bit Schieberegister mit (SPI1) zu
>füllen und auf 0x000F abzufragen (Siehe Anhang),

Nein, das geht nicht. Denn dein SPI läuft nicht synchron zu deiner 
Datenquelle.

> das würde den Beginn
>einer Nachricht kennzeichnen? Dann ein (SPI2) mit dem (SPI1) triggern um
>den Payload auszulesen. Hat das Aussicht auf Erfolg oder übersehe ich
>etwas? SPI3 würde ich dann zum senden benutzen.

Ohjemine. Jetzt ist mir klar, wozu man 4 SPI Module in einem ARM braucht 
8-0
SO NICHT! Es reicht EIN SPI-Modul.

Woran kannst du erkennen, ob ein Datenpaket geschickt wird? Passiert das 
"zufällig" oder weiß man ungefähr, wann es gesendet wird? Denn in den 
Pausen musst du auch Daten abtasdten und erkennen, ob nichts ankommt 
oder eine echte Nachricht. Wenn auf dem Kanal zwischen den Nachrichten 
dauerhaft LOW oder HIGH gesendet wird, kann man das in den abgetasteten 
Daten als 0x00 oder 0xFF erkennen. Da es aber Manchesterkodiert ist, 
könnte es auch sein, dass dauerhaft 0x55 oder 0xAA empfangen wird. Aber 
auch das ist leicht erkennbar.

von Hans (Gast)


Lesenswert?

>>Ist es dann nicht einfacher ein 16Bit Schieberegister mit (SPI1) zu
>>füllen und auf 0x000F abzufragen (Siehe Anhang),

>Nein, das geht nicht. Denn dein SPI läuft nicht synchron zu deiner
>Datenquelle.

>>das würde den Beginn
>>einer Nachricht kennzeichnen? Dann ein (SPI2) mit dem (SPI1) triggern um
>>den Payload auszulesen. Hat das Aussicht auf Erfolg oder übersehe ich
>>etwas? SPI3 würde ich dann zum senden benutzen.

>Ohjemine. Jetzt ist mir klar, wozu man 4 SPI Module in einem ARM braucht
>8-0
>SO NICHT! Es reicht EIN SPI-Modul.

Ich habe deinen Ansatz verstanden dauerhaft abzutasten und dann den 
Anfang einer Nachricht zu suchen und diese zu extrahieren.


Nochmal kurz zu meiner Idee:
Was spricht denn dagegen ein zweites SPI Modul zu verwenden? Das wäre 
doch eher zum Vorteil, da ich die CPU weniger belasten würde. Mir ist 
schon klar, dass die Daten asynchron sind, aber das macht doch keinen 
Unterschied. In dem Anhang: Frame.png ist der Beginn einer Nachricht mit 
einer einzigartigen Folge gekennzeichnet "0001". Diese Folge erfasse ich 
doch in jedem Fall, da vier Abtastpunkte je Bit vorhanden sind um "000F" 
zu erhalten. Auf diese Weise habe ich doch elegant den Beginn meiner 
Nutzlast gefunden, ohne die CPU zu beanspruchen.

Beste Grüße

von Falk B. (falk)


Lesenswert?

@ Hans (Gast)

>Was spricht denn dagegen ein zweites SPI Modul zu verwenden?

Es bringt keinerlei Vorteil.

> Das wäre
>doch eher zum Vorteil, da ich die CPU weniger belasten würde.

Nein.

>Mir ist
>schon klar, dass die Daten asynchron sind,

Wirklich?

>aber das macht doch keinen
>Unterschied. In dem Anhang: Frame.png ist der Beginn einer Nachricht mit
>einer einzigartigen Folge gekennzeichnet "0001". Diese Folge erfasse ich
>doch in jedem Fall, da vier Abtastpunkte je Bit vorhanden sind um "000F"
>zu erhalten.

Aber die Grenzen des 1. Bytes sind NICHT synchron zu deiner Abtastung. 
Du kannst als erstes 16 Bit Wort genausogut

0x00FA empfangen, weil das erste Nibble durch die beliebige Phasenlage 
ins vorherige 16 Bit Wort gerutscht ist. Genauso wie

0x003C

Hier ist es eine Verschiebung um 2 Bit.

> Auf diese Weise habe ich doch elegant den Beginn meiner
>Nutzlast gefunden, ohne die CPU zu beanspruchen.

Nö. Dazu musste eine Hardwarelogik exisiteren, welche immer nach 0x000F 
sucht und dann "Hallo" ruft. Die gibt es aber in den SPI-Modulen nicht.

von Hans (Gast)


Lesenswert?

Falk Brunner schrieb:
>>aber das macht doch keinen
>>Unterschied. In dem Anhang: Frame.png ist der Beginn einer Nachricht mit
>>einer einzigartigen Folge gekennzeichnet "0001". Diese Folge erfasse ich
>>doch in jedem Fall, da vier Abtastpunkte je Bit vorhanden sind um "000F"
>>zu erhalten.
>
> Aber die Grenzen des 1. Bytes sind NICHT synchron zu deiner Abtastung.
> Du kannst als erstes 16 Bit Wort genausogut
>
> 0x00FA empfangen, weil das erste Nibble durch die beliebige Phasenlage
> ins vorherige 16 Bit Wort gerutscht ist. Genauso wie
>
> 0x003C
>
> Hier ist es eine Verschiebung um 2 Bit.

Die Idee ist nicht immer ein Byte einzulesen, sondern jedes Bit einzeln 
und dann das Schieberegister zu beurteilen, oder funktioniert das bei 
SPI nur Byteweise? Dann wäre mein Ansatz natürlich nicht sinnvoll.

von Hans (Gast)


Lesenswert?

Dann vielleicht über ein normales Schieberegister/Timer die Startsequenz 
abtasten, dann SPI triggern für die Nutzdaten und anschließend nach der 
Verarbeitung das Schieberegister/Timer wieder starten.

von Falk B. (falk)


Lesenswert?

@ Hans (Gast)

>Die Idee ist nicht immer ein Byte einzulesen, sondern jedes Bit einzeln
>und dann das Schieberegister zu beurteilen,

Bei 8 Mbit/s? Jaja ;-)

>oder funktioniert das bei
>SPI nur Byteweise?

Das auch.

>Dann wäre mein Ansatz natürlich nicht sinnvoll.

Eben!

von Hans (Gast)


Lesenswert?

Wie wäre es den mit einem "CMOS 4094" den Start einer Nachricht 
abzutasten?

Beste Grüße

von Hans (Gast)


Lesenswert?

Ich greife mal deinen Vorschlag auf:

36Bit mit 4 Abtastwerten ergeben sich 144Bit je Nachricht.

Die 144Bit, die dann im Speicher stehen müssen nach dem Startmuster 
untersucht werden. Diese 144Bit müssen aus dem Speicher in einen 
weiteren Speicher umkopiert werden, bevor die neuen 144Bit da sind. Mit 
den vorhandenen 288Bit ließe sich dann eine Nachricht extrahieren.

von Falk B. (falk)


Lesenswert?

@Hans (Gast)

>Wie wäre es den mit einem "CMOS 4094" den Start einer Nachricht
>abzutasten?

Unsinn, ausserdem ist der viel zu langsam.

>36Bit mit 4 Abtastwerten ergeben sich 144Bit je Nachricht.

>Die 144Bit, die dann im Speicher stehen müssen nach dem Startmuster
>untersucht werden.

Ja.

>Diese 144Bit müssen aus dem Speicher in einen
>weiteren Speicher umkopiert werden, bevor die neuen 144Bit da sind.

Ja.

> Mit
>den vorhandenen 288Bit ließe sich dann eine Nachricht extrahieren.

???

Den Speicher macht man sinnvollerweise um einiges größer, wir reden hier 
nur übe ein paar Dutzend Bytes. Dabei nutztem man 2 DMA Kanäle 
abwechselnd, welche zyklisch ZWEI Speicher immer wieder voll schreiben. 
Während der eine Speicher geschrieben wird, kann man den anderen 
durchsuchen und ggf. dekodieren.

von Uwe Bonnes (Gast)


Lesenswert?

8 Mbit/s mit 4 Bit/Bit gesampelt gibt 4 MByte/s. Ich bezweifle, dass Du 
es schaffst, Dich mit einem F4 kontinuierlich durch den Datenwust zu 
wuehlen....

von Falk B. (falk)


Lesenswert?

@ Uwe Bonnes (Gast)

>8 Mbit/s mit 4 Bit/Bit gesampelt gibt 4 MByte/s. Ich bezweifle, dass Du
>es schaffst, Dich mit einem F4 kontinuierlich durch den Datenwust zu
>wuehlen....

Der Mensch wächst an seinen Aufgaben. Immerhin ist es ein 32 Bit 
Prozessor mit 168 MHz. Da geht schon was. Klar, ein kleiner CPLD, der 
als Dekoder + UART läuft macht das locker, da reichen 32 MHz. Ist aber 
zu einfach ;-)

von Hans (Gast)


Angehängte Dateien:

Lesenswert?

Ich versuche grade per SPI zu senden, jedoch läuft da was nicht ganz 
richtig. Irgendwie sehe ich nicht was falsch ist, siehe (Anhang). An PE7 
ist das CS korrekt zu sehen und an PA5 ein merkwürdiges SCK. PA7 zeigt 
jedoch keine Nachricht.
1
void init_SPI1(void){
2
  
3
  GPIO_InitTypeDef GPIO_InitStruct;
4
  SPI_InitTypeDef SPI_InitStruct;
5
  
6
  // enable clock for used IO pins
7
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
8
  
9
  /* configure pins used by SPI1
10
   * PA5 = SCK
11
   * PA6 = MISO
12
   * PA7 = MOSI
13
   */
14
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5;
15
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
16
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
17
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
18
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
19
  GPIO_Init(GPIOA, &GPIO_InitStruct);
20
  
21
  // connect SPI1 pins to SPI alternate function
22
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
23
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
24
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
25
  
26
  // enable clock for used IO pins
27
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
28
  
29
  /* Configure the chip select pin
30
     in this case we will use PE7 */
31
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
32
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
33
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
34
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
35
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
36
  GPIO_Init(GPIOE, &GPIO_InitStruct);
37
  
38
  GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 high
39
  
40
  // enable peripheral clock
41
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
42
  
43
  /* configure SPI1 in Mode 0 
44
   * CPOL = 0 --> clock is low when idle
45
   * CPHA = 0 --> data is sampled at the first edge
46
   */
47
  SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines
48
  SPI_InitStruct.SPI_Mode = SPI_Mode_Master;     // transmit in master mode, NSS pin has to be always high
49
  SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 8 bits wide
50
  SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;        // clock is low when idle
51
  SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;      // data sampled at first edge
52
  SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set; // set the NSS management to internal and pull internal NSS high
53
  SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // SPI frequency is APB2 frequency / 4
54
  SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first
55
  SPI_Init(SPI1, &SPI_InitStruct); 
56
  
57
  SPI_Cmd(SPI1, ENABLE); // enable SPI1
58
}
59
60
/* This funtion is used to transmit and receive data 
61
 * with SPI1
62
 *       data --> data to be transmitted
63
 *       returns received value
64
 */
65
uint8_t SPI1_send(uint8_t data){
66
67
  SPI1->DR = data; // write data to be transmitted to the SPI data register
68
  while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete
69
  while( !(SPI1->SR & SPI_I2S_FLAG_RXNE) ); // wait until receive complete
70
  while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore
71
  return SPI1->DR; // return received data from SPI data register
72
}
73
74
int main(void){
75
  
76
  uint8_t received_val = 0;
77
  
78
  init_SPI1();
79
  
80
  while(1){
81
    
82
    GPIOE->BSRRH |= GPIO_Pin_7; // set PE7 (CS) low
83
    SPI1_send(0xAA);  // transmit data
84
    received_val = SPI1_send(0x00); // transmit dummy byte and receive data
85
    GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 (CS) high
86
  }
87
}

von Falk B. (falk)


Lesenswert?

@ Hans (Gast)

>richtig. Irgendwie sehe ich nicht was falsch ist, siehe (Anhang). An PE7
>ist das CS korrekt zu sehen und an PA5 ein merkwürdiges SCK. PA7 zeigt
>jedoch keine Nachricht.

Deine Signale sehr ziemlich schlecht aus. Das kriegt man deutlich besser 
hin. Dazu muss man u.a. einen 10:1 Taskopf benutzen und die Masse kurz 
halten.

Auf deinem CS SIgnal gibt es ziemlich viel Übersprechen vom SCK, auch 
ein Indiz für eine schlechte Masseanbindung.

von Hans (Gast)


Lesenswert?

Ein remap der SCK MOSI UND MISO funktioniert irgendwie nicht. Woran kann 
das liegen? Ich messe den SLK trotz remap immer noch an PA5... Das darf 
doch nicht sein, oder?
1
void init_SPI1(void){
2
  
3
  GPIO_InitTypeDef GPIO_InitStruct;
4
  SPI_InitTypeDef SPI_InitStruct;
5
        
6
        // enable peripheral clock
7
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
8
  
9
  // enable clock for used IO pins
10
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
11
        
12
        /* GPIO Deinitialisation */
13
        GPIO_DeInit(GPIOA);
14
        GPIO_DeInit(GPIOA);
15
        GPIO_DeInit(GPIOA);
16
  
17
  /* configure pins used by SPI1
18
   * PA4 = SCK
19
   * PA5 = MISO
20
   * PA6 = MOSI
21
   */
22
        
23
        // connect SPI1 pins to SPI alternate function
24
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_SPI1);
25
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
26
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
27
        
28
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
29
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
30
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
31
        GPIO_InitStruct.GPIO_PuPd  = GPIO_PuPd_DOWN;
32
        
33
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
34
  GPIO_Init(GPIOA, &GPIO_InitStruct);
35
        
36
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
37
  GPIO_Init(GPIOA, &GPIO_InitStruct);
38
        
39
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
40
  GPIO_Init(GPIOA, &GPIO_InitStruct);
41
  
42
  // enable clock for used IO pins
43
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
44
  
45
  /* Configure the chip select pin
46
     in this case we will use PE7 */
47
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
48
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
49
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
50
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
51
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
52
  GPIO_Init(GPIOE, &GPIO_InitStruct);
53
  
54
  GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 high
55
  
56
  /* configure SPI1 in Mode 0 
57
   * CPOL = 0 --> clock is low when idle
58
   * CPHA = 0 --> data is sampled at the first edge
59
   */
60
        
61
        SPI_I2S_DeInit(SPI1);
62
  SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines
63
  SPI_InitStruct.SPI_Mode = SPI_Mode_Master;     // transmit in master mode, NSS pin has to be always high
64
  SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 8 bits wide
65
  SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;        // clock is low when idle
66
  SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;      // data sampled at first edge
67
  SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set; // set the NSS management to internal and pull internal NSS high
68
  SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; // SPI frequency is APB2 frequency / 4
69
  SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first
70
  SPI_Init(SPI1, &SPI_InitStruct); 
71
  
72
  SPI_Cmd(SPI1, ENABLE); // enable SPI1
73
}
74
75
/* This funtion is used to transmit and receive data 
76
 * with SPI1
77
 *       data --> data to be transmitted
78
 *       returns received value
79
 */
80
uint8_t SPI1_send(uint8_t data){
81
82
  SPI1->DR = data; // write data to be transmitted to the SPI data register
83
  while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete
84
  while( !(SPI1->SR & SPI_I2S_FLAG_RXNE) ); // wait until receive complete
85
  while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore
86
  return SPI1->DR; // return received data from SPI data register
87
}
88
89
int main(void){
90
  
91
  uint8_t received_val = 0;
92
  
93
  init_SPI1();
94
        int i =0;
95
  
96
  while(1){
97
    
98
    GPIOE->BSRRH |= GPIO_Pin_7; // set PE7 (CS) low
99
    SPI1_send(0xFA);  // transmit data
100
    received_val = SPI1_send(0x00); // transmit dummy byte and receive data
101
    GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 (CS) high
102
  }
103
}

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.