Forum: Mikrocontroller und Digitale Elektronik SPI auf STM32F103 - kein Signal


von Switcher (Gast)


Lesenswert?

Ich versuche leider vergeblich, SPI1 auf einem STM32F103 zum laufen zu 
bringen. Aus Gründen, die ich nicht verstehe, habe ich aber kein Signal 
an SCK und MOSI. Nicht nur kommen keine seriellen Daten raus, auch das 
Level der SCK ist falsch. Erwarten würde ich bei CPOL=1 und CPHA=1 3.3V 
in Ruhe, messen tue ich aber 0V und mit dem Oszi sehe ich gar nichts.

Der Code ist wie folgt. Initialisierung:
1
  SPI1_CR2 = 0x00;
2
  RCC_APB2ENR |= RCC_APB2ENR_SPI1EN;
3
  SPI1_CR1 = (CPHA ? 0x01 : 0x00)
4
    | (CPOL ? 0x02: 0x00)
5
    | (BR << 3)
6
    | SPI_CR1_SSM
7
    | SPI_CR1_SPE
8
    | SPI_CR1_SSI
9
    | SPI_CR1_MSTR;

Später lese ich CR1=0x037f zurück, was meiner Meinung nach stimmt. Der 
Peripherietakt ist 36MHz.

Für die Schreiberei (in Endlosschleife) verwende ich:
1
  while ( ! (SPI1_SR & SPI_SR_TXE) );   
2
  SPI1_DR = data;  
3
  while ( ! (SPI1_SR & SPI_SR_TXE) );   
4
  while ( (SPI1_SR & SPI_SR_BSY) );

Wenn ich das Status-Register auslese, erhalte ich jeweils 0x43. Das 
Overrun-Flag ist gesetzt, was ok ist, da ich MISO nicht brauche. Aber 
vor allem habe ich MODF=0, d.h. der SPI hat sich also nicht abgestellt.

Und zurücklesen ergibt GPIOA_CRL = 0xb1b16666, was die Alternate 
Function für PA5 und PA7 auch richtig setzt (AF push-pull). Die Pins des 
SPI1 sind auch nicht Remapped.

Es sieht irgendwie so aus, wie wenn etwas notwendiges nicht 
"eingeschaltet" wäre. Auf der anderen Seite läuft schon was, denn sonst 
würde nach dem ersten Schreiben nicht das Overrun-Flag gesetzt.

von holger (Gast)


Lesenswert?

>Der Code ist wie folgt. Initialisierung:
>
>  SPI1_CR2 = 0x00;

Das hier drüber sollte man nicht tun BEVOR das da unten getan wurde.

>  RCC_APB2ENR |= RCC_APB2ENR_SPI1EN;

Beitrag #5554845 wurde von einem Moderator gelöscht.
von Marvin M. (Gast)


Lesenswert?

Moin,

AFIOEN (Alternate function I/O clock enable) in  APB2 peripheral clock 
enable register (RCC_APB2ENR) ist gesetzt?

von honk (Gast)


Lesenswert?

Wie wäre es mal mit einem kompletten lauffähigem Programm, am besten 
inklusive Linkerscript und was Du so dabei hast?
So kann das Raten ewig weitergehen, da wir nicht wissen, ob Du alle 
relevanten Informationen und Codezeilen geliefert hast.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Mir fehlt da die Pin Konfiguration. Da können noch alle möglichen 
Fallstricke sein.

von Dr. Sommer (Gast)


Lesenswert?

holger schrieb:
> Das hier drüber sollte man nicht tun BEVOR das da unten getan wurde.

u.U. kann es sogar nötig sein, nach Aktivieren des Takts und vor erster 
Nutzung der Peripherie eine DSB-Instruktion auszuführen.

von honk (Gast)


Lesenswert?

Dr. Sommer schrieb:
> holger schrieb:
>> Das hier drüber sollte man nicht tun BEVOR das da unten getan wurde.
>
> u.U. kann es sogar nötig sein, nach Aktivieren des Takts und vor erster
> Nutzung der Peripherie eine DSB-Instruktion auszuführen.


