Перейти к содержанию
    

STM32F103VET6 + DAC + DMA + SDIO + FATFS = WAV

Ребята помогите! Не могу воспроизвести wav с карточки.

Хочу сказать фразу по нажатию кнопки.

Карта читается.

Проблема то ли с ЦАП-ом, то ли выводом данных. В общем лыжи наглухо в асфальте.

Вот инит ЦАПа:

void Init_Sound(void)
{
	DAC_InitTypeDef DAC_InitStructure;
  DMA_InitTypeDef DMA_InitStructure;
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  GPIO_InitTypeDef		   GPIO_InitStructure;

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC | RCC_APB1Periph_TIM6, ENABLE);

  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4;  
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseStructure.TIM_Period = 72-1;   //
  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_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);

  DMA_DeInit(DMA2_Channel3);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&DAC->DHR8R1;	 
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32) &WAVBuffer[0];
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  DMA_InitStructure.DMA_BufferSize =512;  
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA2_Channel3, &DMA_InitStructure);

  DMA_Cmd(DMA2_Channel3, ENABLE);

  DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = 0;
  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
  DAC_Init(DAC_Channel_1, &DAC_InitStructure);

  DAC_Cmd(DAC_Channel_1, ENABLE);

  DAC_DMACmd(DAC_Channel_1, ENABLE);

  TIM_Cmd(TIM6, DISABLE);
}

 

Дальше в основном цикле.

 

if(Kn_a==1)    // Kn_a находится в прерывании
{
   Init_Sound();
   load_header();   // Здесь читаются заголовки WAV и настраивается таймер
   sound();
   Kn_a=0;
}

 

А вот с функцией sound(); наверное проблемы.

 

void sound(void)
{
   while(1)
      {
         TIM_Cmd(TIM6, ENABLE);
      while(!(DMA2->ISR & DMA_ISR_HTIF3)) {}  

     f_read (&fsrc, &WAVBuffer[0], 256, &rb);
       DAC_SetChannel1Data(DAC_Align_8b_R, WAVBuffer[0]);
   

     if(rb < 256) {TIM_Cmd(TIM6, DISABLE); break;}  

     while(!(DMA2->ISR & DMA_ISR_TCIF3)) {}

     f_read (&fsrc, &WAVBuffer[256], 256, &rb);
       DAC_SetChannel1Data(DAC_Align_8b_R, WAVBuffer[256]);

     if(rb < 256) {TIM_Cmd(TIM6, DISABLE); break;} 
       }
}

 

В динамике треск и писк.

В общем мозги кипят.

Прошу помощи, кто знает. Нужно проиграть мелодию с карточки.

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вначале научитесь хотя-бы простой тональный сигнал на ЦАП выводить без всяких WAV.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Совет, конечно, хороший.

Я с этого начинал.

Вывел на динамик синус из таблицы.

Дело в другом.

 

Карта читается - я из нее вывожу картинку на ТФТ.

 

Сегодня записал на карту синус и попробовал вывести. И не получилось.

Вот посмотрите правильно или нет?

f_lseek(&fsrc, 44);                                      // переходим на данные

while(1) 
{
f_read (&fsrc, &WAVBuffer[0], 256, &rb);        // загружаем первую часть буфера
if(rb < 256) { break;} 
while(!(DMA2->ISR & DMA_ISR_HTIF3)) {}     // ждем флаг
DMA2->IFCR |= DMA_ISR_HTIF3;                  // сбросить флаг

f_read (&fsrc, &WAVBuffer[256], 256, &rb);   // загружаем вторую часть буфера
if(rb < 256) { break;}
while(!(DMA2->ISR & DMA_ISR_TCIF3)) {}    // ждем флаг
DMA2->IFCR |= DMA_ISR_HTIF3;                 //сбросить флаг
}

Если что то не так, или все не так, не надо сразу лицом в грязь.
Просто подскажите как правильно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сегодня записал на карту синус и попробовал вывести. И не получилось.

 

Я делал не так, закольцовывал дма буфер, с автоперезагрузкой, ставил флаг сработки на половине буфера и начале, дма в режиме прерывания, а в программе ждал сработки флагов, чтоб заполнить высвободившуюся часть буфера и т.д.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А можно по подробнее с настройками?

 

Завтра гляну, если не забыл, где там все было :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В общем записал на карту синус (сформированный в программе Audacity 1кгц, 8 бит)

Начинаю читать, на экране осциллографа какой то кривой прямоугольник валит.

Вот настройка с выводом. Что не так? Прошу помощи.

