STM32CubeIDE USB Audio声卡 WM8978 + I2S

随言:

STM32CubeIDE Audio播放音频,DAC + TIM + DMA https://blog.csdn.net/sudaroot/article/details/106337717
STM32CubeIDE Audio播放音频,PWM + TIM https://blog.csdn.net/sudaroot/article/details/106373388
STM32CbueIDE Audio播放音频 WM8978 + I2S https://blog.csdn.net/sudaroot/article/details/106528371
STM32CubeIDE Audio播放音频 WM8978 + I2S + DMA双缓存模式 https://blog.csdn.net/sudaroot/article/details/106660351
STM32CubeIDE USB Audio声卡 WM8978 + I2S https://blog.csdn.net/sudaroot/article/details/106834893

 

只实现了USB播放音频功能,至于USB录音和控制音量等功能,找到了相关资料,但是个人没时间往下折腾。

官方程序X-CUBE-USB-AUDIO:https://www.st.com/zh/embedded-software/x-cube-usb-audio.html

文档《UM2195 User manual USB device audio streaming Expansion Package for STM32Cube》:https://www.stmcu.org.cn/document/detail/index/id-219223

本手册与补充STM32Cube™固件库的X-CUBE-USB-AUDIO扩展包相关联,它描述了X-CUBE-USB-AUDIO固件库以及使用方法。

文档和程序要相互配合着看。​​​​​​​

 

本文官方参考程序路径:

..\STM32Cube\Repository\STM32Cube_FW_F4_V1.25.0\Projects\STM324xG_EVAL\Applications\USB_Device\AUDIO_Standalone

先看看readme.txt程序支持功能。

The device supports the following audio features:     设备支持以下音频功能:
  - Pulse Coded Modulation (PCM) format                    -脉冲编码调制(PCM)格式
  - sampling rate: 48KHz.                                              -采样率:48KHz。
  - Bit resolution: 16                                                       -位分辨率:16
  - Number of channels: 2                                              -频道数:2
  - No volume control                                                     -无音量控制
  - Mute/Unmute capability                                             -静音/取消静音功能
  - Asynchronous Endpoints                                           -异步端点


注意:不支持音量控制。即电脑无法控制硬件音量,但是可以通过音频数据控制音量。

 

 

STM32CubeIDE配置:

1、I2C控制WM8978寄存器

STM32CubeIDE USB Audio声卡 WM8978 + I2S_第1张图片

2、I2S 飞利浦协议,16bit数据帧,音频48KHz。配置DMA普通模式,数据宽度半个字节,使用满FIFO缓存单次传输,这样AHB总线给予DMA数据的优先最高,相对也会占用AHB总线。

STM32CubeIDE USB Audio声卡 WM8978 + I2S_第2张图片

STM32CubeIDE USB Audio声卡 WM8978 + I2S_第3张图片

 

3、USB配置:USB设备模式。

STM32CubeIDE USB Audio声卡 WM8978 + I2S_第4张图片

4、USB设备,选择为声卡模式,音频采样频率设置48KHz,PID设为0x5730。USB的中断优先级必须降到比0低。

STM32CubeIDE USB Audio声卡 WM8978 + I2S_第5张图片

STM32CubeIDE USB Audio声卡 WM8978 + I2S_第6张图片

STM32CubeIDE USB Audio声卡 WM8978 + I2S_第7张图片

5、时钟配置。

打开《STM32F4xx中文参考手册.pdf》755页。

STM32CubeIDE USB Audio声卡 WM8978 + I2S_第8张图片

由于我们使用MCK时钟输出,采样频率48KHz。故需要修改时钟树的分频。

先把PLLM VCO = 1MHz.

STM32CubeIDE USB Audio声卡 WM8978 + I2S_第9张图片

 

6、生成代码。

 

代码:

   -USB_Device / App/usbd_desc.c 生成的初始化代码
   -USB_Device / App/usbd_desc.h 生成的初始化代码头文件
   -USB_Device / App/usbd_audio_if.c USBD音频接口
   -USB_Device / App/usbd_audio_if.h USBD音频接口头文件
   -USB_Device / App/usbd_desc.c USB设备AUDIO描述符
   -USB_Device / App/usbd_desc.h USB设备AUDIO描述符头文件

   -USB_Device / Target/usbd_conf.c常规低层驱动程序配置
   -USB_Device / Target/ usbd_conf.h USB设备驱动程序配置文件
 

先打开usbd_audio.c, 看生成的底层驱动特性。

STM32CubeIDE USB Audio声卡 WM8978 + I2S_第10张图片

STM32CubeIDE USB Audio声卡 WM8978 + I2S_第11张图片

