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



Урок 48

 

Часть 1

 

USB DEVICE AUDIO

 

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

 

Сегодня мы продолжим изучение нового интерфейса – шины I2S. И работать мы будем также, как и в прошлом уроке по I2S – с микросхемой CS43L22, установленной на плате STM32F4-DISCOVERY. Только в данном занятии мы попытаемся взять цифровой аудиопоток не из WAV-файла, а из ПК по шине USB, то есть мы попробуем из нашей платы создать звуковую карту. Звуковая карта получится, конечно, не полная, так как она будет работать только на воспроизведение (только в режиме ЦАП), но тем не менее, я думаю, работу с шиной I2S мы закрепим основательно, также коснёмся изучения другого класса USB – DEVICE Audio.

Свой проект мы создадим из старинного проекта, в котором не подключено ничего лишнего — TEST002, а назовём мы новый проект USB_DEVICE_AUDIO.

Откроем наш проект в Cube MX и произведём необходимые настройки.

Сначала выключим ненужные светодиоды, оставив только красный и зелёный.

 

image00

 

Включим саму шину I2S

 

image02

 

Ножки никакие не переопределяем. Оставим так как есть. Именно по этим ножкам и подключена микросхема Аудио ЦАП.

Отключим 6-й таймер

 

image01

 

Включим USB_OTG_FS в режим Device_Only

 

image04

 

В USB_DEVICE в разделе Class For FS IP выберем пункт Audio Device Class

 

image03

 

Для работы лапки RESET микросхемы нам будет ещё необходимо включить на выход и настроить данную лапку порта (PD4)

 

image17

image05 

 

В разделе «Clock Configuration» включим всё на максимум

 

image08

 

 

Внесем также некоторые корректировки в настройки I2S

 

image06

 

Также добавим и настроим DMA на шине I2S

 

image12

 

В USB Device увеличим частоту дискретизации

 

image09

 

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

 

image11

 

А так как управление микросхемой происходит в отличии от основного аудио-потока уже по шине I2C, то необходимо включить ещё и эту шину. Включим шину I2C1

 

image13

 

Лапку PB7 нужно будет переопределить на PB9. Я думаю, все уже умеют это делать. Сначала сбросим её, а затем переопределим

 

    image14image15

 

В Project -> Setting установим следующие настройки стека и кучи

 

image16

 

Сгенерируем проект для среды Keil, настроим программатор на авторезет и скомпилируем проект.

Добавим в проект файлы, предназначенные для работы со звуком, audioplay.c и audioplay.h из проекта I2S_AUDIO.

Подключим файл audioplay.c в дереве Application/User

Также добавим подключение данной нашей библиотеки в главный модуль main.h

 

#include «stm32f4xx.h»

#include «audioplay.h»

Удалим здесь следующую строку:

uint8_t tim6_counter;

 

 

Уберём полностью весь код из бесконечного цикла

 

  /* USER CODE BEGIN 3 */

                if(HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_0)==GPIO_PIN_SET)

                {

                        HAL_TIM_Base_Start(&htim6);

                        HAL_TIM_Base_Start_IT(&htim6);

                }

                else

                {

                        tim6_counter=0;

                        HAL_TIM_Base_Stop(&htim6);

                        HAL_TIM_Base_Stop_IT(&htim6);

                        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);

                }

 

В файле audioplay.c удалим подключение ненужных библиотек

 

#include «audioplay.h»

#include «fatfs.h»

#include «usb_host.h»

#include «lcd.h»

 

Также удалим ещё некоторые строки, связанные с использованием удалённых библиотек

 

static uint32_t WaveDataLength = 0;

extern FIL WavFile;

extern ApplicationTypeDef Appli_state;

char str2[20];

char str3[20];

UINT bytesread=0;

extern WAVE_FormatTypeDef *waveformat;

AudioTotalSize=waveformat->FileSize;

/*Get Data from USB Flash Disk*/

WaveDataLength=waveformat->FileSize;

LCD_SetPos(0,3);

LCD_String(str2);

LCD_String(str3);

 

Удалим ещё кое-какие ненужные объявления из файла audioplay.c

 

/* Position in the audio play buffer */

__IO BUFFER_StateTypeDef buffer_offset = BUFFER_OFFSET_NONE;

/* Defines for the Audio playing process */

#define PAUSE_STATUS     ((uint32_t)0x00) /* Audio Player in Pause Status */

#define RESUME_STATUS    ((uint32_t)0x01) /* Audio Player in Resume Status */

#define IDLE_STATUS      ((uint32_t)0x02) /* Audio Player in Idle Status */

#define AUDIO_RESET_GPIO_CLK_ENABLE()         __GPIOD_CLK_ENABLE()

