Forum: Mikrocontroller und Digitale Elektronik STM32F4 Discovery audio passtrough (MP45DT02 --> CS43L22)


von Roland E. (seahood)


Angehängte Dateien:

Lesenswert?

Hallo,
ich probiere schon länger mein 32STMF4 Discovery board zu zu bewegen das 
Mikrofonsignal(MP45DT02) auf den Kopfhörerausgang(CS43L22) durch zu 
schieben, und zwischen durch DSP zu machen. Nach anfänglichen versuchen 
die STM32Cube Beispiele nach gcc zu portieren und um zu bauen, bekam ich 
code von jemanden der genau dies gemacht hat um einen audio codec aus zu 
probieren. Ich habe nur die Quellen bekommen, keine Makefiles oder 
Linkerscripte. Ich kann mittlerweile alles mit arm-none-eabi-gcc und 
meinen Makefiles compilieren, und das DMA und IRQ handlich scheint auch 
richtig implementiert zu sein, jedoch läuft es auf dem board nicht. 
immerhin lief es mal, und das Board ist für genau dieses Aufgabe gebaut 
worden.

Frage: hat jemand das am laufen ?

Anbei die Quellen.

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Ich schlag mich jetzt schon eine ganze Weile mit dem CS43L22 rum, 
allerdings nicht mit dem Onboard Mikro, das kann ich für mein Projekt 
(4-Spur Multitracker Retrofit) nicht brauchen. Aber es lohnt sich, das 
ganze schrittweise anzugehen, das fängt mit dem richtigen Clocksetup an.
Ich wühle mich nicht durch dein TAR.GZ, aber es ist wichtig, die I2S 
Clock erneut einzustellen, da sie von vielen Startup Codes falsch oder 
gar nicht gesetzt wird, und man sollte das Setup dann auch überprüfen.
Man beachte auch die STM Fussnote, die Clock für I2S auf 2 Mhz statt auf 
1 MHz zu setzen, da das Jittern so weniger wird.
Ausserdem enthält der I2C Startup Code für den Cirrus Chip einige 
undokumentierte Sequenzen, ohne die es nicht geht. Der Chip sollte vor 
allem auch resetted werden.
Ohne eine serielle Konsole wäre ich dem Mist übrigens nicht auf die Spur 
gekommen, bau dir sowas am besten mit ein.
Uwe B. hat das meiste des CS43 Setup in seinem Code schon drin, hier ein 
Auszug:
1
/* now lets init the Cirrus I2S DAC */
2
/* first the I2C setup  */
3
uint16_t MS_Init_CS42L22(void) {
4
uint16_t error = 0;
5
    GPIO_SetBits(DRIVE_GPIO_PORT,CS43_RST_PIN);
6
    Delay(50);  // lets settle the chip
7
  error = I2C_WriteByte(CODEC_I2C_ADRESS,0x02, 0x01); // power off
8
  if (error) return error;
9
  error = I2C_WriteByte(CODEC_I2C_ADRESS,0x00, 0x99); //  init sequence by datasheet
10
  if (error) return error;
11
  error = I2C_WriteByte(CODEC_I2C_ADRESS,0x47, 0x80); //  undocumented registers
12
  if (error) return error;
13
  error = I2C_WriteByte(CODEC_I2C_ADRESS,0x32, 0xBB); //  have to be written
14
  if (error) return error;
15
  error = I2C_WriteByte(CODEC_I2C_ADRESS,0x32, 0x3B); //
16
  if (error) return error;
17
  error = I2C_WriteByte(CODEC_I2C_ADRESS,0x00, 0x00); //  register 0 is not in the datasheet
18
  if (error) return error;
19
  return 0;
20
}
Sodann geht es weiter mit dem normalen dokumentierten I2C Setup, das ich 
hier jetzt nicht schreibe, siehe dazu das Datenblatt des Cirrus.
Ok, spätestens jetzt muss die I2S Clock konfiguriert werden:
1
void I2S_PLL_Config(uint16_t N,uint16_t R) {
2
    // Set PLL Clock for I2S
3
    RCC_PLLI2SCmd(DISABLE);
4
    RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S);
5
//    RCC->CFGR &= ~RCC_CFGR_I2SSRC;
6
    /* Configure PLLI2S */
7
    RCC_PLLI2SConfig(N,R);
8
    /* Enable PLLI2S */
9
    RCC_PLLI2SCmd(ENABLE);
10
    /* Wait till PLLI2S is ready */
11
    while (RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY)==RESET){};
12
//     BlinkLED(1);
13
}
Das hat mich beinahe wahnsinnig gemacht. Alle Leute behaupteten, das 
hier PLL_N = 271 und PLL_R = 2 sein sollten - weit daneben bei mir. Für 
meine gewünschte Samplerate von 48kHz waren
1
uint16_t PLL_N = 129,PLL_R = 3;
Man muss dazu sagen, das ich alle I2S Geräte als Slaves mit Masterclock 
vom STM32F4 betreibe.
So, als nächstes stellte sich heraus, das die Init Funktion von CMSIS 
'vergass', das M_CLK Output Bit zu setzen, also:
1
#define I2SDIV 0x0103;
2
  /* now set the parameters for the I2S Interface itself */
3
    I2S_StructInit(&I2S_InitStructure);
4
    I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
5
    I2S_InitStructure.I2S_Standard = I2S_STANDARD;
6
    I2S_InitStructure.I2S_MCLKOutput = ENABLE;
7
    I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_48k;
8
    I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
9
    I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
10
    I2S_Init(SPI3,&I2S_InitStructure);
11
// set the MCLK Output enable bit and prescaler, cause the initfunction is bugged
12
    SPI3->I2SPR = I2S_MCLKOutput_Enable | I2SDIV;
Nach den ganzen Problemen hatte ich erstmal gründlich die Lust verloren 
und habe nur noch den TX Empty Interrupt fürs SPI3 konfiguriert 
konfiguriert, um Samples aus dem Speicher zu spielen, damit wenigstens 
erstmal was zu hören ist. Wenn ich wieder Bock habe, geht es an die DMA.
1
// Configure the I2S Tx empty IRQ
2
    NVIC_InitStructure.NVIC_IRQChannel = SPI3_IRQn;
3
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0a;
4
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
5
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
6
    NVIC_Init(&NVIC_InitStructure);
7
    SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE,ENABLE);
8
    I2S_Cmd(SPI3,ENABLE);
Ich benutze als ADC einen CS5331 auf I2S2, der so gut wie keinen Setup 
braucht, sondern lediglich eine Masterclock. Die 12 bitter des STM32 
klingen nicht so schlecht, haben aber Störgeräusche drauf, was mich 
nicht wundert bei dem kleinen Die des STM32.

Als Test habe ich in ein externes include eine 48 Byte lange 
Sinustabelle mit 16 bit Tiefe gepackt, die mir der Cirrus abspielt, so 
bin ich dem Samplerate Kram auf die Spur gekommen. Im Moment spielt er 
nun 2 Buffer für Kanal 1 und Kanal 2, die per ISR vom CS5331 ADC gefüllt 
werden - ein 2 Kanal Echogerät, wenn man so will.

Mit dem Mikro musst du dich jetzt selber rumschlagen :-P

: Bearbeitet durch User
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.