STM Урок 48. USB DEVICE AUDIO. Часть 2



Урок 48

 

Часть 2

 

USB DEVICE AUDIO

 

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

В файле audioplay.c напишем функции задержки в микросекундах. Данной функцией мы пользуемся часто

 

//—————————————————————

__STATIC_INLINE void DelayMicro(__IO uint32_t micros)

{

        micros *=(SystemCoreClock / 1000000) / 5;

        while (micros—);

}

//—————————————————————

void Error(void)

 

В функциях AudioOut_Init и cs43l22_Init заменим функции задержек HAL_Delay на функции DelayMicro, так как с функциями задержек HAL у меня происходили зависания и не работала отладка

 

  DelayMicro(5000);

  HAL_GPIO_WritePin(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, GPIO_PIN_SET);

  DelayMicro(5000);

 

Отключим оптимизацию для лучшей отладки

 

image19

 

Скомпилируем код и проверим, считан ли у нас идентификатор аудио ЦАП и тот ли именно он считан. Проверим мы это с помощью отладки. Установим точку останова, запустим отладку, дойдём до точки останова, а затем идем шагами. Если всё нормально считано, то попадём в отмеченное на рисунке место

 

image20

 

 

Дальше вставим ещё строку в инициализацию

 

  counter += CODEC_IO_Write(DeviceAddr, 0x04, OutputDev);

  /* Clock configuration: Auto detection */  

  counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x81);

  /* Set the Slave Mode and the audio Standard */  

  counter += CODEC_IO_Write(DeviceAddr, 0x06, CODEC_STANDARD);

 

Тем самым мы в ЦАПе включаем автоопределение скорости, также делитель на 2

 

image21

image07

 

 

Добавим в файле audioplay.c в функцию cs43l22_Stop ещё один входной аргумент

 

//——————————————————

uint32_t cs43l22_Stop(uint16_t DeviceAddr, uint32_t CodecPdwnMode)

{

Исправим функцию AudioPlay_Stop

uint8_t AudioPlay_Stop(uint32_t Option)

{

  uint8_t ret = AUDIO_OK;

         /* Call Audio Codec Stop function */

  if(cs43l22_Stop(AUDIO_I2C_ADDRESS, Option) != 0)

  {

    ret = AUDIO_ERROR;

  }

  if(ret == AUDIO_OK)

  {

    if(Option == CODEC_PDWN_HW)

    {

      /* Wait at least 100us */

      DelayMicro(2000);

    }

    /* Stop DMA transfer of PCM samples towards the serial audio interface */  

    if (HAL_I2S_DMAStop(&hi2s3)!= HAL_OK)

    {

      ret = AUDIO_ERROR;

    }

        }

  /* Return AUDIO_OK when all operations are correctly done */

  return ret;

}

//——————————————————

 

В файл audioplay.h добавим прототип данной функции

 

uint8_t AudioOut_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq);

uint8_t AudioPlay_Stop(uint32_t Option);

 

Вызовем данную функцию в файле usbd_audio_if.c в определенном обработчике

 

static int8_t AUDIO_DeInit_FS(uint32_t options)

{

  /* USER CODE BEGIN 1 */

  AudioPlay_Stop(CODEC_PDWN_SW);

  return (USBD_OK);

  /* USER CODE END 1 */

}

 

Теперь в файле audioplay.c изменим вызов функции cs43l22_Play

 

uint32_t cs43l22_Play(uint16_t DeviceAddr, uint16_t* pBuffer, uint16_t Size)

{

 

Вставим две функции следующего содержания

 

//——————————————————

uint8_t AudioPlay_Play(uint16_t* pBuffer, uint32_t Size)

{

  uint8_t ret = AUDIO_OK;

        if(cs43l22_Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0)

        {

                Error();

    ret = AUDIO_ERROR;

        }

  if(ret == AUDIO_OK)

        {

    if (HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE))!= HAL_OK)

    {

                        Error();

      ret = AUDIO_ERROR;

    }

        }

  return ret;

}

//——————————————————

void AudioPlay_ChangeBuffer(uint16_t *pData, uint16_t Size)

{

  HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t*) pData, Size);

}

//——————————————————

 

Ну здесь всё стандартно, я думаю и объяснять нечего.

Вставим прототипы функций в файл audioplay.h

 

uint8_t AudioPlay_Stop(uint32_t Option);        

uint8_t AudioPlay_Play(uint16_t* pBuffer, uint32_t Size);

void AudioPlay_ChangeBuffer(uint16_t *pData, uint16_t Size);

 

В файле usbd_audio_if.c в обработчике вставим вызовы функций

 

static int8_t AUDIO_AudioCmd_FS (uint8_t* pbuf, uint32_t size, uint8_t cmd)

{

  /* USER CODE BEGIN 2 */

  switch(cmd)

  {

    case AUDIO_CMD_START:    

    AudioPlay_Play((uint16_t *)pbuf, size);

    break;

 

    case AUDIO_CMD_PLAY:  

   AudioPlay_ChangeBuffer((uint16_t *)pbuf, size);

    break;        

  }

  return (USBD_OK);

  /* USER CODE END 2 */

 

}

 

В следующей части нашего урока мы мы закончим изучение данной темы и услышим работу написанной нашими руками звуковой карты.

 

 

Предыдущая часть Программирование МК STM32 Следующая часть

 

Техническая документация на Аудио ЦАП CS43L22

 

 

Купить отладочную плату можно здесь STM32F4-DISCOVERY

 

 

Смотреть ВИДЕОУРОК

 

STM32 USB DEVICE AUDIO

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*