Forum: Mikrocontroller und Digitale Elektronik STM32F103 und I2S Probleme


von Stefan S. (chiefeinherjar)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

seit längerem hänge ich bei der Inbetriebnahme eines 24-Bit Audio ADC 
fest; konkret handelt es sich dabei um einen PCM1808.
Mein verwendeter Mikrocontroller ist ein STM32F103RCT6.

Mein Problem liegt darin, dass ich zwar Daten vom ADC lesen kann, diese 
Daten aber offenbar falsch sind. Entweder erhalte ich haufenweise 0 oder 
16777181, manchmal auch nur wirre und unzusammenhängende Daten.
Hier ein Beispiel:
1
16774477, 0, 16777096, 0, 16777205, 0, 16777136, 0, 69, 0, 16777208, 0, 77, 0, 128, 0, 197, 0, 16777048, 0, 16776997, 0, 96, 0, 205, 0, 16777144, 0, 16777085, 0, 152, 0, 85, 0, 16777120, 0, 133, 0, 16777136, 0, 16777189, 0, 16777152, 0, 16777141, 0, 16777200, 0, 53, 0, 0, 0, 85, 0, 120, 0, 16777181, 0, 16777200, 0, 37, 0, 72, 0
Ich habe das I2S-Interface zum Einen per Hand, zum Anderen in meiner 
Verzweiflung per CubeMX konfiguriert, um eventuelle Fehlinterpretationen 
des DaBla auszuschließen; das Ergebnis ist das gleiche.

Ich habe 48kHz Abtastrate, I2S-Standard-Format und Master-Clock-Output, 
da der STM32 der Master sein soll (Master-Receive-Only-Modus, 24 Bit in 
32 Bit langen Paketen).

Die Signale selbst sehen gut aus, kaum nennenswerte Überschwinger bzw. 
Klingeln. Die Frequenzen passen auch (L/R-Clock bei knapp 48kHz, 
Master-Clock bei ca. 12,2 MHz, Bit-Clock bei 3 MHz).
Bei Bedarf kann ich Bilder vom Oszi hochladen.

Ich habe als Zip-Dateien jeweils die Projektordner für das STM-Studio 
sowie den Schaltplan angehängt.
Nachfolgend mein eigener Code mit CMSIS. Zu Debug-Zwecken habe ich die 
Optimierung deaktiviert und mir jeweils am Ende der 64 Durchläufe die 
Inhalte des Arrays angeschaut. Das ganze soll natürlich, wenn die 
Schnittstelle funktioniert, weiterverarbeitet werden.

Ich habe das Gefühl, IRGENDETWAS völlig offensichtliches übersehen zu 
haben; ich komme nur nicht drauf... Vielleicht findet ihr ja meinen 
Fehler?
1
#include "stm32f1xx.h"
2
3
#define BUFFER_LENGTH 64
4
5
#define FMT_SET() GPIOB->ODR |= GPIO_ODR_ODR2;
6
#define FMT_CLR() GPIOB->ODR &= ~(GPIO_ODR_ODR2);
7
#define MD0_SET() GPIOB->ODR |= GPIO_ODR_ODR10;
8
#define MD1_SET() GPIOB->ODR |= GPIO_ODR_ODR11;
9
#define MD0_CLR() GPIOB->ODR &= ~GPIO_ODR_ODR10;
10
#define MD1_CLR() GPIOB->ODR &= ~GPIO_ODR_ODR10;
11
12
      
