STM32CubeIDE USB Audio声卡 WM8978 + I2S

随言:

STM32CubeIDE Audio播放音频,DAC + TIM + DMA STM32CubeIDE Audio播放音频,DAC + TIM + DMA_sudaroot的博客-CSDN博客
STM32CubeIDE Audio播放音频,PWM + TIM STM32CubeIDE Audio播放音频,PWM + TIM_sudaroot的博客-CSDN博客
STM32CbueIDE Audio播放音频 WM8978 + I2S STM32CbueIDE Audio播放音频 WM8978 + I2S_sudaroot的博客-CSDN博客_wm8978全双工
STM32CubeIDE Audio播放音频 WM8978 + I2S + DMA双缓存模式 STM32CubeIDE Audio播放音频 WM8978 + I2S + DMA双缓存模式_sudaroot的博客-CSDN博客
STM32CubeIDE USB Audio声卡 WM8978 + I2S STM32CubeIDE USB Audio声卡 WM8978 + I2S_sudaroot的博客-CSDN博客

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

官方程序X-CUBE-USB-AUDIO:X-CUBE-USB-AUDIO - STM32Cube的STM32 USB设备音频流传输软件扩展 - STMicroelectronics

文档《UM2195 User manual USB device audio streaming Expansion Package for STM32Cube》:意法半导体STM | STM32/STM8微控制器 | MCU单片机

本手册与补充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寄存器

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

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

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

5、时钟配置。

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

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

先把PLLM VCO = 1MHz.

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, 看生成的底层驱动特性。

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

现在需要做的是打开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数据也可以实现控制音量的效果。

源码:USBSlaveAudio.rar_STM32CubeAudio-嵌入式文档类资源-CSDN下载

B站视频:STM32CubeIDE USB Audio声卡 WM8978 + I2S_哔哩哔哩_bilibili

  全篇完。

本人是一个嵌入式未入门小白,博客仅仅代表我个人主观见解,记录成长笔记。
笔记是以最简单的方式,只展示最核心的原理。
若有与 大神大大 见解有歧义,我绝对坚信 大神大大 见解是对的,我的是错的。
若无积分等无法下载源码,可加入QQ群657407920下载交流经验。感谢~!

 

 

  • 7
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值