Forum: Mikrocontroller und Digitale Elektronik STM32F7xx und Audio codec am SAI2


von itzztitz (Gast)


Lesenswert?

Hi

Ich abe einen STM32F745 und am SAI2 einen Audio codec WM8510
Der einfacheit halber soll erstmal nur etwas rauskommen.
Mit CubeMX habei ch mir das ausgewürfelt:

Samplerate: 8KHz bei 16bit

PeriphClkInitStruct.PLLSAI.PLLSAIN = 288;
PeriphClkInitStruct.PLLSAI.PLLSAIR = 2;
PeriphClkInitStruct.PLLSAI.PLLSAIQ = 5;
PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV8;
das sollten 12,288 Mhz als basistakt sein

    PC0      ------> SAI2_FS_B
    PA0      ------> SAI2_SD_B
    PE12     ------> SAI2_SCK_B
    PE14     ------> SAI2_MCLK_B


Später soll der SAI2_A hinzukommen.



als code kommt das für die init bei heraus:
1
// in main.c
2
static void MX_SAI2_Init(void)
3
{
4
5
  hsai_BlockB2.Instance = SAI2_Block_B;
6
  hsai_BlockB2.Init.AudioMode = SAI_MODEMASTER_TX;
7
  hsai_BlockB2.Init.Synchro = SAI_ASYNCHRONOUS;
8
  hsai_BlockB2.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
9
  hsai_BlockB2.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
10
  hsai_BlockB2.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_FULL;
11
  hsai_BlockB2.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_8K;
12
  hsai_BlockB2.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
13
  hsai_BlockB2.Init.MonoStereoMode = SAI_STEREOMODE;
14
  hsai_BlockB2.Init.CompandingMode = SAI_NOCOMPANDING;
15
  hsai_BlockB2.Init.TriState = SAI_OUTPUT_RELEASED;
16
  if (HAL_SAI_InitProtocol(&hsai_BlockB2, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_16BIT, 2) != HAL_OK)
17
  {
18
    Error_Handler();
19
  }
20
21
}
22
23
// in stm32f7xx_hal_msp.c
24
void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)
25
{
26
27
  GPIO_InitTypeDef GPIO_InitStruct;
28
/* SAI2 */
29
    if(hsai->Instance==SAI2_Block_B)
30
    {
31
      /* Peripheral clock enable */
32
      if (SAI2_client == 0)
33
      {
34
      __HAL_RCC_SAI2_CLK_ENABLE();
35
      }
36
    SAI2_client ++;
37
    
38
    /**SAI2_B_Block_B GPIO Configuration    
39
    PC0      ------> SAI2_FS_B
40
    PA0      ------> SAI2_SD_B
41
    PE12     ------> SAI2_SCK_B
42
    PE14     ------> SAI2_MCLK_B 
43
    */
44
    GPIO_InitStruct.Pin = GPIO_PIN_0;
45
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
46
    GPIO_InitStruct.Pull = GPIO_NOPULL;
47
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
48
    GPIO_InitStruct.Alternate = GPIO_AF8_SAI2;
49
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
50
51
    GPIO_InitStruct.Pin = GPIO_PIN_0;
52
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
53
    GPIO_InitStruct.Pull = GPIO_NOPULL;
54
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
55
    GPIO_InitStruct.Alternate = GPIO_AF10_SAI2;
56
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
57
58
    GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_14;
59
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
60
    GPIO_InitStruct.Pull = GPIO_NOPULL;
61
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
62
    GPIO_InitStruct.Alternate = GPIO_AF10_SAI2;
63
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
64
65
    /* Peripheral DMA init*/
66
    
67
    hdma_sai2_b.Instance = DMA2_Stream6;
68
    hdma_sai2_b.Init.Channel = DMA_CHANNEL_3;
69
    hdma_sai2_b.Init.Direction = DMA_PERIPH_TO_MEMORY;
70
    hdma_sai2_b.Init.PeriphInc = DMA_PINC_DISABLE;
71
    hdma_sai2_b.Init.MemInc = DMA_MINC_ENABLE;
72
    hdma_sai2_b.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
73
    hdma_sai2_b.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
74
    hdma_sai2_b.Init.Mode = DMA_CIRCULAR;
75
    hdma_sai2_b.Init.Priority = DMA_PRIORITY_LOW;
76
    hdma_sai2_b.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
77
    hdma_sai2_b.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
78
    hdma_sai2_b.Init.MemBurst = DMA_MBURST_SINGLE;
79
    hdma_sai2_b.Init.PeriphBurst = DMA_PBURST_SINGLE;
80
    if (HAL_DMA_Init(&hdma_sai2_b) != HAL_OK)
81
    {
82
      Error_Handler();
83
    }
84
85
    /* Several peripheral DMA handle pointers point to the same DMA handle.
86
     Be aware that there is only one stream to perform all the requested DMAs. */
87
    __HAL_LINKDMA(hsai,hdmarx,hdma_sai2_b);
88
    __HAL_LINKDMA(hsai,hdmatx,hdma_sai2_b);
89
    }
90
}



