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.
>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;
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.
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.
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.
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.
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...
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.
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.
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...
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)
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.
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.