Mikrocontroller und Digitale Elektronik
›
Thread
Probleme mit STM32F103 und SPI1 remapping
Hallo allerseits,
ich habe mich mal nach längerer Pause wieder an die STM's rangewagt und habe mir ein kleines Board zum Spielen designed und gebaut.
Dabei handelt es sich um ein Board mit dem STM32F103, der auch auf dem BluePill-Board verbaut ist.
Ich habe am SPI1 ein kleines ILI9341 Display laufen, aber nicht an den default Pins für SPI1 (PA5-PA7) sondern an den alternativen Pins für den SPI1 (PB3-PB5).
Dafür muss der SPI1 anders gemappt werden, sowie der JTAG deaktiviert werden, um diese Pins dafür nutzen zu können. Zudem soll es noch ein Errata geben, was besagt, dass bei gemapptem SPI1 der Clock vom I2C1 nicht aktiviert sein darf. Ich habe jetzt schon Stunden rumprobiert, aber ich krieg den SPI1 einfach ums verrecken nicht zum laufen. In der Init hängt er sich zwar nicht auf, aber dann in der while()-Schleife in spi_send(). Zudem hab ich mal mit dem LogicAnalyzer geguckt, was da so lost ist. Auf PB3-PB5 absolut GAR nix. Der SPI ist komplett tot.
Vielleicht hat ja jemand das schonmal gemacht und könnte mir weiterhelfen. Hier mal der Code dazu:
1
//Pseudo-Functions
2
#define CS_low() GPIOC->ODR &= ~(1<<14);
3
#define CS_high() GPIOC->ODR |= (1<<14);
4
5
6
void spi_init ( void ) //set spi speed and settings
7
{
8
SPI_InitTypeDef SPI_InitStruct ;
9
GPIO_InitTypeDef GPIO_InitStruct ;
10
11
RCC_APB1PeriphClockCmd ( RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC , ENABLE );
12
RCC_APB1PeriphClockCmd ( RCC_APB1Periph_I2C1 , DISABLE ); //Errata -> Don't use Remapped SPI1 with activated I2C1-Clock
13
14
// GPIO pins for MISO, MOSI and SCK
15
GPIO_InitStruct . GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_4 | GPIO_Pin_3 ;
16
GPIO_InitStruct . GPIO_Mode = GPIO_Mode_AF_PP ;
17
GPIO_InitStruct . GPIO_Speed = GPIO_Speed_50MHz ;
18
GPIO_Init ( GPIOB , & GPIO_InitStruct );
19
20
//GPIO PortC 14 ->CS
21
GPIO_InitStruct . GPIO_Pin = GPIO_Pin_14 ;
22
GPIO_InitStruct . GPIO_Mode = GPIO_Mode_Out_PP ;
23
GPIO_InitStruct . GPIO_Speed = GPIO_Speed_50MHz ;
24
GPIO_Init ( GPIOC , & GPIO_InitStruct );
25
26
GPIO_PinRemapConfig ( GPIO_Remap_SWJ_JTAGDisable , ENABLE );
27
GPIO_PinRemapConfig ( GPIO_Remap_SPI1 , ENABLE );
28
29
SPI_InitStruct . SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256 ;
30
SPI_InitStruct . SPI_CPHA = SPI_CPHA_1Edge ;
31
SPI_InitStruct . SPI_CPOL = SPI_CPOL_Low ;
32
SPI_InitStruct . SPI_DataSize = SPI_DataSize_8b ;
33
SPI_InitStruct . SPI_Direction = SPI_Direction_2Lines_FullDuplex ; //SPI_Direction_1Line_Tx;
34
SPI_InitStruct . SPI_FirstBit = SPI_FirstBit_MSB ;
35
SPI_InitStruct . SPI_Mode = SPI_Mode_Master ;
36
SPI_InitStruct . SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set ;
37
SPI_Init ( SPI1 , & SPI_InitStruct );
38
SPI_Cmd ( SPI1 , ENABLE );
39
40
CS_high ();
41
}
42
43
void spi_send ( uint8_t spi_data ) //send spi data to display
44
{
45
SPI1 -> DR = spi_data ; // Write data to be transmitted to the SPI data register
46
while ( ! ( SPI1 -> SR & ( SPI_I2S_FLAG_TXE ))); // Wait until transmit complete
47
while ( SPI1 -> SR & ( SPI_I2S_FLAG_BSY )); // Wait until SPI is not busy anymore
48
}
49
50
uint8_t spi_read ( void )
51
{
52
SPI1 -> DR = 0x00 ; // Write data to be transmitted to the SPI data register
53
while ( ! ( SPI1 -> SR & ( SPI_I2S_FLAG_TXE ))); // Wait until transmit complete
54
while ( SPI1 -> SR & ( SPI_I2S_FLAG_BSY )); // Wait until SPI is not busy anymore
55
while ( ! ( SPI1 -> SR & ( SPI_I2S_FLAG_RXNE ))); // Wait until receive complete
56
return SPI1 -> DR ; // Return received data from SPI data register
57
}
Viele Grüße
Henning
M
Monk
Gast
04.09.2024 20:35
#7731350
Bist du sicher, dass es ein originaler STM32F103C8 ist?
Moin Monk,
ja, da bin ich mir eigentlich sicher. Habe anbei mal ein Foto von dem Controller angehängt.
Viele Grüße
Henning S. schrieb:
Vielleicht hat ja jemand das schonmal gemacht und könnte mir
weiterhelfen.
Ich hab mal schnell CubeMX angeworfen und den Code für deine
Konfiguration generieren lassen. Dabei fällt auf dass MISO als
Input deklariert wird, also keine alternate Function hat.
Vielleicht kannst du dir aus den restlichen Zeilen einen Reim
machen ob bei dir alles stimmig ist. Siehe Anhang.
Wastl schrieb:
Dabei fällt auf dass MISO als Input deklariert wird
Also genauer genommen als floating Pin, das wird offensichtlich
gebraucht damit die alternate Function erfüllt werden kann.
Beim Setzen der GPIO_InitStruct für MISO werden die Daten von den
Output-Pins übernommen, speziell die alternate Function bleibt
bestehen.
Moin Wastl,
danke schonmal für deine Hilfe. Ich hab es jetzt mal genauso gemacht und hab den Miso als Floating Input. Zudem hab ich noch die Interrupt-Config aus dem CubeMX Code übernommen. Beides bringt aber leider keine Änderung.
1
void spi_init ( void ) //set spi speed and settings
2
{
3
SPI_InitTypeDef SPI_InitStruct ;
4
GPIO_InitTypeDef GPIO_InitStruct ;
5
6
RCC_APB1PeriphClockCmd ( RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC , ENABLE );
7
RCC_APB1PeriphClockCmd ( RCC_APB1Periph_I2C1 , DISABLE ); //Errata -> Don't use Remapped SPI1 with activated I2C1-Clock
8
9
// GPIO pins for MOSI and SCK
10
GPIO_InitStruct . GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5 ;
11
GPIO_InitStruct . GPIO_Mode = GPIO_Mode_AF_PP ;
12
GPIO_InitStruct . GPIO_Speed = GPIO_Speed_50MHz ;
13
GPIO_Init ( GPIOB , & GPIO_InitStruct );
14
15
// GPIO pins for MISO
16
GPIO_InitStruct . GPIO_Pin = GPIO_Pin_4 ;
17
GPIO_InitStruct . GPIO_Mode = GPIO_Mode_IN_FLOATING ;
18
GPIO_Init ( GPIOB , & GPIO_InitStruct );
19
20
//GPIO PortC 14 ->CS
21
GPIO_InitStruct . GPIO_Pin = GPIO_Pin_14 ;
22
GPIO_InitStruct . GPIO_Mode = GPIO_Mode_Out_PP ;
23
GPIO_Init ( GPIOC , & GPIO_InitStruct );
24
25
//Remapping SPI1 to PB3-5 & Disable JTAG
26
GPIO_PinRemapConfig ( GPIO_Remap_SWJ_JTAGDisable , ENABLE );
27
GPIO_PinRemapConfig ( GPIO_Remap_SPI1 , ENABLE );
28
29
NVIC_SetPriority ( SPI1_IRQn , NVIC_EncodePriority ( NVIC_GetPriorityGrouping (), 0 , 0 ));
30
NVIC_EnableIRQ ( SPI1_IRQn );
31
32
SPI_InitStruct . SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256 ;
33
SPI_InitStruct . SPI_CPHA = SPI_CPHA_1Edge ;
34
SPI_InitStruct . SPI_CPOL = SPI_CPOL_Low ;
35
SPI_InitStruct . SPI_DataSize = SPI_DataSize_8b ;
36
SPI_InitStruct . SPI_Direction = SPI_Direction_2Lines_FullDuplex ; //SPI_Direction_1Line_Tx;
37
SPI_InitStruct . SPI_FirstBit = SPI_FirstBit_MSB ;
38
SPI_InitStruct . SPI_Mode = SPI_Mode_Master ;
39
SPI_InitStruct . SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set ;
40
SPI_Init ( SPI1 , & SPI_InitStruct );
41
SPI_Cmd ( SPI1 , ENABLE );
42
43
CS_high ();
44
}
Grüße
Henning S. schrieb:
Beides bringt aber leider keine Änderung.
Ist diese Zeile
1
LL_APB2_GRP1_EnableClock ( LL_APB2_GRP1_PERIPH_SPI1 );
gleichlautend zu deiner Initialisierung?
Ich würde die Clock-Initialisierung immer separat für jedes
Peripherie-Element aufrufen, es ist mir sonst zu unübersichtlich ...
Henning S. schrieb:
Zudem hab ich noch die Interrupt-Config
aus dem CubeMX Code übernommen.
Das Interrupt-Handling hat sicherlich nichts mit der prinzipiellen
Hardware-Funktionalität des SPI zu tun.
Wastl schrieb:
Henning S. schrieb:
Beides bringt aber leider keine Änderung.
Ist diese Zeile
1
> LL_APB2_GRP1_EnableClock ( LL_APB2_GRP1_PERIPH_SPI1 );
2
>
gleichlautend zu deiner Initialisierung?
Ich würde die Clock-Initialisierung immer separat für jedes
Peripherie-Element aufrufen, es ist mir sonst zu unübersichtlich ...
Hallo Wastl,
DANKE! Das war entscheidende Hinweis auf den Tippfehler, den ich drin hatte. Da hast du mich auf die richtige Spur gebracht
Falsch:
1
RCC_APB1PeriphClockCmd ( RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC , ENABLE );
2
RCC_APB1PeriphClockCmd ( RCC_APB1Periph_I2C1 , DISABLE ); //Errata -> Don't use Remapped SPI1 with activated I2C1-Clock
Richtig
1
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC , ENABLE );
2
RCC_APB1PeriphClockCmd ( RCC_APB1Periph_I2C1 , DISABLE ); //Errata -> Don't use Remapped SPI1 with activated I2C1-Clock
Jetzt kann ich endlich schlafen gehen :-D
Viele Grüße
Henning S. schrieb:
DANKE! Das war entscheidende Hinweis auf den Tippfehler, den ich drin
hatte. Da hast du mich auf die richtige Spur gebracht
Danke. Mit den Clock-Bezeichnungen stehe ich auch auf Kriegsfuss,
zum Glück nimmt einem da CubeMX die Arbeit ab.
Würde dir auch empfehlen mit CubeMX zu arbeiten. Die HAL-
Geschichten kann man ja getrost unbeachtet lassen.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.
Noch kein Account?
Die Registrierung ist kostenlos und dauert nur eine Minute.
Jetzt registrieren