Nun zum Problem:

MCLK und BCLK funktionieren wie gewollt
MCLK liegt bei 2,05Mhz  ( 256 * 8000 )
BCLK bei 256kHz  ( 16bit  2  8000 )

Was aber fehlt ist der FS takt von 8kHz
Ich habe dazu auch schon den FS Pin mal umgebogen aber auch hier kein 
wackeln.
Er springt zwar in den Interrupt ... aber es passiert auch nocht nichts.
Hat schonmal jemand mit dem SAI gearbeitet?
oder kann vlt weiterhelfen?


Im vorraus: DANKE !!!

von Vincent H. (vinci)


Lesenswert?

Ohne Daten bleibt FS aus. Das Datenblatt sagt folgendes:

"In master TX mode, enabling the audio block immediately generates the 
bit clock for the external slaves even if there is no data in the FIFO, 
However FS signal generation is conditioned by the presence of data in 
the FIFO. After the FIFO receives the first data to transmit, this data 
is output to external slaves."

Außerdem ist mit aufgefallen, dass du SAI als "Stereo" initialisierts, 
der WM8510 aber Mono sein dürfte?

lg

von itzztitz (Gast)


Lesenswert?

hi

bei mono kopiert er die daten..
Ich lese eh an den korrekten stellen aus , daher stört das nicht

Das ganze lief ja vorher auf dem STM32F4 am I2S


Problem gefunden ...
DMA war falsch konfiguriert.

Jetzt kommt ton raus.
Ton rein ist noch die frage wegen der internen synchronisierung...

von itzztitz (Gast)


Lesenswert?

Hi

ich nochmal.


Ton raus ist ja mitlerweile gelöst.
Ton rein jedoch will nicht funktionieren.

der Buffe rist immer leer.
Auch springt er in den DMA Interrupt.
Es ist auch auf der Leitung kein traffic zu sehen.

MCLK 2,048Mhz
BCLK 256Khz
FS   8Khz

sind alle da.

Wenn ein signal kommt ist auch in TX richtig daten zu sehen.
Nur RX kommt leider nichts



