Forum: Mikrocontroller und Digitale Elektronik STM32 empfängt keine SPDIF-Daten


von Shinner (Gast)


Lesenswert?

Ich versuche hier, mit einem STM32F466RE einen SPDIF-Datenstrom an PB7 
zu empfangen. Der Code ist mit CubeMX erzeugt und sollte daher 
eigentlich passen, wenn ich mir ansehe, was CubeMX generiert hat, kann 
ich keinen offensichtlichen Fehler erkennen. Der SPDIF-Datenstrom ist - 
direkt am Eingangspin gemessen - ein perfektes und astrein sauberes 
Signal. Der zugehörige sowie die globalen Interrupts sind aktiviert. 
Trotzdem wird nichts empfangen, die Receive-Interruptfunktion wird nie 
aufgerufen:
1
void HAL_SPDIFRX_RxCpltCallback(SPDIFRX_HandleTypeDef *hspdif)
2
{
3
   spdifRecvComplete=1;
4
}

Die Initialisierung von CubeMX sieht inklusive des Pinmappings so aus 
(zumindest die relevanten Teile, der Rest ist ja eh' der immer gleiche, 
generierte Code):
1
   hspdif.Instance = SPDIFRX;
2
   hspdif.Init.InputSelection = SPDIFRX_INPUT_IN0;
3
   hspdif.Init.Retries = SPDIFRX_MAXRETRIES_63;
4
   hspdif.Init.WaitForActivity = SPDIFRX_WAITFORACTIVITY_ON;
5
   hspdif.Init.ChannelSelection = SPDIFRX_CHANNEL_A;
6
   hspdif.Init.DataFormat = SPDIFRX_DATAFORMAT_LSB;
7
   hspdif.Init.StereoMode = SPDIFRX_STEREOMODE_ENABLE;
8
   hspdif.Init.PreambleTypeMask = SPDIFRX_PREAMBLETYPEMASK_ON;
9
   hspdif.Init.ChannelStatusMask = SPDIFRX_CHANNELSTATUS_ON;
10
   hspdif.Init.ValidityBitMask = SPDIFRX_VALIDITYMASK_ON;
11
   hspdif.Init.ParityErrorMask = SPDIFRX_PARITYERRORMASK_ON;
12
   if (HAL_SPDIFRX_Init(&hspdif) != HAL_OK)
13
   {
14
      Error_Handler();
15
   }
16
  
17
  ...
18
19
   GPIO_InitStruct.Pin = GPIO_PIN_7;
20
   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
21
   GPIO_InitStruct.Pull = GPIO_PULLUP;
22
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
23
   GPIO_InitStruct.Alternate = GPIO_AF8_SPDIFRX;
24
   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
25
26
   /* SPDIFRX interrupt Init */
27
   HAL_NVIC_SetPriority(SPDIF_RX_IRQn, 0, 5);
28
   HAL_NVIC_EnableIRQ(SPDIF_RX_IRQn);

An der Funktion, die den Empfang der Daten starten sollte, ist auch 
nichts dramatisch kompliziertes:
1
if (HAL_SPDIFRX_ReceiveDataFlow_IT(&hspdif,recvBuffer,8)==HAL_OK)
2
{
3
   spdifRecvComplete=0;
4
}

Google hilft nicht wirklich weiter, entweder finde ich Beispielcode, der 
auch nur aus CubeMX stammt, oder der für einen anderen STM32-Typen ist 
und letztenendes auch keine Erkenntnisse bringt, die das Problem lösen 
würden.

Das Einzige, was in meinem Fall speziell ist: die eingehenden Daten 
haben 100 kHz statt 96 kHz oder 192 khz oder irgend ein anderes 
Vielfaches von 24 kHz - aber ich kann nirgendwo im Handbuch erkennen, 
dass das ein Problem wäre, es ist nur von einer Maxialfrequenz von 192 
kHz die Rede.

Was könnte hier falsch sein/fehlen?

von Lothar J. (black-bird)


Lesenswert?

IRQ Receive Routine?

Blackbird

von Shinner (Gast)


Lesenswert?

Lothar J. schrieb:
> IRQ Receive Routine?

...wird von dem CubeMX-Code gemacht. Wenn es so funktioniert, wie es 
soll, erhalte ich ein "Receive Complete" über die Funktion 
HAL_SPDIFRX_RxCpltCallback() und finde dann die empfangenen Daten in 
meinem per HAL_SPDIFRX_ReceiveDataFlow_IT() übergebenen recvBuffer. Aber 
eben dieses "Receive Complete" kommt nie.

von Sebastian (Gast)


Lesenswert?

spdifRecvComplete volatile?

LG, Sebastian

von Lothar J. (black-bird)


Lesenswert?

Shinner schrieb:
> ...wird von dem CubeMX-Code gemacht. Wenn es so funktioniert, wie es
> soll, erhalte ich ein "Receive Complete" über die Funktion
> HAL_SPDIFRX_RxCpltCallback() und finde dann die empfangenen Daten in
> meinem per HAL_SPDIFRX_ReceiveDataFlow_IT() übergebenen recvBuffer. Aber
> eben dieses "Receive Complete" kommt nie.

Dann würde ich in dieser IRQ Routine suchen per Debugger.
Meine Erfahrungen kommen aus der EFM32 Ecke, die sind ja ähnlich und 
eine HAL gibt es da auch.
Nur hat die selten vollständigen Code generiert, wie soll sie auch.

Blackbird

von Shinner (Gast)


