STM32F4RGT6 + microSD + CS4344
Re: STM32F4RGT6 + microSD + CS4344
Может кому интересно будет.Перепроверил еще пару раз схему, решил сделать. Начертил платку, протравил, впаял, прошил (просто моргать светодиодом) и все заработало:
Теперь буду разбираться с SDIO и I2S.
Теперь буду разбираться с SDIO и I2S.
- Вложения
-
- STM32F405RGT6.rar
- (66.88 КБ) 413 скачиваний
Re: STM32F4RGT6 + microSD + CS4344
Разобрался с 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)
{
}
}
Re: STM32F4RGT6 + microSD + CS4344
Все решил проблему. Надо было непрерывно подавать данные на ЦАП а таймер должен работать миннимум на удвоенной частоте дискритизации (у меня таймер настроен на 500кгц).
Вот так должен выглядеть нормальный I2S:
Код: Выделить всё
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:
Re: STM32F4RGT6 + microSD + CS4344
...а про DMA вы слышали?
Re: STM32F4RGT6 + microSD + CS4344
Слышал только название DMA, но пока не знаю как и для чего им пользоваться. STM микроконтроллеры недавно изучать начал, на простеньких уроках + stm32discovery. Спасибо за подсказку, буду разбираться с DMA.