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 | }
|