1
DMA_HandleTypeDef hdma_sai2_Input;
2
DMA_HandleTypeDef hdma_sai2_Output;
3
static uint32_t SAI2_client =0;
4
5
void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)
6
{
7
    GPIO_InitTypeDef GPIO_InitStruct;
8
    /* SAI2 */
9
  if(hsai->Instance==SAI2_Block_A)
10
  {
11
  /* Peripheral clock enable */
12
  if (SAI2_client == 0)
13
  {
14
    __HAL_RCC_SAI2_CLK_ENABLE();
15
  }
16
  SAI2_client ++;
17
18
  /**SAI2_A_Block_A GPIO Configuration
19
  PD11     ------> SAI2_SD_A
20
  */
21
  GPIO_InitStruct.Pin     = GPIO_PIN_11;
22
  GPIO_InitStruct.Mode     = GPIO_MODE_AF_PP;
23
  GPIO_InitStruct.Pull     = GPIO_NOPULL;
24
  GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
25
  GPIO_InitStruct.Alternate   = GPIO_AF10_SAI2;
26
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
27
28
  /* Peripheral DMA init*/
29
  hdma_sai2_Input.Instance         = DMA2_Stream4;
30
  hdma_sai2_Input.Init.Channel       = DMA_CHANNEL_3;
31
  hdma_sai2_Input.Init.Direction       = DMA_PERIPH_TO_MEMORY;
32
  hdma_sai2_Input.Init.PeriphInc       = DMA_PINC_DISABLE;
33
  hdma_sai2_Input.Init.MemInc          = DMA_MINC_ENABLE;
34
  hdma_sai2_Input.Init.PeriphDataAlignment   = DMA_PDATAALIGN_HALFWORD;
35
  hdma_sai2_Input.Init.MemDataAlignment   = DMA_MDATAALIGN_HALFWORD;
36
  hdma_sai2_Input.Init.Mode         = DMA_CIRCULAR;
37
  hdma_sai2_Input.Init.Priority       = DMA_PRIORITY_HIGH;
38
  hdma_sai2_Input.Init.FIFOMode       = DMA_FIFOMODE_ENABLE;
39
  hdma_sai2_Input.Init.FIFOThreshold     = DMA_FIFO_THRESHOLD_HALFFULL;
40
  hdma_sai2_Input.Init.MemBurst       = DMA_MBURST_SINGLE;
41
  hdma_sai2_Input.Init.PeriphBurst     = DMA_PBURST_SINGLE;
42
43
  if (HAL_DMA_Init(&hdma_sai2_Input) != HAL_OK)
44
  {
45
    Error_Handler();
46
  }
47
48
  /* Several peripheral DMA handle pointers point to the same DMA handle.
49
   Be aware that there is only one stream to perform all the requested DMAs. */
50
  __HAL_LINKDMA(hsai,hdmarx,hdma_sai2_Input);
51
  __HAL_LINKDMA(hsai,hdmatx,hdma_sai2_Input);
52
53
  }
54
  if(hsai->Instance==SAI2_Block_B)
55
  {
56
    /* Peripheral clock enable */
57
    if (SAI2_client == 0)
58
    {
59
    __HAL_RCC_SAI2_CLK_ENABLE();
60
    }
61
  SAI2_client ++;
62
63
  /**SAI2_B_Block_B GPIO Configuration
64
  PC0     ------> SAI2_FS_B
65
  PA0/WKUP     ------> SAI2_SD_B
66
  PE12     ------> SAI2_SCK_B
67
  PE14     ------> SAI2_MCLK_B
68
  */
69
  GPIO_InitStruct.Pin = GPIO_PIN_0;
70
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
71
  GPIO_InitStruct.Pull = GPIO_NOPULL;
72
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
73
  GPIO_InitStruct.Alternate = GPIO_AF8_SAI2;
74
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
75
76
  GPIO_InitStruct.Pin = GPIO_PIN_0;
77
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
78
  GPIO_InitStruct.Pull = GPIO_NOPULL;
79
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
80
  GPIO_InitStruct.Alternate = GPIO_AF10_SAI2;
81
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
82
83
  GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_14;
84
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
85
  GPIO_InitStruct.Pull = GPIO_NOPULL;
86
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
87
  GPIO_InitStruct.Alternate = GPIO_AF10_SAI2;
88
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
89
90
  /* Peripheral DMA init*/
91
  hdma_sai2_Output.Instance         = DMA2_Stream6;
92
  hdma_sai2_Output.Init.Channel       = DMA_CHANNEL_3;
93
  hdma_sai2_Output.Init.Direction     = DMA_MEMORY_TO_PERIPH;
94
  hdma_sai2_Output.Init.PeriphInc     = DMA_PINC_DISABLE;
95
  hdma_sai2_Output.Init.MemInc       = DMA_MINC_ENABLE;
96
  hdma_sai2_Output.Init.PeriphDataAlignment   = DMA_PDATAALIGN_HALFWORD;
97
  hdma_sai2_Output.Init.MemDataAlignment     = DMA_MDATAALIGN_HALFWORD;
98
  hdma_sai2_Output.Init.Mode         = DMA_CIRCULAR;
99
  hdma_sai2_Output.Init.Priority       = DMA_PRIORITY_HIGH;
100
  hdma_sai2_Output.Init.FIFOMode       = DMA_FIFOMODE_ENABLE;
101
  hdma_sai2_Output.Init.FIFOThreshold   = DMA_FIFO_THRESHOLD_HALFFULL;
102
  hdma_sai2_Output.Init.MemBurst       = DMA_MBURST_SINGLE;
103
  hdma_sai2_Output.Init.PeriphBurst     = DMA_PBURST_SINGLE;
104
  if (HAL_DMA_Init(&hdma_sai2_Output) != HAL_OK)
105
  {
106
    Error_Handler();
107
  }
108
109
  /* Several peripheral DMA handle pointers point to the same DMA handle.
110
   Be aware that there is only one stream to perform all the requested DMAs. */
111
  __HAL_LINKDMA(hsai,hdmarx,hdma_sai2_Output);
112
  __HAL_LINKDMA(hsai,hdmatx,hdma_sai2_Output);
113
  }
114
}
115
116
117
static void MX_SAI2_Init(void)
118
{
119
    // output
120
    hsai_output.Instance         = SAI2_Block_B;
121
    hsai_output.Init.AudioMode     = SAI_MODEMASTER_TX;
122
    hsai_output.Init.Synchro       = SAI_ASYNCHRONOUS;
123
    hsai_output.Init.OutputDrive     = SAI_OUTPUTDRIVE_DISABLE;
124
125
    hsai_output.Init.NoDivider     = SAI_MASTERDIVIDER_ENABLE;
126
    hsai_output.Init.FIFOThreshold   = SAI_FIFOTHRESHOLD_FULL;
127
    hsai_output.Init.AudioFrequency   = SAI_AUDIO_FREQUENCY_8K;
128
    hsai_output.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
129
    hsai_output.Init.MonoStereoMode   = SAI_STEREOMODE;
130
    hsai_output.Init.CompandingMode   = SAI_NOCOMPANDING;
131
    hsai_output.Init.TriState     = SAI_OUTPUT_NOTRELEASED;
132
133
    if (HAL_SAI_InitProtocol(&hsai_output, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_16BIT, 2) != HAL_OK)
134
    {
135
      Error_Handler();
136
    }
137
    // input
138
    hsai_input.Instance         = SAI2_Block_A;
139
    hsai_input.Init.AudioMode     = SAI_MODESLAVE_RX;
140
    hsai_input.Init.Synchro       = SAI_SYNCHRONOUS;
141
    hsai_input.Init.OutputDrive     = SAI_OUTPUTDRIVE_DISABLE;
142
143
//    hsai_input.Init.NoDivider     = SAI_MASTERDIVIDER_ENABLE;
144
    hsai_input.Init.FIFOThreshold   = SAI_FIFOTHRESHOLD_FULL;
145
///    hsai_input.Init.AudioFrequency   = SAI_AUDIO_FREQUENCY_8K;
146
    hsai_input.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
147
    hsai_input.Init.MonoStereoMode   = SAI_STEREOMODE;
148
    hsai_input.Init.CompandingMode   = SAI_NOCOMPANDING;
149
    hsai_input.Init.TriState       = SAI_OUTPUT_RELEASED;
150
151
    if (HAL_SAI_InitProtocol(&hsai_input, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_16BIT, 2) != HAL_OK)
152
    {
153
      Error_Handler();
154
    }
155
156
}
157
158
static void MX_DMA_Init(void)
159
{
160
  /* DMA controller clock enable */
161
  __HAL_RCC_DMA2_CLK_ENABLE();
162
163
  /* DMA interrupt init */
164
  /* DMA2_Stream4_IRQn interrupt configuration */
165
  HAL_NVIC_SetPriority(DMA2_Stream4_IRQn, MEDIA_AL_IRQ_PREPRIO , MEDIA_AL_IRQ_SUBRIO);
166
  HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);