Also wenn Du schon so eine schwammige Aussage machst, die Unbedarfte 
mehr verwirrt als erleuchtet, dann solltest Du wenigstens irgendeine 
Quelle dafür angeben.
Z.B.:
https://www.st.com/content/ccc/resource/technical/document/errata_sheet/38/e6/37/64/08/38/45/67/DM00068628.pdf/files/DM00068628.pdf/jcr:content/translations/en.DM00068628.pdf
auf Seite 14 oder

https://www.st.com/content/ccc/resource/technical/document/errata_sheet/0a/98/58/84/86/b6/47/a2/DM00037591.pdf/files/DM00037591.pdf/jcr:content/translations/en.DM00037591.pdf

Seite 16.

von Dr. Sommer (Gast)


Lesenswert?

honk schrieb:
> Also wenn Du schon so eine schwammige Aussage machst, die Unbedarfte
> mehr verwirrt als erleuchtet, dann solltest Du wenigstens irgendeine
> Quelle dafür angeben.

Sorry, ich hatte das mal selbst rausgefunden und kannte die Quelle gar 
nicht. Durch Angabe der richtigen Suchworte kann der Fragende die Quelle 
auch selbst finden.

von Korinthen Sucher (Gast)


Lesenswert?

honk schrieb:
> dann solltest Du wenigstens irgendeine
> Quelle dafür angeben.
> Z.B.:
> 
https://www.st.com/content/ccc/resource/technical/document/errata_sheet/38/e6/37/64/08/38/45/67/DM00068628.pdf/files/DM00068628.pdf/jcr:content/translations/en.DM00068628.pdf

Diese Quelle bezieht sich auf F4xx COntroller, der
TO redet aber vom F103.

Gilt das Geschriebene auch für den F103?

von John Doe (Gast)


Lesenswert?

Korinthen Sucher schrieb:
> Diese Quelle bezieht sich auf F4xx COntroller, der
> TO redet aber vom F103.
>
> Gilt das Geschriebene auch für den F103?

Aus der stm32f1xx_hal_rcc.h:
1
/* Delay after an RCC peripheral clock enabling */

Also ST selber macht es so. Wird sicherlich einen Grund haben.

von Switcher (Gast)


Angehängte Dateien:

Lesenswert?

Da ich leider noch nicht weiter gekommen bin, hier ein vollständiges 
Minimalbeispiel. Mein Code sieht natürlich nicht so aus, ich wollte Euch 
aber ein Projekt aus zig Dateien ersparen.

Im Wesentlichen basiert das Projekt auf dem USB CDC ACM-Code von W.S., 
für gcc angepasst. Linker-Skript und Startup-Code sind der von ST/CubeMX 
generierte, mit kleinen Anpassungen.

USB und GPIO-Zeug funktioniert auch alles wunderbar, lediglich den SPI 
kriege ich nicht zum Laufen.

Hoffe jetzt auf weitere Tipps...

von Fern Schätzer (Gast)


Lesenswert?

Switcher schrieb:
> Hoffe jetzt auf weitere Tipps...

sysconfig (...)  wird nicht aufgerufen.

von Switcher (Gast)


Lesenswert?

Fern Schätzer schrieb:
> sysconfig (...)  wird nicht aufgerufen.

Doch, direkt vom Startup-Code:
1
...
2
3
LoopFillZerobss:
4
  ldr r3, = _ebss
5
  cmp r2, r3
6
  bcc FillZerobss
7
8
  bl  sysconfig/* Call the clock system intitialization function. */
9
  bl __libc_init_array   /* Call static constructors */
10
  bl main                /* Call the applications entry point. */
11
  bx lr
12
.size Reset_Handler, .-Reset_Handler

Sonst würde gar nix funktionieren...

von C. W. (chefkoch)


Lesenswert?

Auch wenn gleich wieder mit Dreck geschmissen wird: Benutze CubeMX um 
einfach mal zu schauen was alles gemacht wird bzw. werden muss. Ich kann 
nur sagen, dass der generierte Code betüglich SPI von CubeMX einwandfrei 
auf einem F103 läuft und frei von magic numbers ist.

von Dr. Sommer (Gast)


Lesenswert?