void Init_Sound(void)
{   
/*   const uint16_t sinus_12bit[180]={
2048, 2119, 2191, 2262, 2333, 2404, 2474, 2543, 2613, 2681, 2748, 2815, 2881, 2946, 3009, 3072, 3133, 3193, 3252, 3309,
3364, 3418, 3471, 3521, 3570, 3617, 3662, 3705, 
3746, 3785, 3822, 3856, 3889, 3919, 3947, 3972, 3996, 4017, 4035, 4051, 4065, 4076, 4085, 4091, 4095, 4095, 4095, 4091,
4085, 4076, 4065, 4051, 4035, 4017, 3996, 3972, 
3947, 3919, 3889, 3856, 3822, 3785, 3746, 3705, 3662, 3617, 3570, 3521, 3471, 3418, 3364, 3309, 3252, 3193, 3133, 3072,
3009, 2946, 2881, 2815, 2748, 2681, 2613, 2543, 
2474, 2404, 2333, 2262, 2191, 2119, 2048, 1977, 1905, 1834, 1763, 1692, 1622, 1553, 1483, 1415, 1348, 1281, 1215, 1150,
1087, 1024, 963, 903, 844, 787, 732, 678, 625, 
575, 526, 479, 434, 391, 350, 311, 274, 240, 207, 177, 149, 124, 100, 79, 61, 45, 31, 20, 11, 5, 1, 0, 1, 5, 11, 20, 31, 45, 61, 
79, 100, 124, 149, 177, 207, 240, 274, 
311, 350, 391, 434, 479, 526, 575, 625, 678, 732, 787, 844, 903, 963, 1024, 1087, 1150, 1215, 1281, 1348, 1415, 1483, 1553,
1622, 1692, 1763, 1834, 1905, 1977 
};*/


  DAC_InitTypeDef DAC_InitStructure;
  DMA_InitTypeDef DMA_InitStructure;
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  GPIO_InitTypeDef		   GPIO_InitStructure;

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC | RCC_APB1Periph_TIM2, ENABLE);

  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4;  
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;   
  TIM_TimeBaseStructure.TIM_Period = (72000000/8000)-1;   
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);

  DMA_DeInit(DMA2_Channel3);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&DAC->DHR8R1;	   // (uint32_t) & DAC->DHR12R1
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32) &WAVBuffer[0];				 // sinus_12bit
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  DMA_InitStructure.DMA_BufferSize = 512;		// (sizeof(sinus_12bit) / sizeof(sinus_12bit[0])) 
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;   // DMA_PeripheralDataSize_HalfWord
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;		   // DMA_MemoryDataSize_HalfWord
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA2_Channel3, &DMA_InitStructure);

  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;
  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;		// DAC_OutputBuffer_Disable;
  DAC_Init(DAC_Channel_1, &DAC_InitStructure);

  DAC_DMACmd(DAC_Channel_1, ENABLE);
  DAC_Cmd(DAC_Channel_1, ENABLE);
  DMA_Cmd(DMA2_Channel3, ENABLE);

  TIM_Cmd(TIM2, ENABLE);		  //TIM_Cmd(TIM2, DISABLE);
}

 

void sound(void)
{
   
   disk_initialize(0);
   f_mount(0,&fs);
   f_open( &fsrc, "200.wav", FA_READ );
        f_read (&fsrc, &WAVBuffer, 512, &rb);
   f_lseek(&fsrc, 44);
   
   while(1) 
      {
         while(!(DMA2->ISR & DMA_ISR_HTIF3)) {}
         f_read (&fsrc, &WAVBuffer[0], 256, &rb);
         DMA2->IFCR |= DMA_ISR_HTIF3;   
         if(rb < 256) {TIM_Cmd(TIM2, DISABLE); break;} 
         
         while(!(DMA2->ISR & DMA_ISR_TCIF3)) {}
         f_read (&fsrc, &WAVBuffer[256], 256, &rb);   
         DMA2->IFCR |= DMA_ISR_HTIF3;
         if(rb < 256) {TIM_Cmd(TIM2, DISABLE); break;}
       }
}

 

Сама задача

 

static  void  Task_AudioOUT (void *p_arg)
{
    (void)p_arg;
    OSTimeDlyHMSM(0, 0, 2, 250);
    Status = SD_Init();
    Status = SD_GetCardInfo(&SDCardInfo);
    Status = SD_SelectDeselect((uint32_t) (SDCardInfo.RCA << 16));
    Status = SD_EnableWideBusOperation(SDIO_BusWide_4b);
    Status = SD_SetDeviceMode(SD_DMA_MODE); 
   
   while(1) 
  {   
      if(Kn_a==1)                  // Флаг кнопки меняется в прерывании
      {
         
         Init_Sound();
         
         sound();
         Kn_a=0;
      }
      
      OSTimeDlyHMSM(0, 0, 1, 250);
   }
}

 

 