167
168
  /* DMA2_Stream6_IRQn interrupt configuration */
169
  HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, MEDIA_AL_IRQ_PREPRIO , MEDIA_AL_IRQ_SUBRIO);
170
  HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
171
}
172
173
void DMA2_Stream4_IRQHandler(void)
174
{
175
  HAL_DMA_IRQHandler( hsai_input.hdmarx );
176
}
177
178
void DMA2_Stream6_IRQHandler(void)
179
{
180
  HAL_DMA_IRQHandler( hsai_output.hdmatx );
181
}
182
183
static void Start_Stream( uint8_t* Play, uint8_t* Record, uint32_t Size ){
184
  HAL_SAI_Transmit_DMA( &hsai_output, (uint8_t *)Play    , Size );
185
  HAL_SAI_Receive_DMA(  &hsai_input , (uint8_t *)Record   , Size );
186
}
187
188
189
//PLAYBACK
190
void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
191
{
192
  if( hsai->Instance == SAI2_Block_B ){
193
  }else if( hsai->Instance == SAI2_Block_A ){
194
195
  }
196
}
197
void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
198
{
199
  if( hsai->Instance == SAI2_Block_B ){
200
  }else if( hsai->Instance == SAI2_Block_A ){
201
202
  }
203
}
204
205
//RECORD
206
void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
207
{
208
  if( hsai->Instance == SAI2_Block_B ){
209
  }else if( hsai->Instance == SAI2_Block_A ){
210
  }
211
}
212
void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
213
{
214
  if( hsai->Instance == SAI2_Block_B ){
215
  }else if( hsai->Instance == SAI2_Block_A ){
216
  }
217
}
218
219
void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
220
{
221
  if( hsai->Instance == SAI2_Block_B ){
222
  }else if( hsai->Instance == SAI2_Block_A ){
223
  }
224
}

von itzztitz (Gast)


Lesenswert?

niemand eine idee?

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.