IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32 USB声卡 CUBEMX配置 极简配置十分钟解决 STM32+PCM5120A -> 正文阅读

[嵌入式]STM32 USB声卡 CUBEMX配置 极简配置十分钟解决 STM32+PCM5120A

1.综述

USB声卡无非就是USB将PCM数据给I2S外设或SAI外设通过I2S输出给DAC转为模拟信号后,连接上耳机。

就算名贵的意大利数字界面也不例外。

2.分步

2.1 USB接收音频数据

2.2 将音频数据发送给DAC

3.开工

开工前啰嗦两句:

笔者分别使用了STM32F103ZET6\STM32F411CEU\STM32F407VET6\STM32F429IGT6\STM32H743IIT6\STM32H750VBT6做了USB声卡,这些芯片在配置时USB部分几乎无差异,最大的区别在于F103\F411\F407将音频数据发送给DAC使用的是I2S外设,F429\H743\H750有SAI外设,可以选择使用SAI发送。

下面的详细介绍以STM32F411CEU为例,因为STM32F411CEU封装小,能效高,适于用于低功耗体积小且需要一定性能的场合中。相较于上面提到的其它芯片更加适合用于数字声卡中。

3.1 USB硬件设置

在第一步处选择Device_Only,第二步默认即可

3.2 USB中间件配置

?第一步找到Middleware,选择USB_DEVICE,在第二步选择Audio_Device_Class,第三步实测默认直接就是这个值不需要改。

到此,USB部分设置完辽

3.3 I2S基本设置

第一步设置为主模式。主模式全双工和半双工都行,如果想同时实现USB麦克风,且麦克风通过I2S发送到电脑时需要设置为全双工模式。之后记得选择主时钟输出(Master Clock Output)

3.4 音频数据传输DMA设置

此部分无论使用SAI还是I2S在设置时均相同。

?

第一步选择DMA设置,并且选择DMA请求为发送,DMA数据流只有带有DMA复用器的芯片才可以自由选择本例中芯片只能默认。其次如果数字声卡只是其中之一的功能,且有多个功能用到了DMA,需要注意DMA的优先级,实时性要求高的请提高DMA的优先级。本例中仅数字声卡故跟随默认选择了低优先级

第二步配置DMA的基本参数,DMA模式设置为循环模式,数据带宽设置为半字(与上节中I2S发送数据帧16bits相对应)

第三步配置DMA的FIFO,DMA的FIFO可以使得DMA请求封装成更大的数据块从而减少访存次数并充分利用SRAM的猝发式读写功能。该部分设置可自由发挥,本例中使用了所有FIFO并最大限度地封装成大数据块,将猝发尺寸(Brust Size)设置到了最大。注意:Brust Size不能任意改,由于FIFO深度为4个字,故传输半字数据时FIFO中最多可以装的下8个数据,故最大猝发式读取的尺寸为8

?3.5 时钟配置

配置时钟使得I2S或SAI界面中的误差系数尽量小。若有缘分和我使用了相同的芯片和相同的采样率(48KHZ)可以直接参考我的设置。

3.6误差值在哪看?

?第一步选择I2S或SAI

第二步在选择的标准频率下面会显示当前的实际频率和误差,让误差(Error between Selected and Real)尽量小。此部分参数与时钟配置是直接关联的。调参数的时候请两边切换这调。

3.7 修改堆栈大小

?

第一步选择工程管理(Project Manager)选项卡

第二步修改堆栈,请改大,改成和我一样,因为USB功能会定义很多带有很多信息的结构体,其次数字声卡的缓冲区也是USB功能直接从堆中申请的。所以需要把堆栈调大。当然如果使用了操作系统或有自己的内存分配函数可以在缓冲区定义的位置缓冲内存分配函数

这个函数在usbd_conf.c内,源码如下

/**
  * @brief  Static single allocation.
  * @param  size: Size of allocated memory
  * @retval None
  */
void *USBD_static_malloc(uint32_t size)
{
  static uint32_t mem[(sizeof(USBD_AUDIO_HandleTypeDef)/4)+1];/* On 32-bit boundary */
  return mem;
}

?3.8 改代码配置