С массива, который в функции Init_Sound(), синус на осциллографе хороший.

Как начинаю с карты читать записанный синус, лезет какой то бред.

Может подскажите , добрые люди, где запятая не там стоит :help:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так в wav-файле же не просто отсчёты для синуса, там ещё какой-то заголовок наверное?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хорошо. Вот так я читаю заголовок. Изменений никаких. В посте выше я просто переместил указатель на 44 байта.

 

static
DWORD load_header (void)	/* 0:Invalid format, 1:I/O error, >1:Number of samples */
{

DWORD ChunkID, SamplingRate, sz, Length;
char str[20];

//------------------------------------------------
f_mount(0,&fs);
f_open( &fsrc, "200.wav", FA_READ );
//------------------------------------------------
GUI_SetColor(GUI_WHITE);  //RED
GUI_SetFont(&GUI_Font24_1);
GUI_DispStringAt(">", 0, 50);

if (f_read(&fsrc, Buff, 12, &rb)) return 1;	/* Load file header (12 bytes) */
if (rb != 12 || LD_DWORD(Buff+8) != FCC('W','A','V','E')) return 0;
GUI_DispNextLine(); GUI_DispString("WAV File found:");

while(1) {
	f_read(&fsrc, Buff, 8, &rb);			/* Get Chunk ID and size */
	if (rb != 8) return 0;
	ChunkID = LD_DWORD(&Buff[0]);
	sz = LD_DWORD(&Buff[4]);		/* Chunk size */	
//------------------------------
	sprintf(str, "%ld", sz);
	GUI_DispNextLine();
	GUI_DispString(str); 
//------------------------------		
	switch (ChunkID) {	/* FCC */
		case fmt_chunk:					/* 'fmt ' chunk */
			if (sz > 100 || sz < 16) return 0;		/* Check chunk size */
			f_read(&fsrc, Buff, sz, &rb);					/* Get content */
			if (rb != sz) return 0;
			if (Buff[0] != 1) return 0;				/* Check coding type (PCM=1) */

			NumChannels = Buff[2];					/* Get channel flag */
			if (NumChannels != 1 && NumChannels != 2) 		/* Check channels (1/2) */
				return 0;
			if(NumChannels == 1) 	{GUI_DispNextLine(); GUI_DispString("Mono");}
			else if(NumChannels == 2) 	{GUI_DispNextLine(); GUI_DispString("Stereo");}				

			BitsPerSample = Buff[14];		/* Resolution flag */
			if (BitsPerSample != 8 && BitsPerSample != 16)	/* Check resolution (8/16) */
				return 0;
			if(BitsPerSample == 8) 	{GUI_DispNextLine(); GUI_DispString("8-bits");}   
			else if(BitsPerSample == 16) {GUI_DispNextLine(); GUI_DispString("16-bits");}				

			SamplingRate = LD_DWORD(Buff+4);
//				set_sampling_rate( SamplingRate );			/* Sampling freq */
			sprintf(str, "%ldHz", SamplingRate);
			GUI_DispNextLine(); GUI_DispString(str);
			break;

		case data_chunk:				/* 'data' chunk (start to play) */
			Length = sz / (SamplingRate * NumChannels * (BitsPerSample>>3) );	// length in seconds
			sprintf(str, "%ld:%2ld min", (Length/60), (Length%60));
			GUI_DispNextLine(); GUI_DispString(str);
			return sz;

		case LIST_chunk:				/* 'LIST' chunk (skip) */

		case fact_chunk:				/* 'fact' chunk (skip) */
			f_lseek(&fsrc, (fsrc.fptr + sz));			

			break;

		default :					 /* Unknown chunk (error) */
			return 0;
	}
}
//return 0;
}

 

и дальше

 

void sound(void)
{
f_read (&fsrc, &WAVBuffer[0], 512, &rb);
    
    while(1)   
        {
            while(!(DMA2->ISR & DMA_ISR_HTIF3)) {}
            f_read (&fsrc, &WAVBuffer[0], 256, &rb);
            DMA2->IFCR |= DMA_ISR_HTIF3;    
            if(rb < 256) {TIM_Cmd(TIM2, DISABLE); break;} 
            
            while(!(DMA2->ISR & DMA_ISR_TCIF3)) {}
            f_read (&fsrc, &WAVBuffer[256], 256, &rb);    
            DMA2->IFCR |= DMA_ISR_HTIF3;
            if(rb < 256) {TIM_Cmd(TIM2, DISABLE); break;}
         }
}

 