13
void SysTick_Handler(void){
14
15
}
16
17
void GPIO_Init(){
18
  GPIOB->CRL |= GPIO_CRL_MODE0_0 | GPIO_CRL_MODE1_0 | GPIO_CRL_MODE2_0;
19
  GPIOB->CRH |= GPIO_CRH_MODE10_0 | GPIO_CRH_MODE11_0;
20
  GPIOB->CRL &= ~(GPIO_CRL_CNF0_0 | GPIO_CRL_CNF1_0 | GPIO_CRL_CNF2_0);
21
  GPIOB->CRH &= ~(GPIO_CRH_CNF10_0 | GPIO_CRH_CNF11_0);
22
}
23
24
25
void SysInit(void){
26
  FLASH->ACR = FLASH_ACR_PRFTBE;
27
  while(!(FLASH->ACR & FLASH_ACR_PRFTBS));
28
  FLASH->ACR |= FLASH_ACR_LATENCY_1;
29
  RCC->CR |= RCC_CR_HSEON;
30
  while(!(RCC->CR & RCC_CR_HSERDY));
31
  RCC->CFGR |= RCC_CFGR_PLLSRC;
32
  RCC->CFGR |= RCC_CFGR_PLLMULL9;
33
  RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
34
  RCC->CR |= RCC_CR_CSSON;
35
  RCC->CR |= RCC_CR_PLLON;
36
  while(!(RCC->CR & RCC_CR_PLLRDY));
37
  RCC->CFGR |= RCC_CFGR_SW_PLL;
38
  while(!(RCC->CFGR & RCC_CFGR_SWS_PLL));
39
  RCC->CFGR |= RCC_CFGR_MCOSEL_PLL_DIV2;
40
  RCC->APB2ENR |= RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN;
41
  GPIOA->CRH |= GPIO_CRH_CNF8_1;
42
  GPIOA->CRH &= ~GPIO_CRH_CNF8_0;
43
  GPIOA->CRH |= GPIO_CRH_MODE8_1 | GPIO_CRH_MODE8_0;
44
  SysTick_Config(7200000);
45
  GPIOC->CRL |= GPIO_CRL_MODE4_0 | GPIO_CRL_MODE5_0;
46
  GPIOC->CRL &= ~(GPIO_CRL_CNF4_0 | GPIO_CRL_CNF5_0);
47
  GPIOC->ODR |= GPIO_ODR_ODR4;
48
}
49
50
void I2S_Init(){
51
  RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
52
/*  Procedure
53
  1. Select the I2SDIV[7:0] bits in the SPI_I2SPR register to define the serial clock baud
54
  rate to reach the proper audio sample frequency. The ODD bit in the SPI_I2SPR
55
  register also has to be defined.**/
56
  SPI2->I2SPR = (SPI_I2SPR_MCKOE | 3);
57
58
  /*
59
  2. Select the CKPOL bit to define the steady level for the communication clock. Set the
60
  MCKOE bit in the SPI_I2SPR register if the master clock MCK needs to be provided to
61
  the external DAC/ADC audio component (the I2SDIV and ODD values should be
62
  computed depending on the state of the MCK output, for more details refer to
63
  Section 25.4.3).*/
64
  SPI2->I2SCFGR &= ~SPI_I2SCFGR_CKPOL;
65
  /*
66
  3. Set the I2SMOD bit in SPI_I2SCFGR to activate the I2S functionalities and choose the
67
  I2S standard through the I2SSTD[1:0] and PCMSYNC bits, the data length through the
68
  DATLEN[1:0] bits and the number of bits per channel by configuring the CHLEN bit.
69
  Select also the I2S master mode and direction (Transmitter or Receiver) through the
70
  I2SCFG[1:0] bits in the SPI_I2SCFGR register.*/
71
  SPI2->I2SCFGR |= SPI_I2SCFGR_I2SMOD;
72
//  SPI2->I2SCFGR |= SPI_I2SCFGR_I2SSTD_0;
73
  SPI2->I2SCFGR |= SPI_I2SCFGR_DATLEN_0;
74
  SPI2->I2SCFGR |= SPI_I2SCFGR_I2SCFG;
75
76
77
  /*4. If needed, select all the potential interruption sources and the DMA capabilities by
78
  writing the SPI_CR2 register.
79
  */
80
  //<to do>
81
  /*
82
  5. The I2SE bit in SPI_I2SCFGR register must be set.
83
  WS and CK are configured in output mode. MCK is also an output, if the MCKOE bit in
84
  SPI_I2SPR is set.*/
85
86
  /*
87
   * Pin B12 -> I2S2_WS; Alternate function, output, 50MHz
88
   * Pin B13 -> I2S2_CK; Alternate function, output, 50MHz
89
   * Pin B15 -> I2S2_SD; Input (Reset state)
90
   * Pin C6  -> I2S2_MCK; Alternate function, output, 50MHz
91
   */
92
  GPIOB->CRH &= ~(GPIO_CRH_CNF12 | GPIO_CRH_CNF13);
93
  GPIOB->CRH |= GPIO_CRH_MODE12 | GPIO_CRH_MODE13;
94
  GPIOB->CRH |= GPIO_CRH_CNF12_1 | GPIO_CRH_CNF13_1;
95
  GPIOC->CRL &= ~GPIO_CRL_CNF6;
96
  GPIOC->CRL |= GPIO_CRL_CNF6_1;
97
  GPIOC->CRL |= GPIO_CRL_MODE6_0 | GPIO_CRL_MODE6_1;
98
99
  MD0_CLR();
100
  MD1_CLR();
101
  FMT_CLR();
102
  SPI2->I2SCFGR |= SPI_I2SCFGR_I2SE;
103
return;
104
}
105
106
uint32_t I2S_ReadData(){
107
  //uint16_t data_received = 0;
108
  uint32_t data_complete = 0;
109
  while(!(SPI2->SR & SPI_SR_RXNE));
110
  data_complete = SPI2->DR;
111
  return data_complete;
112
}
113
114
int main(void)
115
{
116
  SysInit();
117
  GPIO_Init();
118
  I2S_Init();
119
  uint32_t data_received[BUFFER_LENGTH] = {0};
120
  uint16_t data_temp = 0;
121
  for(;;){
122
    for(uint8_t i = 0; i < BUFFER_LENGTH; i = i+2){
123
      data_temp = I2S_ReadData();
124
      data_received[i] = data_temp << 8;
125
      data_temp = I2S_ReadData();
126
      data_received[i] |= data_temp >> 8;
127
    }
128
    GPIOC->ODR ^= GPIO_ODR_ODR4;
129
  }
130
}

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.