STM32F4RGT6 + microSD + CS4344

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Аватара пользователя
Andrey27
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс май 11, 2014 23:24:21

STM32F4RGT6 + microSD + CS4344

Сообщение Andrey27 »

Всем привет! Тренировался где-то пол года на STM32f4 discovery. Решил сделать свою платку, для проигрывания качественных wav файлов (16bit stereo 48000kHz). Вопрос, правильно ли я все подключил, номиналы резисторов, конденсаторов. Схема:Изображение
Аватара пользователя
Andrey27
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс май 11, 2014 23:24:21

Re: STM32F4RGT6 + microSD + CS4344

Сообщение Andrey27 »

Может кому интересно будет.Перепроверил еще пару раз схему, решил сделать. Начертил платку, протравил, впаял, прошил (просто моргать светодиодом) и все заработало:

Изображение

Изображение

Изображение

Изображение

Изображение

Изображение

Изображение


Теперь буду разбираться с SDIO и I2S.
Вложения
STM32F405RGT6.rar
(66.88 КБ) 413 скачиваний
Аватара пользователя
Andrey27
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс май 11, 2014 23:24:21

Re: STM32F4RGT6 + microSD + CS4344

Сообщение Andrey27 »

Разобрался с SDIO, проиграл аудио на встроенном в мк 12бит ЦАП, а с I2S возникли проблемы. Шум, щелчки при воспроизведении через CS4344. Может кто работал с I2S посмотрите код где ошибка. Мне кажется что ошибка в обработчике прерывания таймера при посылке данных ЦАП. Ниже осцилограмма I2S, настройки тактирования и код. Кстати при частоте дискретизации 44100Гц частота переключения каналов LRCK тоже должна быть 44100Гц ? У меня почему то 22.06Кгц. И тактирование должно быть 44100*16*2 = 1411200Гц а у меня 1.333Мгц.

Изображение



Изображение



Код: Выделить всё

#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32_ub_fatfs.h"
#include "stm32f4xx_dac.h"
#include "stm32f4xx_tim.h"
#include "stm32f4xx_spi.h"

    FIL myFile;              // Файл
    uint8_t buff[1024];      // Буфер
    volatile uint16_t n = 0; // Счетчик

void Init_GPIO(void)
{
   GPIO_InitTypeDef GPIO;

   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC, ENABLE); // Вкл. тактирование В, С
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);                          // Вкл. тактирование DAC
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);                          // Вкл. тактирование TIM6
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);                         // Вкл. тактирование SPI2
   RCC_PLLI2SCmd(ENABLE);                                                       // Вкл. тактирование I2S

   GPIO.GPIO_Mode = GPIO_Mode_AF;
   GPIO.GPIO_OType = GPIO_OType_PP;
   GPIO.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_12;     // GPIOB Pin_10 - SCLK,  Pin_12 - LRCK
   GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
   GPIO.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(GPIOB, &GPIO);

   GPIO.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_6;      // GPIOC Pin_3 - SDIN,  Pin_6 - MCLK
   GPIO_Init(GPIOC, &GPIO);

   GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_SPI2);     // Альтернатива I2S
   GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_SPI2);
   GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_SPI2);
   GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_SPI2);

   GPIO.GPIO_Pin = GPIO_Pin_5;                  // Светодиод
   GPIO.GPIO_Mode = GPIO_Mode_OUT;
   GPIO.GPIO_Speed = GPIO_Speed_2MHz;
   GPIO.GPIO_OType = GPIO_OType_PP;
   GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
   GPIO_Init(GPIOB, &GPIO);
}

void Init_Timer6(void)  // Насторйка таймера на 44100 Гц
{
   TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;

   TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
   TIM_TimeBaseStructure.TIM_Period        = 1904;
   TIM_TimeBaseStructure.TIM_Prescaler     = 0;
   TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
   TIM_TimeBaseStructure.TIM_CounterMode   = TIM_CounterMode_Up;
   TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
   TIM_Cmd(TIM6, ENABLE);

   TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
   NVIC_EnableIRQ(TIM6_DAC_IRQn);                 // Прерывание 44100 Гц
}

void Init_I2S(void)  // Настройка I2S
{
   I2S_InitTypeDef I2S;

   I2S.I2S_AudioFreq = I2S_AudioFreq_44k;
   I2S.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
   I2S.I2S_DataFormat = I2S_DataFormat_16b;
   I2S.I2S_Mode = I2S_Mode_MasterTx;
   I2S.I2S_Standard = I2S_Standard_Phillips;
   I2S.I2S_CPOL = I2S_CPOL_High;
    I2S_Init(SPI2, &I2S);
    // RCC_PLLI2SConfig(192, 2);
    I2S_Cmd(SPI2, ENABLE);
}