Исправил

while(1)

{

while(!(DMA2->ISR & DMA_ISR_HTIF3)) {}

f_read (&fsrc, &WAVBuffer[0], 256, &rb);

DMA2->IFCR |= DMA_ISR_HTIF3;

if(rb < 256) {TIM_Cmd(TIM2, DISABLE); break;}

 

while(!(DMA2->ISR & DMA_ISR_TCIF3)) {}

f_read (&fsrc, &WAVBuffer[256], 256, &rb);

DMA2->IFCR |= DMA_ISR_TCIF3; //

if(rb < 256) {TIM_Cmd(TIM2, DISABLE); break;}

}

 

Все равно на экране беспорядочные значения

WP20150430_9890935_17163602.jpg

Изменено пользователем loreal1970
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хорошо. Вот так я читаю заголовок. Изменений никаких. В посте выше я просто переместил указатель на 44 байта.

Ок. Значит, вы уверены, что у вас считываются именно отсчёты синуса?

Тогда следующее замечание: зачем вы изменили размер периферии? (DMA_PeripheralDataSize_HalfWord на DMA_PeripheralDataSize_Byte)

Ведь размер регистра ЦАП не изменяется.

А, понял. Регистр поменялся тоже.

Ну тогда не знаю... Попробуйте записать в файл прямо тот же синус, который работает, многократно. И считайте его. Чтобы исключить ошибки обработки wav.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так секундочку. Я чего то не понимаю.

В заголовке у меня получается

Сигнал моно, 16-бит, 8000Гц, размер и время.

 

 

Ребят! Может поделитесь рабочим примером чтения WAV с карты.

Что то совсем не получается.

В общем заголовок на экран вывожу.

А сами данные не получается вывести. Плиз.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так секундочку. Я чего то не понимаю.

В заголовке у меня получается

Сигнал моно, 16-бит, 8000Гц, размер и время.

 

 

Ребят! Может поделитесь рабочим примером чтения WAV с карты.

Что то совсем не получается.

В общем заголовок на экран вывожу.

А сами данные не получается вывести. Плиз.

Добавляйте к считанному с wav +0x8000 и сдвигайте на 4, чтоб получить 12 бит.

 

И непонятно как вы "разруливаете" ситуацию с тем, что данные в wav 16-битные?

В функциях чтения у вас 256 это байт?

 

А в DAC вы пишете байтами.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пусть функция загрузки данных в DAC - укладывает выходные данные и в память тоже. Много не надо, первых 20-30 байт (или слов?) достаточно.

Затем сравните первые 20-30 семплов из WAV файла, с тем что отправилось в DAC.

 

Вот например кусочек на 18 семплов из Audacity в формате "WAV signed 16 bit PCM", и те-же данные как их видно в WINHEXе.

На второй картинке график в Excel построенный по тем-же 16 битным значениям (с прибавлением + 0x8000, как предлагает adnega).

 

Проверьте у себя, как работает функция преобразования данных для DAC. Или выложите здесь для сравнения, что читаете из WAV файла и что пишете в DAC.

post-45309-1430565414_thumb.jpg

post-45309-1430565426_thumb.jpg

Изменено пользователем controller_m30

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Заголовок незачем читать, ели точно известно, в каком формате записан файл.

Но работая с 16и битным файлом, Вы не знаете, правильно ли задали смещение при чтении: быть может в выборку ЦАП у Вас попадает 1й байт из одного 16и битного значения и 2ой байт из следующго 16и битного значения, и поэтому на выходе ЦАП непонятная белиберда. Что бы исключить эту ошибку, запишите файл в 8и битном формате. И читайте его побайтно, побайтно отправляйте в ЦАП.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да ребята. Вы правы. WAV у меня 16 битный. А преобразование неправильное.

Я так понимаю?

1. Заводим буфер на (к примеру 1024 байт)

2. Настраиваем таймер на частоту выборки семплов.

3. В прерывании таймера читаем половину буфера (по счетчику), сдвигаем каждое uint16_t слово на >>4 (приводим к 12 битам)

4. Выкладываем в DAC (настроенный на 12 битный режим)

5. Далее вторая половинка буфера.

 

Такой вариант (с некоторыми изменениями приемлем), но в DMA есть хороший режим, т.е. прерывание на половине и конце буфера.

Осталось теперь соединить это в кучу.

Вроди бы просто. Но что то перемкнуло и не могу сдвинуться с места.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...