不支持音量控制!!!不支持音量控制!!!不支持音量控制!!!不支持音量控制!!!不支持音量控制!!!

 

 

现在需要做的是打开usbd_audio_if.c进行填充函数。

  AUDIO_Init_FS,            插入PC会初始化
  AUDIO_DeInit_FS,        USB在挂起后重新连接PC会调用,再调用AUDIO_Init_FS
  AUDIO_AudioCmd_FS, 播放控制函数。
  AUDIO_VolumeCtl_FS,  音量控制,没用,底层不支持。
  AUDIO_MuteCtl_FS,      静音。功能可用。
  AUDIO_PeriodicTC_FS, 数据包接收完成回调。
  AUDIO_GetState_FS,     获取状态。

还有两个外部函数,用于音频数据i2s半发送和发送完成后要求音频数据同步,即请求PC音频数据的。

void HalfTransfer_CallBack_FS(void)

void TransferComplete_CallBack_FS(void)

 

用到的只有粗体3个函数就行了,初始化我使用外部初始化WM8978,不在USB连接初始化硬件。其他函数功能自己玩。

 

WM8978的相关函数以前博客写了好多了。跳过。

 

新建一个audio_player.c,添加如下代码

#include "audio_player.h"
#include "wm8978.h"
#include "usbd_audio_if.h"

extern I2S_HandleTypeDef hi2s2;
extern DMA_HandleTypeDef hdma_spi2_tx;

void Audio_Player_Play(uint16_t* pBuffer, uint32_t Size)
{
	if(Size > 0xFFFF) Size = 0xFFFF;
	HAL_I2S_Transmit_DMA(&hi2s2, pBuffer, Size);
}

void Audio_Player_Pause(void)
{
	HAL_I2S_DMAPause(&hi2s2);
}

void Audio_Player_Resume(void)
{
	HAL_I2S_DMAResume(&hi2s2);
}

void Audio_Player_Stop(void)
{
	HAL_I2S_DMAStop(&hi2s2);
}

void Audio_Player_VolumeCtl(uint8_t vol)
{
	WM8978_VolumeCtl(vol);
}

void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
	HalfTransfer_CallBack_FS();
}

void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{
	TransferComplete_CallBack_FS();
}

 

填充usbd_audio_if.c, AUDIO_CMD_START播放前的准备。 AUDIO_CMD_PLAY连续播放。

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:
    	Audio_Player_Play((uint16_t*)pbuf, size);
    break;

    case AUDIO_CMD_PLAY:
    	Audio_Player_Play((uint16_t*)pbuf, size);
    break;	
  }
  return (USBD_OK);
  /* USER CODE END 2 */
}

I2S发送完数据,hUsbDeviceFS.dev_state检测USB是否还连接。如果是USBD_STATE_CONFIGURED则是连接了PC。

如果不添加获取USB连接状态可能导致I2S一直在发送数据,原因就是USBD_AUDIO_Sync()即使在USB断开的情况下还是能

AUDIO_AudioCmd_FS()的AUDIO_CMD_PLAY触发,导致I2S DMA一直在发数据。

void TransferComplete_CallBack_FS(void)
{
  if(hUsbDeviceFS.dev_state == USBD_STATE_CONFIGURED)
  {
	  USBD_AUDIO_Sync(&hUsbDeviceFS, AUDIO_OFFSET_FULL);
  }
}

void HalfTransfer_CallBack_FS(void)
{
	if(hUsbDeviceFS.dev_state == USBD_STATE_CONFIGURED)
	{
		USBD_AUDIO_Sync(&hUsbDeviceFS, AUDIO_OFFSET_HALF);
	}
}

主函数main

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  HAL_Delay(100);
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_I2C1_Init();
  MX_I2S2_Init();
  MX_USART1_UART_Init();
  MX_USB_DEVICE_Init();
  WM8978_Init();
  printf("Sudaroot\r\n");
  HAL_Delay(1000);

  while (1)
  {

  }
}

对了,在初始化WM8978的时候,把音量开到最大。然后PC在调整音量的时候会调整音频PCM数据。故PC无法调整硬件WM8978的音量,但是通过调整发送过来的PCM数据也可以实现控制音量的效果。

 

源码:https://download.csdn.net/download/sudaroot/12532997

B站视频:https://www.bilibili.com/video/BV1xz411e7t5/

 

全篇完。

 

本人是一个嵌入式未入门小白,博客仅仅代表我个人主观见解方便记录成长笔记。 若有与大神大大见解有冲突,我坚信大神大大见解是对的,我的是错的。 若无法下载源码,可私聊私发。 感谢~!

你可能感兴趣的:(STM32)