void TIM6_DAC_IRQHandler(void)
{
    uint16_t R, L;

    TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
    R = (buff[n+1] << 8) + buff[n] + 0x8000;
    L = (buff[n+3] << 8) + buff[n+2] + 0x8000;
    // DAC_SetChannel1Data(DAC_Align_8b_R, buff[n]);        // Работает ++++
    // DAC_SetChannel2Data(DAC_Align_8b_R, buff[n+1]);
    // n = n + 2;
    // DAC_SetChannel1Data(DAC_Align_12b_L, R);             // Работает +++++
    // DAC_SetChannel2Data(DAC_Align_12b_L, L);
    if (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)) SPI_I2S_SendData(SPI2, R); // Не работает
    if (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)) SPI_I2S_SendData(SPI2, L);
    n = n + 4;
    if (n > 1023) n = 0;
}

void Play(void) // Чтение с карты памяти в буфер кольцо.
{
    uint32_t bt = 0;
    uint8_t p = 0;

    while(1)
     {
      if (!p && n > 511)  // Если первая половина буфера проиграна то...
       {
        UB_Fatfs_ReadBlock(&myFile, &buff[0], 512, &bt); // Заполняем первую часть.
        p = 1;
        if (bt < 512) break;           // Конец файла.
       }
       if (p && n < 512)  // Если вторая половина буфера проиграна то...
       {
        UB_Fatfs_ReadBlock(&myFile, &buff[512], 512, &bt); // Заполняем вторую часть.
        p = 0;
        if (bt < 512) break;          // Конец файла.
       }
     }
}

int main(void)
{
    uint32_t b = 0;

    SystemInit();  // HSE 8Мгц, PLL_M  8, PLL_N 336, PLL_P 2, PLL_Q 7, 168Мгц тактовая частота.
    Init_GPIO();
    Init_Timer6();
    Init_I2S();

    //DAC_Cmd(DAC_Channel_1, ENABLE);
    //DAC_Cmd(DAC_Channel_2, ENABLE);

    GPIO_ResetBits(GPIOB, GPIO_Pin_5);

    UB_Fatfs_Init();

    if(UB_Fatfs_CheckMedia(MMC_0) == FATFS_OK)
    {
     if(UB_Fatfs_Mount(MMC_0) == FATFS_OK)
     {
      if(UB_Fatfs_OpenFile(&myFile, "0:/2.wav", F_RD) == FATFS_OK)
       {
        UB_Fatfs_ReadBlock(&myFile, &buff[0], 512, &b);

        GPIO_SetBits(GPIOB, GPIO_Pin_5);
        Play();
        GPIO_ResetBits(GPIOB, GPIO_Pin_5);

       //DAC_Cmd(DAC_Channel_1, DISABLE);
       //DAC_Cmd(DAC_Channel_2, DISABLE);
        UB_Fatfs_CloseFile(&myFile);
       }
        UB_Fatfs_UnMount(MMC_0);
     }
    }

    while(1)
    {

    }
}
Аватара пользователя
Andrey27
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс май 11, 2014 23:24:21

Re: STM32F4RGT6 + microSD + CS4344

Сообщение Andrey27 »

Все решил проблему. Надо было непрерывно подавать данные на ЦАП а таймер должен работать миннимум на удвоенной частоте дискритизации (у меня таймер настроен на 500кгц).

Код: Выделить всё

void TIM6_DAC_IRQHandler(void)
{
    if (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE))
     {
       SPI_I2S_SendData(SPI2, R);
       R = (buff[n+1] << 8) + buff[n];
       n = n + 2;
       if (n > 1023) n = 0;
     }
    TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
}

Вот так должен выглядеть нормальный I2S:

Изображение

murkot
Первый раз сказал Мяу!
Сообщения: 22
Зарегистрирован: Чт фев 14, 2013 16:28:36

Re: STM32F4RGT6 + microSD + CS4344

Сообщение murkot »

...а про DMA вы слышали?
Аватара пользователя
Andrey27
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс май 11, 2014 23:24:21

Re: STM32F4RGT6 + microSD + CS4344

Сообщение Andrey27 »

Слышал только название DMA, но пока не знаю как и для чего им пользоваться. STM микроконтроллеры недавно изучать начал, на простеньких уроках + stm32discovery. Спасибо за подсказку, буду разбираться с DMA.
Ответить

Вернуться в «ARM»