Lesenswert?

Das wäre SPDIF_RX_IRQHandler() - die wird niemals aufgerufen.

Tatsächlich kann ich nicht erkennen, wo die jemals als 
IRQ-Einsprungpunkt gesetzt werden würde. Allerdings sehe ich das bei 
USART2_IRQHandler() auch nicht, aber der UART-Interrupt funktioniert.

von mitlesa (Gast)


Lesenswert?

Shinner schrieb:
> Tatsächlich kann ich nicht erkennen, wo die jemals als
> IRQ-Einsprungpunkt gesetzt werden würde.

Üblicherweise ist diese Funktion in der Datei <stm32f4xx_it.c>
zu finden ....
1
/******************************************************************************/
2
/* STM32F4xx Peripheral Interrupt Handlers                                    */
3
/* Add here the Interrupt Handlers for the used peripherals.                  */
4
/* For the available peripheral interrupt handler names,                      */
5
/* please refer to the startup file (startup_stm32f4xx.s).                    */
6
/******************************************************************************/
7
/**
8
  * @brief This function handles SPDIF-RX global interrupt.
9
  */
10
void SPDIF_RX_IRQHandler(void)
11
{
12
  /* USER CODE BEGIN SPDIF_RX_IRQn 0 */
13
14
  /* USER CODE END SPDIF_RX_IRQn 0 */
15
  HAL_SPDIFRX_IRQHandler(&hspdif);
16
  /* USER CODE BEGIN SPDIF_RX_IRQn 1 */
17
18
  /* USER CODE END SPDIF_RX_IRQn 1 */
19
}

von Shinner (Gast)


Lesenswert?

mitlesa schrieb:
> Shinner schrieb:
>> Tatsächlich kann ich nicht erkennen, wo die jemals als
>> IRQ-Einsprungpunkt gesetzt werden würde.
>
> Üblicherweise ist diese Funktion in der Datei <stm32f4xx_it.c>
> zu finden ....

Nein, die Funktion selber ist im Usercode zu finden, weil dort auch das 
SPDIF-Handle liegt, welches für die weitere Bearbietung des Interrupt 
benötigt wird.

Die Frage ist, wo wird der POINTER auf diese Funktion in die Hardware 
geschrieben? Das muss ja irgendwo passieren, so dass der Interrupt weiß, 
wo hingesprungen werden muss. Und diese Zuweisung Hardware Interrupt -> 
aufzurufende Funktion SPDIF_RX_IRQHandler() fehlt mir hier irgendwie 
komplett.

von A. B. (funky)


Lesenswert?

mitlesa hat schon recht

normalerweise ist SPDIF_RX_IRQHandler als weak definiert in einem deiner 
startup files.
startup_stm32f...s dürfte das heißen

dort findest du dann ein EXPORT SPDIF_RX_IRQHandler [WEAK]
und das wird in der xxx_it.c   implementiert. Dort wird dann der HAL 
IRQHandler aufgerufen, der dann wiederum deinen callback aufruft.

von Shinner (Gast)


Lesenswert?

A. B. schrieb:
> normalerweise ist SPDIF_RX_IRQHandler als weak definiert

Auch dann fehlt mir die Verbindung zwischen Code und Hardware! Die MCU 
springt ja keinen String "SPDIF_RX_IRQHandler" an, sondern eine Adresse, 
hinter der sich dieser IRQ-Handler verbirgt, der halt zufällig 
"SPDIF_RX_IRQHandler" heißt.

von mitlesa (Gast)


Angehängte Dateien:

Lesenswert?

Shinner schrieb:
> Auch dann fehlt mir die Verbindung zwischen Code und Hardware! Die MCU
> springt ja keinen String "SPDIF_RX_IRQHandler" an, sondern eine Adresse,
> hinter der sich dieser IRQ-Handler verbirgt, der halt zufällig
> "SPDIF_RX_IRQHandler" heißt.

Das klingt deutlich nach Beratungsresistenz bzw. Faulheit einfach
nachzusehen wo was ist. Also hier noch im Detail für die Faulen
unter uns: Im Anhang ein Auszug aus <startup_stm32f446xx.s>.
Dort sind am Anfang viele 32-Bit Worte (also Vektoren) definiert
wobei für jeden Offset von Null ein bestimmter auf die Hardware
zugeschnittener Platz für einen Interrupt reserviert ist. Der
Offset bestimmt welcher Hardware-IRQ gemeint ist, der Wert
bestimmt wo hingesprungen werden soll. Wer's jetzt nicht kapiert
dem ist nicht mehr zu helfen.

von Stefan W. (stefan_w380)


Lesenswert?

Ich finde das Thema S/P-DIF mit STM32 hochspannend.
Denn es gibt von TI Class-D Verstärkerchips, die einen Digital-Eingang 
haben und man kann mit dem STM32 dann auch über die I2C Schnittstelle 
bei dem TI Class-D Verstärker einiges einstellen, z.b. Mehrkanal-EQ, 
Lautstärke etc.
Mit einem Bluetoothmodul könnte man auch eine Fernbedienung übers Handy 
realisieren, etc.
Aktivboxen mit digitaler Frequenzweiche, die Frequenzcharakteristik 
übers Handy konfiguieren etc. Raumkorrektur.
Da wäre ein STM32 in der Mitte als Controller mit SP-DIF Eingang für den 
ganzen Spaß eine interessante Option.

von Harry L. (mysth)


Lesenswert?

Poste mal deine .ioc-Datei!

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.