USB原本是非常复杂的,代码部分原本也是不例外得复杂,但是ST官方帮我们完成了几乎所有工作,我们只需要牵线让USB和I2S认识一下就行了。

整个修改过程USB部分只需要填写usbd_audio_if.c文件中的各个功能函数和封装I2S的功能函数。

usbd_audio_if.c中,最简修改是只修改AUDIO_AudioCmd_FS函数并在I2S发生中断和半传输中断时分别调用该文件中的同步函数TransferComplete_CallBack_FS和HalfTransfer_CallBack_FS。

封装I2S的功能有I2S以DMA方式发送、DMA中断处理函数。其次也可封装DMA 的暂停、恢复、停止等功能以背后续使用。

void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
	if(hi2s == &hi2s2){
		HalfTransfer_CallBack_FS();//osSemaphoreRelease(SAI3_TX_BUFF0Handle);
	}
}

void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{
	if(hi2s == &hi2s2){
		TransferComplete_CallBack_FS();//osSemaphoreRelease(SAI3_TX_BUFF1Handle);
	}
}

AudioPlayerInfo.DMA_TX_NUM);
}
void AudioDMA_Stop(void)//停止DMA结束播放
{
	HAL_I2S_DMAStop(&hi2s2);
}

void AudioDMA_Pause(void)//暂停DMA暂停播放
{
	HAL_I2S_DMAPause(&hi2s2);
}

void AudioDMA_Resume(void)//从暂停恢复播放
{
	HAL_I2S_DMAResume(&hi2s2);
}

void AudioCard_Play(uint16_t* buff, uint16_t size)//声卡模式开始播放
{
	HAL_I2S_Transmit_DMA(&hi2s2, buff, size);
}

?修改usbd_audio_if.c中的AUDIO_AudioCmd_FS函数


/**
  * @brief  Handles AUDIO command.
  * @param  pbuf: Pointer to buffer of data to be sent
  * @param  size: Number of data to be sent (in bytes)
  * @param  cmd: Command opcode
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
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:
		AudioCard_Play((uint16_t*)pbuf, size);
    break;

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

到此为止就可以插到电脑上并且选择该声卡了,连接电脑后从I2S接口便能源源不断的输出数据,连接上PCM5120A插上耳机就能听歌了。由于PCM5120A只是一个DAC没有寄存器需要配置,连上就能用简单粗暴且音质好,电源噪音抑制好。在Windows环境下可以自由调节音量(虽然usbd_audio_if.c文件中指出没有调节音量的功能)。理论上这种调整音量的方式牺牲了数据精度然而在实际使用中,在听感几乎不影响。

3.9添加静音功能

经营功能对应usbd_audio_if.c文件的AUDIO_MuteCtl_FS(uint8_t cmd)函数。该函数在设置静音和接触静音时均会调用,故需要增加标志位进行判断是静音还是接触静音。此功能可以用得着之前封装I2S功能的暂停和恢复功能。修改后代码如下

/**
  * @brief  Controls AUDIO Mute.
  * @param  cmd: command opcode
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
static int8_t AUDIO_MuteCtl_FS(uint8_t cmd)
{
  /* USER CODE BEGIN 4 */
  static uint8_t state=0;
  if(state){
	  AudioDMA_Pause();
	  state = 0;
  } else{
	  AudioDMA_Resume();
	  state = 1;
  }
  UNUSED(cmd);
  return (USBD_OK);
  /* USER CODE END 4 */
}

?4踩坑

新版本的CUBEMX已经和之前有很大的区别,很多问题已经解决,但是有时候还是会阴差阳错发生一些错误。本例中,在上述配置后,编译烧写代码发现不出声音。调试在I2S传输完成函数打断点发现根本不会运行,即I2S没有持续工作。之后检查DMA寄存器发现DMA的寄存器中控制寄存器根本没有写入初始化的值。最终发现在DMA初始化时,CUBEMX没有考虑到初始化I2S时即初始化DMA,将DMA初始化的代码放到了I2S初始化的后面。

应当如图所示,将DMA的初始化改到I2S初始化的前面。

?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-02-01 20:46:36  更:2022-02-01 20:48:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:34:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码