文章目录
- 一、硬件原理
- 二、STM32CubeMX配置
- 2.1 RCC
- 2.2 SYS
- 2.3 I2C1
- 2.4 USART1
- 2.5 USB_OTG_FS
- 2.6 I2S2
- 2.7 USB_DEVICE
- 2.8 Clock Configuration
- 2.9 Project Manager
- 2.10 生成代码
- 三、代码完善
- 3.1 WM8978
- 3.2 usbd_audio_if
- 四、程序流程图
- 4.1 初始化流程
- 4.2 播放流程
 
一、硬件原理
基于正点原子STM32F407探索者开发板,其中音频部分硬件原理图如下
其中WM8978是一款全功能音频处理器,STM32通过控制WM8978即可实现扬声器/喇叭的音频播放,麦克风的音频录制等功能。
主要控制两个接口
- IIC控制接口,实现WM8978寄存器的读写
- I2S数字音频接口,实现音频数据传输(接收和发送)
二、STM32CubeMX配置
2.1 RCC
开发板外接了两个晶振
- 8MHz的高速晶振
- 32.768kHz的低速晶振

2.2 SYS
Debug Serial Wire

2.3 I2C1
- GPIO口是PB8/PB9


2.4 USART1
- 用来打印调试日志,波特率调到1000000,加快日志打印
- Data Direction: Transmit Only
- DMA Settings: USART1_TX
- PA9 / PA10


2.5 USB_OTG_FS
- Mode:Device Only
- global interrupt 勾选

2.6 I2S2
- mode: Full-Duplex Master
- Audio Frequency: 48KHz
- DMA Setting: SPI2_TX / I2S2_EXT_RX
- GPIO Setting



2.7 USB_DEVICE
- Class For FS IP: Audio Device Class
- USBD_AUDIO_FREQ: 48000 sample/s
- 描述符有些部分可以自定义


2.8 Clock Configuration


2.9 Project Manager
- 堆栈调大0x4000

2.10 生成代码
- 右上角 GENERATE CODE

3.1 WM8978
main.c
- main函数增加- WM8978_Init();
int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_I2C1_Init();
  MX_I2S2_Init();
  MX_USART1_UART_Init();
  MX_USB_DEVICE_Init();
  WM8978_Init();
  while (1)
  {
  }
}wm8978.c
#define	DEVICE_ADDRESS						0x1A
#define	WIRTE_ADDRESS							(DEVICE_ADDRESS << 1 | 0)
extern I2C_HandleTypeDef hi2c1;
uint8_t WM8978_Write(uint8_t reg_addr, uint16_t data)
{
	uint8_t pData[10] =	{ 0 };
	pData[0] = (reg_addr << 1) | ((data >> 8) & 0x01);
	pData[1] = data & 0xFF;
	return HAL_I2C_Master_Transmit(&hi2c1, WIRTE_ADDRESS, pData, 2, 1000);
}
uint32_t WM8978_Init(void)
{
	WM8978_Reset();
	WM8978_Write(1, 0x0F);	// 模拟放大器使能, 使能输出输入缓存区
	WM8978_Write(3, 0x7F);	// 使能左右声道和L\ROUT2
	WM8978_Write(4, 0x10);	// I2S 16bit
	WM8978_Write(6, 0x00);	// MCU提供时钟
	WM8978_Write(10, 0x08);	// 输出音质最好
	WM8978_Write(43, 0x10);	// ROUT2反相
	WM8978_VolumeCtl(0x3F);
	return 0;
}
uint32_t WM8978_Reset(void)
{
	if(WM8978_Write(0, 0)!= HAL_OK)// 软复位
		return 1;
	HAL_Delay(10);
	return 0;
}3.2 usbd_audio_if
- AUDIO_AudioCmd_FS中对应- AUDIO_CMD_START、- AUDIO_CMD_PLAY和- AUDIO_CMD_STOP的操作
- HAL_I2S_TxCpltCallback对应传输完成的USB同步操作
extern I2S_HandleTypeDef hi2s2;
/**
  * @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)
{
  switch(cmd)
  {
    case AUDIO_CMD_START:
		HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t*)pbuf, size);
    break;
    case AUDIO_CMD_PLAY:
		HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t*)pbuf, size);
    break;	
    case AUDIO_CMD_STOP:
    	HAL_I2S_DMAStop(&hi2s2);
    break;	
  }
  return (USBD_OK);
}
void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
	HalfTransfer_CallBack_FS();
}
void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{
	TransferComplete_CallBack_FS();
}4.1 初始化流程
main 
    
      hal库 
    
      stm32f4xx_hal_map 
    
      wx8978 
    
      usb_device 
    
      STM32_USB_DEVICE_Library 
    
    HAL_Init() 
  
    SystemClock_Config() 
  
    HAL_Delay(100) 
  
    MX_GPIO_Init() 
  
    MX_DMA_Init() 
  
    MX_I2C1_Init() 
  
    HAL_I2C_Init() 
  
    HAL_I2C_MspInit() 
  
    MX_I2S2_Init() 
  
    HAL_I2S_Init() 
  
    HAL_I2S_MspInit() 
  
    WM8978_Init() 
  
    MX_USB_DEVICE_Init() 
  
    USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) 
  
    USBD_RegisterClass(&hUsbDeviceFS, &USBD_AUDIO) 
  
    USBD_AUDIO_RegisterInterface(&hUsbDeviceFS, &USBD_AUDIO_fops_FS) 
  
    USBD_Start(&hUsbDeviceFS) 
  
    HAL_Delay(100) 
  
    while(1) 
  
      main 
    
      hal库 
    
      stm32f4xx_hal_map 
    
      wx8978 
    
      usb_device 
    
      STM32_USB_DEVICE_Library
 
4.2 播放流程
 
STM32_USB_DEVICE_Library 
    
      usbd_audio_if 
    
      hal库 
    
    AudioCmd(uint8_t *pbuf, uint32_t size, uint8_t cmd) 
  
    HAL_I2S_Transmit_DMA 
  
      STM32_USB_DEVICE_Library 
    
      usbd_audio_if 
    
      hal库
                