Du schreibst alles neu, benennst alle üblichen Konstanten um, dann 
wunderst du dich dass es nicht funktioniert und erwartest dann dass 
andere das aufdröseln? Benutze doch wenigstens die stm32f1xx.h und 
erspare dir den Wust an Makros. Dann könnten erfahrene STM32-User 
deutlich schneller sehen, woran es hapert.

von Dr. Sommer (Gast)


Lesenswert?

PS: Sicher, dass nicht irgendwo bei den ganzen Makros eine Textersetzung 
einen Ausdruck ergibt, der unerwartet evaluiert wird 
(Operator-Präzedenzen)? Du hast ja oft keine Klammern gesetzt, das kann 
lustige Effekte haben...

von Switcher (Gast)


Lesenswert?

Mit Cubemx läuft der SPI. Ich möchte aber eine bare metal Lösung.

Der Grund für den anderen Header ist W.S. usb vcp code, das File stammt 
von dort.

Ich stelle das Beispiel aber gerne auf den CMSIS Header um (heute Abend)

von honk (Gast)


Lesenswert?

Switcher schrieb:
> Die Pins des SPI1 sind auch nicht Remapped.


Und wie nennst Du das:
1
#define wf_AFIO_MAPR  (SPI1_REMAP)|

Nimms nicht persönlich, aber ich habe noch nie solch einen kruden Code 
gesehen. Tu Dir selber einen Gefallen und ändere das.
Dass Du ohne irgendwelche Bloat-Libs arbeitest, ist gut. Aber dann 
solltest Du auch gut lesbaren Code schreiben, also z.B. die vielen 
Defines weglassen, mit den Register- und Bitnamen aus den Headerdateien 
arbeiten und konsistent sein.

von Switcher (Gast)


Lesenswert?

honk schrieb:
> Und wie nennst Du das:
> #define wf_AFIO_MAPR  (SPI1_REMAP)|
> Nimms nicht persönlich, aber ich habe noch nie solch einen kruden Code
> gesehen.

Ich werde das jetzt auf die CMSIS umsetzen und den neuen Code hier 
posten.

Aber jetzt muss ich den Code von W.S. doch sehr in Schutz nehmen (die 
Defines stammen von ihm). Was Du "krud" nennst ist sehr systematisch, da 
werden erst die Remaps gesetzt (1/0 = ja/nein), und diese dann zum 
entsprechenden Registerwert zusammengesetzt.
1
/**************** Remap setup ******************/
2
3
#define SPI1_REMAP          0     /* PA4,5,6,7 --> PA15,3,4,5 */
4
#define I2C1_REMAP          1     /* PB6,7 --> PB8,9 */
5
#define USART1_REMAP        0     /* PA9,10 --> PB6,7 */
6
#define USART2_REMAP        0     /* PA0,1,2,3,4 --> PD3,4,5,6,7 */
7
8
(...)
9
10
#define wf_AFIO_MAPR  (SPI1_REMAP)|         \
11
                      (I2C1_REMAP<<1)|      \
12
          (USART1_REMAP<<2)|    \
13
          (USART2_REMAP<<3)|    \
14
          (USART3_REMAP0_3<<4)| \
15
          (TIM1_REMAP0_3<<6)|   \
16
          (TIM2_REMAP0_3<8)|    \
17
          (TIM3_REMAP0_3<10)|   \
18
          (TIM4_REMAP<<12)|     \
19
          (CAN1_REMAP0_3<<13)|  \
20
          (PD01_REMAP<<15)|     \
21
          (TIM5CH4_REMAP<<16)|  \
22
          (ADC1_ETRGINJ_REMAP<<17)| \
23
          (ADC1_ETRGREG_REMAP<<18)| \
24
          (ADC2_ETRGINJ_REMAP<<19)| \
25
                      (ADC3_ETRGREG_REMAP<<20)| \
26
          (SWJ_CFG0_7<<24)


Ich finde das sowohl kompakt als auch lesbar.

von Switcher (Gast)


Angehängte Dateien:

Lesenswert?

Läuft jetzt, war offenbar doch was mit den Defines... Im Attachment der 
Code Code mit den CMSIS-Headern.

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.