/* Variables used in normal mode to manage audio file during DMA transfer */

uint32_t AudioTotalSize           = 0xFFFF; /* This variable holds the total size of the audio file */

int32_t AudioRemSize             = 0xFFFF; /* This variable holds the remaining data in audio file */

uint16_t *CurrentPos ;             /* This variable holds the current position of audio pointer */

__IO uint32_t PauseResumeStatus = IDLE_STATUS;

static uint32_t WaveDataLength = 0;

#define AUDIO_BUFFER_SIZE             0X8000

uint8_t Audio_Buffer[AUDIO_BUFFER_SIZE];

AUDIO_StateMachine     Audio;

uint32_t samplerate;

uint32_t offsetpos;

uint32_t cnt;

uint32_t dur; //переменная для оставшегося времени воспроизведения файла

Функции AudioPlay_Init и AudioPlay_Start удалим со все содержимым

 

void AudioPlay_Init(uint32_t AudioFreq)

{

        samplerate = AudioFreq;

        __IO uint8_t volume=70;

        if(AudioOut_Init(OUTPUT_DEVICE_AUTO, volume, samplerate)!=0)

        {

                Error();

        }

}

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

void AudioPlay_Start(uint32_t AudioFreq)

{

}

 

Также удалим содержимое функций-обработчиков событий и слегка их переименуем

 

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

void AudioPlay_HalfTransfer_CallBack(void)

{

}

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

void AudioPlay_TransferComplete_CallBack(void)

{

}

 

Переименуем функцию также в файле audioplay.h в объявлении её прототипа

 

void AudioPlay_HalfTransfer_CallBack(void);

void AudioPlay_TransferComplete_CallBack(void);

 

Также подключим в этом файле файл usbd_audio_if.h

 

#include «stm32f4xx_hal.h»

#include «usbd_audio_if.h»

 

Удалим из этого файла объявление функции

 

void AudioPlay_Start(uint32_t AudioFreq);

 

А объявление функции AudioPlay_Init откорректируем в объявление другой функции

 

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

 

Также удалим все объявления переменных и структур кроме SPI3, а вместо них добавим другие, взяв их из си-файла

 

#include «usbd_audio_if.h»

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

#define I2S3                            SPI3

/* Codec output DEVICE */

#define OUTPUT_DEVICE_SPEAKER         1

#define OUTPUT_DEVICE_HEADPHONE       2

#define OUTPUT_DEVICE_BOTH            3

#define OUTPUT_DEVICE_AUTO            4

/* Audio status definition */

#define AUDIO_OK                            ((uint8_t)0)

#define AUDIO_ERROR                         ((uint8_t)1)

#define AUDIO_TIMEOUT                       ((uint8_t)2)

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

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

 

Добавим ещё пару макросов

 

/* Codec POWER DOWN modes */

#define CODEC_PDWN_HW                 1

#define CODEC_PDWN_SW                 2

 

Вставим обработчики прерываний в main.c

 

/* USER CODE BEGIN 4 */

void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s3)

{

  if(hi2s3->Instance == I2S3)

  {

    AudioPlay_TransferComplete_CallBack();      

  }

}

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

void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)

{

  if(hi2s->Instance == I2S3)

  {

AudioPlay_HalfTransfer_CallBack();

  }

}

/* USER CODE END 4 */

 

Подключим нашу плату к ПК, и ST-Link, и USB OTG

 

image11

 

Соберём проект, прошьём контроллер и убедимся, что драйвер нашей будущей звуковой карты у нас нормально установился

 

image18

 

В файл usbd_audio_if.c  подключим нашу библиотеку

 

/* USER CODE BEGIN INCLUDE */

#include «audioplay.h»

/* USER CODE END INCLUDE */

 

В этом же файле в функции AUDIO_Init_FS вызовем инициализацию микросхемы

 

static int8_t AUDIO_Init_FS(uint32_t  AudioFreq, uint32_t Volume, uint32_t options)

{

  /* USER CODE BEGIN 0 */

        AudioOut_Init(OUTPUT_DEVICE_AUTO, Volume, AudioFreq);

  return (USBD_OK);

  /* USER CODE END 0 */

}

 

В следующей части занятия мы напишем ещё несколько функций и подключим их в обработчики команд драйвера звуковой карты.

 

 

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

 

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

 

 

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

 

 

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

 

STM32 USB DEVICE AUDIO

Один комментарий на “STM Урок 48. USB DEVICE AUDIO. Часть 1
  1. Денис:

    Добрый день, на сколько я понял если в кубе настроить i2s и сгенерить его в кейл то транспорт будет работать? Все настройки и изменения в маин касаются управления цап?

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

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

*