【HC32F460开发板测评】05 wm8731通过耳机播放音乐
本帖最后由 1nnocent 于 2021-4-21 14:55 编辑<p>HC32F460开发板的AUDIO是比较感兴趣的一个功能,这次来大概看一看。</p>
<p>AUDIO<br />
EVB 配置 1 个 Audio Codec 芯片 WM8731SEDS 和 Audio PA 芯片 BL6281,并提供一个板载<br />
MIC、 3.5mm 耳机接口和 Line in 接口以及一个喇叭接口,以实现录音以及音频输入和输出功<br />
能。<br />
MCU I2S 接口时钟可以通过更改电阻来切换,如下所示:</p>
<table>
<tbody>
<tr>
<td width="200">I2S_CLK</td>
<td width="200">R141</td>
<td width="200">R54</td>
<td width="200">R143</td>
<td width="200">R55</td>
<td width="200">R30</td>
</tr>
<tr>
<td width="200">I2S_EXCK(default)</td>
<td width="200">33</td>
<td width="200">100</td>
<td width="200">DNP</td>
<td width="200">DNP</td>
<td width="200">0</td>
</tr>
<tr>
<td width="200">I2S_MCK</td>
<td width="200">DNP</td>
<td width="200">DNP</td>
<td width="200">33</td>
<td width="200">100</td>
<td width="200">DNP</td>
</tr>
</tbody>
</table>
<p> </p>
<p>WM8731是一款Codec芯片, WM 8731带有集成耳机驱动器的低功率立体声编解码器,提供了立体声线和单麦克风电平音频输入,以及静音功能、可编程线型音量控制和适合驻极体型麦克风的偏压输出。</p>
<p>BL6281是一款 AB类<a href="https://datasheet.eeworld.com.cn/cat/Audio_power_amplifier.html">音频功率放大器</a>用于驱动1.1W8Ω喇叭。</p>
<p>一开始看的是配套的历程,在I2C的例程里面可以找到,例程i2s_record_wm8731_exck_dma的功能是,录取音乐或麦克风的音频信号,将其存储,再通过DMA和I2S使用耳机或者喇叭播放出来,比较麻烦,所以先只单独试一下wm8731这个芯片,单独使用wm8731的话程序就比较简单,配置一下相关寄存器就好了。</p>
<p>一下是使用i2s_record_wm8731_exck_dma历程改的程序(程序就只剩下wm8731的配置,配置完就可以播放音频信号(J12输入音频信号),通过耳机J11可以听到音乐):</p>
<p>audio.c</p>
<div aria-label="代码段 小部件" contenteditable="false" role="region" tabindex="-1">
<pre data-widget="codesnippet">
<code class="hljs">/******************************************************************************/
/** \file audio.c
**
** \brief Audio functions
**
** - 2021-04-151.0First version for Audio
**
******************************************************************************/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ddl.h"
#include "wm8731.h"
#include "audio.h"
#include "i2c.h"
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
#define RECORDER_WAVFILELEN (15u*1024u)
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
extern uint16_t *pu16SoundData;
extern uint16_t au16RecorderSoundI2s;
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/**
*******************************************************************************
** \briefConfiguration Codec to record wav file
**
** \paramNone
**
** \retval None
**
******************************************************************************/
void WM8731_CodecConfigRecord(void)
{
stc_wm8731_reg_t stcWm8731Reg;
MEM_ZERO_STRUCT(stcWm8731Reg);
/* Config codec */
/* Reset register */
stcWm8731Reg.RESET = 0x00u; // Reset WM8731
/* Left & right line input */
stcWm8731Reg.LLIN_f.LINVOL = 0x17; // Left channel line input volume: 0dB--0x17u
stcWm8731Reg.LLIN_f.LINMUTE = 0u; // Enable left channel line input mute
stcWm8731Reg.LLIN_f.LRINBOTH = 0u; // Disable simultaneous input volume and mute load from left to right
stcWm8731Reg.RLIN_f.RINVOL = 0x17; // Right channel line input volume 0dB
stcWm8731Reg.RLIN_f.RINMUTE = 0u; // Enable right channel line input mute
stcWm8731Reg.RLIN_f.RINBOTH = 0u; // Disable simultaneous input volume and mute load from right to left
/* Left & right headphone output */
stcWm8731Reg.LHOUT_f.LHPVOL = 0x5Fu; // Set volume of left headphone to 0dB. 0x30(-73dB) ~ 0x7F(+6dB), 0 ~ 0x2F: mute
stcWm8731Reg.LHOUT_f.LZCEN = 0u; // Disable left channel zero cross detect
stcWm8731Reg.LHOUT_f.LRHPBOTH = 0u; // Disable simultaneous output volume and mute load from left to right
stcWm8731Reg.RHOUT_f.RHPVOL = 0x5Fu; // Set volume of right headphone to 0dB. 0x30(-73dB) ~ 0x7F(+6dB), 0 ~ 0x2F: mute
stcWm8731Reg.RHOUT_f.RZCEN = 0u; // Enable right channel zero cross detect
stcWm8731Reg.RHOUT_f.RLHPBOTH = 0u; // Disable simultaneous output volume and mute load from right to left
/* Analog audio path control */
#if(RECORD_MIC)
stcWm8731Reg.AAPC_f.MICBOOST = 1u; // Disable boost, 0: disable 1: enable
stcWm8731Reg.AAPC_f.MUTEMIC = 0u; // Enable mute to ADC
stcWm8731Reg.AAPC_f.INSEL = 1u; // Line input select to ADC, 0: linein1: mic
stcWm8731Reg.AAPC_f.BYPASS = 1u; // Enbale bypass 0: disable 1:enable
stcWm8731Reg.AAPC_f.DACSEL = 0u; // Select DAC
stcWm8731Reg.AAPC_f.SIDETONE = 0u; // Disable side tone 0: disable 1:enable
stcWm8731Reg.AAPC_f.SIDEATT = 0u; // 0: -6dB, 1: -12dB, 2: -9dB, 3: -15dB.
#else
stcWm8731Reg.AAPC_f.MICBOOST = 0u; // Disable boost, 0: disable 1: enable
stcWm8731Reg.AAPC_f.MUTEMIC = 1u; // Enable mute to ADC
stcWm8731Reg.AAPC_f.INSEL = 0u; // Line input select to ADC, 0: linein1: mic
stcWm8731Reg.AAPC_f.BYPASS = 1u; // Enbale bypass 0: disable 1:enable
stcWm8731Reg.AAPC_f.DACSEL = 0u; // Select DAC
stcWm8731Reg.AAPC_f.SIDETONE = 0u; // Disable side tone 0: disable 1:enable
stcWm8731Reg.AAPC_f.SIDEATT = 0u; // 0: -6dB, 1: -12dB, 2: -9dB, 3: -15dB.
#endif
/* Digital audio path control */
stcWm8731Reg.DAPC_f.ADCHPD = 0u; // Enable high pass filter
stcWm8731Reg.DAPC_f.DEEMP = 0u; // De-emphasis contrl. 0: disable, 1: 32kHz, 2: 44.1kHz, 3: 48kHz
stcWm8731Reg.DAPC_f.DACMU = 0u; // 0:Disable soft mute 1: Enable soft mute
stcWm8731Reg.DAPC_f.HPOR = 0u; // Clear offset when high pass
/* Power down control */
stcWm8731Reg.PDC_f.LINEINPD = 0u; // Disable line input power down
stcWm8731Reg.PDC_f.MICPD = 0u; // Disable microphone input power down
stcWm8731Reg.PDC_f.ADCPD = 0u; // Disable ADC power down
stcWm8731Reg.PDC_f.DACPD = 0u; // Disable DAC power down
stcWm8731Reg.PDC_f.OUTPD = 0u; // Disable output power down
stcWm8731Reg.PDC_f.OSCPD = 0u; // Disable oscillator power down
stcWm8731Reg.PDC_f.CLKOUTPD = 0u; // Disable CLKOUT power down
stcWm8731Reg.PDC_f.POWEROFF = 0u; // Disable power off mode
/* Digital audio interface format */
stcWm8731Reg.DAIF_f.FORMAT = 2u; // 0: MSB-First, right justified, 1: MSB-first, left justified, 2: I2S-format, 3: DSP mode
stcWm8731Reg.DAIF_f.IWL = 0u; // 0: 16 bits, 1: 20 bits, 2: 24 bits, 3: 32 bits
stcWm8731Reg.DAIF_f.LRP = 0u; // 1: right channel DAC data when DACLRC (WS) is high,0: right channel DAC data when DACLRC (WS) is low
stcWm8731Reg.DAIF_f.LRSWAP = 0u; // 1: swap left channel and right channel, 0: don't swap
stcWm8731Reg.DAIF_f.MS = 0u; // 1: Enable master mode, 0: Enable slave mode
stcWm8731Reg.DAIF_f.BCLKINV = 0u; // Don't invert BCLK
/* Sampling control */
stcWm8731Reg.SC_f.NORMAL_USB = 0u; // 0: normal mode, 1: USB mode
stcWm8731Reg.SC_f.BOSR = 0u; // Nomrmal mode: 0: 256fs, 1: 384fs
// USB mode: 0: 250fs, 1:272fs
stcWm8731Reg.SC_f.SR = 2u; // Sample rate setting
stcWm8731Reg.SC_f.CLKDIV2 = 0u; // 0: core clock is MCLK, 1: core clock is MCLK divided by 2
stcWm8731Reg.SC_f.CLKODIV2 = 0u; // 0: output clock is core clock, 1: core clock is core clock/2
// Active control
stcWm8731Reg.AC_f.ACTIVE = 1u; // 0: inactive, 1: active
WM8731_Init(I2C_CH, &stcWm8731Reg);
WM8731_SetHpVolume(I2C_CH, 0x7Fu,0x7Fu); //0x2F-MUTE ~ 0x7F Maximum
}
/**
*******************************************************************************
** \briefConfiguration Codec to play wav file
**
** \paramNone
**
** \retval None
**
******************************************************************************/
void WM8731_CodecConfigPlay(void)
{
stc_wm8731_reg_t stcWm8731Reg;
MEM_ZERO_STRUCT(stcWm8731Reg);
/* Config codec */
/* Reset register */
stcWm8731Reg.RESET = 0x00u; // Reset WM8731
/* Left & right line input */
stcWm8731Reg.LLIN_f.LINVOL = 0x00u; // Left channel line input volume: 0dB--0x17u
stcWm8731Reg.LLIN_f.LINMUTE = 1u; // Enable left channel line input mute
stcWm8731Reg.LLIN_f.LRINBOTH = 0u; // Disable simultaneous input volume and mute load from left to right
stcWm8731Reg.RLIN_f.RINVOL = 0x00u; // Right channel line input volume 0dB
stcWm8731Reg.RLIN_f.RINMUTE = 1u; // Enable right channel line input mute
stcWm8731Reg.RLIN_f.RINBOTH = 0u; // Disable simultaneous input volume and mute load from right to left
/* Left & right headphone output */
stcWm8731Reg.LHOUT_f.LHPVOL = 0x5Fu; // Set volume of left headphone to 0dB. 0x30(-73dB) ~ 0x7F(+6dB), 0 ~ 0x2F: mute
stcWm8731Reg.LHOUT_f.LZCEN = 0u; // Disable left channel zero cross detect
stcWm8731Reg.LHOUT_f.LRHPBOTH = 0u; // Disable simultaneous output volume and mute load from left to right
stcWm8731Reg.RHOUT_f.RHPVOL = 0x5Fu; // Set volume of right headphone to 0dB. 0x30(-73dB) ~ 0x7F(+6dB), 0 ~ 0x2F: mute
stcWm8731Reg.RHOUT_f.RZCEN = 0u; // Enable right channel zero cross detect
stcWm8731Reg.RHOUT_f.RLHPBOTH = 0u; // Disable simultaneous output volume and mute load from right to left
/* Analog audio path control */
stcWm8731Reg.AAPC_f.MICBOOST = 0u; // Disable boost
stcWm8731Reg.AAPC_f.MUTEMIC = 1u; // Enable mute to ADC
stcWm8731Reg.AAPC_f.INSEL = 0u; // Line input select to ADC
stcWm8731Reg.AAPC_f.BYPASS = 0u; // Enbale bypass
stcWm8731Reg.AAPC_f.DACSEL = 1u; // Select DAC
stcWm8731Reg.AAPC_f.SIDETONE = 0u; // Disable side tone
stcWm8731Reg.AAPC_f.SIDEATT = 0u; // 0: -6dB, 1: -12dB, 2: -9dB, 3: -15dB.
/* Digital audio path control */
stcWm8731Reg.DAPC_f.ADCHPD = 0u; // Enable high pass filter
stcWm8731Reg.DAPC_f.DEEMP = 3u; // De-emphasis contrl. 0: disable, 1: 32kHz, 2: 44.1kHz, 3: 48kHz
stcWm8731Reg.DAPC_f.DACMU = 0u; // 0:Disable soft mute 1: Enable soft mute
stcWm8731Reg.DAPC_f.HPOR = 0u; // Clear offset when high pass
/* Power down control */
stcWm8731Reg.PDC_f.LINEINPD = 0u; // Disable line input power down
stcWm8731Reg.PDC_f.MICPD = 0u; // Disable microphone input power down
stcWm8731Reg.PDC_f.ADCPD = 0u; // Disable ADC power down
stcWm8731Reg.PDC_f.DACPD = 0u; // Disable DAC power down
stcWm8731Reg.PDC_f.OUTPD = 0u; // Disable output power down
stcWm8731Reg.PDC_f.OSCPD = 0u; // Disable oscillator power down
stcWm8731Reg.PDC_f.CLKOUTPD = 0u; // Disable CLKOUT power down
stcWm8731Reg.PDC_f.POWEROFF = 0u; // Disable power off mode
/* Digital audio interface format */
stcWm8731Reg.DAIF_f.FORMAT = 2u; // 0: MSB-First, right justified, 1: MSB-first, left justified, 2: I2S-format, 3: DSP mode
stcWm8731Reg.DAIF_f.IWL = 0u; // 0: 16 bits, 1: 20 bits, 2: 24 bits, 3: 32 bits
stcWm8731Reg.DAIF_f.LRP = 0u; // 1: right channel DAC data when DACLRC (WS) is high,0: right channel DAC data when DACLRC (WS) is low
stcWm8731Reg.DAIF_f.LRSWAP = 0u; // 1: swap left channel and right channel, 0: don't swap
stcWm8731Reg.DAIF_f.MS = 0u; // 1: Enable master mode, 0: Enable slave mode
stcWm8731Reg.DAIF_f.BCLKINV = 0u; // Don't invert BCLK
/* Sampling control */
stcWm8731Reg.SC_f.NORMAL_USB = 0u; // 0: normal mode, 1: USB mode
stcWm8731Reg.SC_f.BOSR = 0u; // Nomrmal mode: 0: 256fs, 1: 384fs
// USB mode: 0: 250fs, 1:272fs
stcWm8731Reg.SC_f.SR = 1u; // Sample rate setting
stcWm8731Reg.SC_f.CLKDIV2 = 0u; // 0: core clock is MCLK, 1: core clock is MCLK divided by 2
stcWm8731Reg.SC_f.CLKODIV2 = 0u; // 0: output clock is core clock, 1: core clock is core clock/2
// Active control
stcWm8731Reg.AC_f.ACTIVE = 1u; // 0: inactive, 1: active
WM8731_Init(I2C_CH, &stcWm8731Reg);
WM8731_SetHpVolume(I2C_CH, 0x7Fu,0x7Fu); //0x2F-MUTE ~ 0x7F Maximum
}
/**
*******************************************************************************
** \briefConfiguration Codec to play wav file
**
** \paramNone
**
** \retval None
**
******************************************************************************/
void SpeakerInit(void)
{
stc_port_init_t stcPortIni;
#if(SPEAKER_ON)
/* Initialize SPK_EN port for speaker */
MEM_ZERO_STRUCT(stcPortIni);
stcPortIni.enPinMode = Pin_Mode_Out;
PORT_Init(SPK_EN_PORT, SPK_EN_PIN, &stcPortIni);
SPEAKER_EN();
#endif
// /* Prepare buffer for store recoder data */
// pu16SoundData = &au16RecorderSoundI2s;
}
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/
</code></pre>
<img src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" /><span style="background: url("https://bbs.eeworld.com.cn/static/editor/plugins/widget/images/handle.png") rgba(220, 220, 220, 0.5); top: -15px; left: 0px; display: block;"><img height="15" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" /></span></div>
<p>audio.h</p>
<div aria-label="代码段 小部件" contenteditable="false" role="region" tabindex="-1">
<pre data-widget="codesnippet">
<code class="hljs">/******************************************************************************/
/** \file audio.h
**
** A detailed description is available at
** @link audio Series description @endlink
**
** - 2021-4-151.0First version for Audio Series Functions description
** Library.
**
******************************************************************************/
#ifndef __AUDIO_H__
#define __AUDIO_H__
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_common.h"
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/* Define if need play by speaker*/
#define SPEAKER_ON (true)
/* Select Record source */
//#define RECORD_MIC (true)
#define SPK_EN_PORT (PortB)
#define SPK_EN_PIN (Pin00)
#define SPEAKER_EN() (PORT_SetBits(SPK_EN_PORT, SPK_EN_PIN))
#define SPEAKER_DISEN() (PORT_ResetBits(SPK_EN_PORT, SPK_EN_PIN))
//#define RECORDER_WAVFILELEN (15u*1024u)
///*******************************************************************************
// * Local variable definitions ('static')
// ******************************************************************************/
//uint16_t *pu16SoundData=NULL;
//uint16_t au16RecorderSoundI2s;
//uint8_t u8RecordEndFlag = 0u;
//uint32_t u32Count = 0ul;
void WM8731_CodecConfigRecord(void);
void WM8731_CodecConfigPlay(void);
void SpeakerInit(void);
#endif /* __AUDIO_H__ */
/*******************************************************************************
* End of file
******************************************************************************/
</code></pre>
<img src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" /><span style="background: url("https://bbs.eeworld.com.cn/static/editor/plugins/widget/images/handle.png") rgba(220, 220, 220, 0.5); top: -15px; left: 0px; display: block;"><img height="15" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" /></span></div>
<p>i2c.c</p>
<pre>
<code>/******************************************************************************/
/** \file I2C.c
**
** \brief I2C functions
**
** - 2021-04-151.0First version for I2C
**
******************************************************************************/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ddl.h"
#include "i2c.h"
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
void i2cInit()
{
/* Initialize i2c port for codec wm8731 */
PORT_SetFunc(I2C2_SCL_PORT, I2C2_SCL_PIN, Func_I2c2_Scl, Disable);
PORT_SetFunc(I2C2_SDA_PORT, I2C2_SDA_PIN, Func_I2c2_Sda, Disable);
/* Enable I2C Peripheral*/
PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_I2C2, Enable);
}
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/
</code></pre>
<p>i2c.h</p>
<pre>
<code>/******************************************************************************/
/** \file i2c.h
**
** A detailed description is available at
** @link i2c Series description @endlink
**
** - 2021-4-151.0First version for i2c Series Functions description
** Library.
**
******************************************************************************/
#ifndef __I2C_H__
#define __I2C_H__
/*******************************************************************************
* Include files
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/* Define I2C unit used for the example */
#define I2C_CH (M4_I2C2)
/* Define port and pin for SDA and SCL */
#define I2C2_SCL_PORT (PortD)
#define I2C2_SCL_PIN (Pin00)
#define I2C2_SDA_PORT (PortD)
#define I2C2_SDA_PIN (Pin01)
void i2cInit(void);
#endif /* __I2C_H__ */
/*******************************************************************************
* End of file
******************************************************************************/
</code></pre>
<p>wm8731.c以及相应的头文件这里不再给出,这两个文件和例程里的是一样的。</p>
<p>单独wm8731代码:</p>
<p></p>
<p>下面这个代码和例程i2s_record_wm8731_exck_dma功能一样,但是使用空历程文件改的,看起来会比历程的简洁一些:</p>
<p></p>
页:
[1]