WM8994
回帖(1)
2022-2-23 11:45:21
描述
- WM8994 是一款高度集成的超低功耗高保真 CODEC,专为智能手机和其他具有丰富多媒体功能的便携式设备而设计。
- 集成的立体声 D/AB 扬声器驱动器和 W 类耳机驱动器,可最大限度降低音频播放期间的功耗。
- 该器件只需要两个电压电源,所有其他内部电源均由集成 LDO 生成。
- 立体声全双工异步采样率转换和多通道数字混合,加上强大的模拟混合功能,使器件能够支持各种不同的架构和用例。
- 完全可编程参数均衡器提供扬声器补偿,ADC 或 DAC 路径中可以使用动态范围控制器,用于保持恒定的信号电平、最大限度地提高响度并保护扬声器免受过载和截止失真。
- 智能数字麦克风接口提供功率调节、低抖动时钟输出和多达四个数字麦克风的抽取滤波器。 MIC 活动检测可以触发中断。
- 有源接地环路噪声抑制和直流偏置校正有助于防止爆裂噪音,并抑制耳机输出上的接地噪声。
特征
- 高保真 24 位 4 通道 DAC 和 2 通道 ADC
- DAC 播放期间的 100dB SNR('A' 加权)
- 智能 MIC 接口 电源、时钟和数据输入,可存储多达四个数字高性能 MIC /模拟 MIC 接口/ MIC 活动监视器 + 中断/允许处理器休眠
- 1W 立体声 / 2W 单声道 D/AB 扬声器驱动器
- W 类耳机驱动器 集成充电泵 6mW 总功率,用于 DAC 播放至耳机
- 4 线输出(单端或差分)
- BTL 耳机驱动器
- 用于多处理器架构的数字音频接口异步立体声双工采样率转换 强大的混音和数字环回功能
- ReTuneTM 移动 5 频段、6 通道参数均衡器
- 可编程动态范围控制器
- 双 FLL 提供所有必要的时钟自时钟模式,允许处理器休眠所有标准采样速率,从 8kHz 到 96kHz
- 有源降噪电路直流偏置校正可消除爆裂声和咔嗒声,并消除接地环路噪声消除
- 集成 LDO 调节器
- 72 球(脚) W-CSP 封装(4.511 x 4.023 x 0.7mm)
总体框图
开发板实际应用电路图
接口支持
4路单/差分麦克风,3路I2S/PCM接口,1路立体声耳机接口,1路单声道差分耳机接口,1路喇叭(手机听筒),1路立体声喇叭。
1.调试准备
首先准备的是使用软件IIC接口进行通信(先用软件IIC调试成功后再移植硬件IIC,降低调试难度)。
IIC使用的是PH8(SDA),PH7(SCL),地址为0x34,初始化软件IIC接口
2.关于IIC接口
WM8994文档中写的很清楚,当CIFMODE接地时为IIC通信方式(应该大部分都是使用IIC通信),但是我按照手册上面的时序,发现读写都正常,就是读取的数据一直是FF,而且能正常收到ACK,如果随便改一个地址就会通信失败,证明读写是对的,但是折腾了几天发现读取的数据一直是FF,最后查明原因无论是软件还是硬件IIC,输出都得是开漏输出才行。
通信接口配置
寄存器很多,平时使用就几个寄存器,就初始化时麻烦,但是这个软件WISCE能一键给你搞定。
软件使用比较简单,上面有下载链接,自己可以折腾一下,我使用的是第一个配置,AF1 输出HPOUT1,底部就会显示要设置的寄存器与值。
以下是具体的驱动代码(只实现了HPOUT1 也就是耳机1输出所需的接口)
/*************************************************************************************************************
* 文件名 : WM8994.c
* 功能 : STM32F7 WM8994驱动
* 作者 : cp1300@139.com
* 创建时间 : 2020-02-18
* 最后修改时间 : 2020-02-19
* 详细: 使用的IIC与WM8994通讯
注意:关闭写寄存器与SYS_CLK同步,否则如果没有提供MCLK时钟并配置SYS_CLK会导致写入的寄存器无效,建议关闭掉
如果不关闭一定要先将SAI初始化完成,并提供MCLK时钟,否则对WM8994的寄存器配置将无效
正常使用先调用WM8994_Init(),然后初始化好SAI并输出音频数据,调用WM8994_SetFrequency()设置采样率,
WM8994_SetDataBitSize()设置位宽,最后WM8994_EnableDAC()使能DAC
*************************************************************************************************************/
#include "stm32f7xx.h"
#include "system.h"
#include "main.h"
#include "WM8994.h"
#include "SoftwareIIC.h"
const u16 WM8994_INIT_REG_TABLE[][2] =
{
//全自动的AIF1设置
{0x000, 0x0000}, //寄存器0写入任意数据将会导致芯片复位,复位后请第一时间关闭写同步0x101寄存器写0x0004(只开启IIC读指针自增模式)
{0xFFFF, 1}, //0Xffff代表延时,延时1ms
{0x101, 0x0004}, //关闭写寄存器与SYS_CLK同步,否则如果没有提供MCLK时钟并配置SYS_CLK会导致写入的寄存器无效,建议关闭掉
{0xFFFF, 1}, //0Xffff代表延时,延时1ms
{0x420, 0X0200}, //AIF1 Slot0 DAC1 L/R静音-默认不让任何声音输出,正常使用时请调用WM8994_EnableDAC()使能DAC
{0x422, 0X0200}, //AIF1 Slot1 DAC2 L/R取消静音-默认不让任何声音输出,正常使用时请调用WM8994_EnableDAC()使能DAC
{0x102, 0x0003},
{0x817, 0x0000},
{0x102, 0x0000},
{0x39, 0x0064},
{0x01, 0x0003},
{0xFFFF, 50}, //0Xffff代表延时,延时50ms
{0x601, 0x0001},
{0x602, 0x0001},
{0x210, 0x0083}, //采样时钟设置48KHz
{0x300, 0x4010}, //AIF1接口格式设置I2S:标准的I2S数据格式
{0x302, 0x0000}, //从机模式
{0x208, 0x000A}, //时钟使能-不开启PLL,因为单片机直接提供了有效的MCLK时钟(256倍的采样频率)
{0x200, 0x0001}, //AIF1CLK启用,不分频,使用MCLK1作为AIF1CLK时钟源
{0x51, 0x0005},
{0x01, 0x0303},
{0x60, 0x0022}, //启用HPOUT1输出,耳机1输出使能,先使能,然后延时
{0x4C, 0x9F25},
{0xFFFF, 15}, //0Xffff代表延时,延时15ms
{0x05, 0x0303},
{0x2D, 0x0001},
{0x2E, 0x0001},
{0x03, 0x0030},
{0x54, 0x0033},
{0xFFFF, 250}, //0Xffff代表延时,延时250ms
{0x60, 0x00EE}, //HPOUT1输出短路移除,中间级启用-驱动能力会变强
{0x610, 0x00C0}, //DAC1L取消静音-音量设置0db
{0x611, 0x00C0}, //DAC1R取消静音-音量设置0db
//{0x420, 0x0000}, //AIF1 Slot0 DAC1 L/R取消静音
//{0x422, 0x0000}, //AIF1 Slot1 DAC2 L/R取消静音
};
static bool WM8994_WriteOneReg(WM8994_HANDLE *pHandle, u16 RegAddr, u16 Data);//WM8994 写入一个寄存器值
/*************************************************************************************************************************
*函数 : bool WM8994_Init(WM8994_HANDLE *pHandle, u8 SlaveAddr,
bool (*Func_ReadReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum),
bool (*Func_WriteReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum))
*功能 : WM8994初始化
*参数 : pHandle:句柄;SlaveAddr通讯地址;Func_ReadReg:读寄存器接口;Func_WriteReg:写寄存器接口
*返回 : TRUE:初始化成功;FALSE:初始化失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-01-30
*最后修改时间 : 2020-01-30
*说明 : 需要先提前初始化IIC接口
*************************************************************************************************************************/
bool WM8994_Init(WM8994_HANDLE *pHandle, u8 SlaveAddr,
bool (*Func_ReadReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum),
bool (*Func_WriteReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum))
{
u16 temp;
u8 retry = 0;
u16 i = 0;
u16 addr;
if(pHandle == NULL) return FALSE;
pHandle->SlaveAddr = SlaveAddr; //通讯地址
pHandle->Func_ReadReg = Func_ReadReg; //读寄存器接口
pHandle->Func_WriteReg = Func_WriteReg; //写寄存器接口
WM8994_WriteOneReg(pHandle, 0, 1); //写寄存器0,任意值导致WM8994复位
SYS_DelayMS(1);
if(pHandle->Func_ReadReg(pHandle->SlaveAddr, 0, &temp, 1) == TRUE) //读取寄存器0,id
{
uart_printf("WM8994 id:0x%04Xrn",temp);
}
else
{
uart_printf("读取WM8994 id失败rn");
}
//寄存器初始化
for(i = 0;i < sizeof(WM8994_INIT_REG_TABLE)/2/2;i ++)
{
addr = WM8994_INIT_REG_TABLE[0];
temp = WM8994_INIT_REG_TABLE[1];
if(addr == 0xFFFF) //代表延时
{
SYS_DelayMS(temp);
continue;
}
uart_printf("WM8994 REG 0x%04X->0x%04Xrn", addr, temp);
WM8994_WriteOneReg(pHandle, addr, temp); //写入寄存器
}
WM8994_SetVolume(pHandle, WM8994_HPOUT1, 30); //设置声音-注意默认的声音特别大,这里设置稍微小点
return TRUE;
}
/*************************************************************************************************************************
*函数 : bool WM8994_WriteOneReg(WM8994_HANDLE *pHandle, u16 RegAddr, u16 Data)
*功能 : WM8994 写入一个寄存器值
*参数 : pHandle:句柄;AudioFreq:RegAddr:寄存器地址;Data:数据
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-19
*最后修改时间 : 2020-02-19
*说明 :
*************************************************************************************************************************/
bool WM8994_WriteOneReg(WM8994_HANDLE *pHandle, u16 RegAddr, u16 Data)
{
return pHandle->Func_WriteReg(pHandle->SlaveAddr, RegAddr, &Data, 1); //写寄存器
}
/*************************************************************************************************************************
*函数 : bool WM8994_Reset(WM8994_HANDLE *pHandle)
*功能 : WM8994 复位(所有寄存器值为默认)
*参数 : pHandle:句柄;
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-19
*最后修改时间 : 2020-02-19
*说明 :
*************************************************************************************************************************/
bool WM8994_Reset(WM8994_HANDLE *pHandle)
{
return WM8994_WriteOneReg(pHandle, 0x000, 0x0000); //寄存器0写入任意值复位WM8994
}
/*************************************************************************************************************************
*函数 : bool WM8994_SetFrequency(WM8994_HANDLE *pHandle, u32 AudioFreq)
*功能 : WM8994 采样率设置
*参数 : pHandle:句柄;AudioFreq:采样率设置值(单位Hz)
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-19
*最后修改时间 : 2020-02-19
*说明 : 只支持:(8KHz~96KHz的标注采样率)8KHz,11.025KHz,12KHz,16KHz,22.05KHz,24KHz,32KHz,44.1KHz,88.2KHz,96KHz
设置的是AIF1接口,并且ratio固定为256
*************************************************************************************************************************/
bool WM8994_SetFrequency(WM8994_HANDLE *pHandle, u32 AudioFreq)
{
u16 tempreg;
switch (AudioFreq)
{
case (8000): tempreg = 0x0003;break; //8KHz
case (11025):tempreg = 0x0013;break; //11.025KHz
case (12000):tempreg = 0x0023;break; //12KHz
case (16000):tempreg = 0x0033;break; //16KHz
case (22050):tempreg = 0x0043;break; //22.05KHz
case (24000):tempreg = 0x0053;break; //24KHz
case (32000):tempreg = 0x0063;break; //32KHz
case (44100):tempreg = 0x0073;break; //44.1KHz
case (48000):tempreg = 0x0083;break; //48KHz
case (88200):tempreg = 0x0093;break; //88.2KHz
case (96000):tempreg = 0x00A3;break; //96KHz
default: //不支持的采样率
{
DEBUG("不支持的采样率:%dHzrn", AudioFreq);
return FALSE;
}break;
}
return WM8994_WriteOneReg(pHandle, 0x210, tempreg);
}
/*************************************************************************************************************************
*函数 : bool WM8994_SetVolume(WM8994_HANDLE *pHandle, WM8994_OUT_MODULE Module, u8 Volume)
*功能 : WM8994 音量设置
*参数 : pHandle:句柄;WM8994_OUT_MODULE:WM8994输出模块,见WM8994_OUT_MODULE;Volume:音量范围0-100
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-19
*最后修改时间 : 2020-02-19
*说明 : 设置音量为0会开启静音,设置音量为其他值则自动关闭静音,耳机1音量设置寄存器为0x1C 0x1D,范围0-63,按比例扩大范围到0-100
*************************************************************************************************************************/
bool WM8994_SetVolume(WM8994_HANDLE *pHandle, WM8994_OUT_MODULE Module, u8 Volume)
{
bool isStatus = FALSE;
u16 RegBuff[2];
if(Volume >= 100) Volume = 63;
else if(Volume > 0) //按照比例计算
{
Volume = Volume * 63 / 100;
}
switch(Module)
{
case WM8994_HPOUT1: //WM8994 耳机1 Headphone HPOUT1 通过0x1C 0x1D设置音量
{
//寄存器0x1C 0x1D控制耳机的左右音量与静音
if(Volume == 0) //声音最小-直接静音-实测发现0x1C 0x1D的耳机静音功能无效,设置后依旧有很小的声音,所以直接调用静音设置
{
WM8994_SetMute(pHandle, Module, TRUE); //静音
RegBuff[0] = RegBuff[1] = 0x0000; //关闭声音,直接静音
RegBuff[1] |= BIT8; //耳机输出PGA音量更新,向该位写入1将同时更新HPOUT1LVOL和HPOUT1RVOL。
}
else
{
WM8994_SetMute(pHandle, Module, FALSE); //取消静音
RegBuff[0] = RegBuff[1] = (Volume & 0x3F) | BIT6; //设置声音并取消静音
RegBuff[1] |= BIT8; //耳机输出PGA音量更新,向该位写入1将同时更新HPOUT1LVOL和HPOUT1RVOL。
}
isStatus = pHandle->Func_WriteReg(pHandle->SlaveAddr, 0x01C, RegBuff, 2);//写入寄存器
}break;
default:break;
}
return isStatus;
}
/*************************************************************************************************************************
*函数 : bool WM8994_EnableDAC(WM8994_HANDLE *pHandle, bool isEnable)
*功能 : WM8994 DAC使能(开启或关闭DAC输出)
*参数 : pHandle:句柄;isEnable:是否使能DAC
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-19
*最后修改时间 : 2020-02-19
*说明 : 0x420 0x422 控制DAC1 DAC2静音,实现关闭DAC功能
用于在没有音乐数据或无效的数据的时候,临时禁用DAC输出,防止DAC有杂音
0x05寄存器可以用于DAC输出使能,1个寄存器功能太多,不适合单独控制(需要读改写操作)
*************************************************************************************************************************/
bool WM8994_EnableDAC(WM8994_HANDLE *pHandle, bool isEnable)
{
if(isEnable) //使能-关闭DAC静音功能
{
WM8994_WriteOneReg(pHandle, 0x420, 0x0000); //关闭DAC1静音
WM8994_WriteOneReg(pHandle, 0x422, 0x0000); //关闭DAC2静音
}
else //关闭DAC,使能DAC静音
{
WM8994_WriteOneReg(pHandle, 0x420, 0X0200); //开启DAC1静音
WM8994_WriteOneReg(pHandle, 0x422, 0X0200); //开启DAC2静音
}
}
/*************************************************************************************************************************
*函数 : bool WM8994_SetMute(WM8994_HANDLE *pHandle, WM8994_OUT_MODULE Module, bool isEnableMute)
*功能 : WM8994 静音设置
*参数 : pHandle:句柄;Module:WM8994内部功能模块,见WM8994_OUT_MODULE;isEnableMute:是否使能静音
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-19
*最后修改时间 : 2020-02-20
*说明 : 0x610 0x611 DAC1的音量与静音设置(默认不使用此处设置音量,保持0db输入输出即可)
0x420 DAC1 数据输入静音设置-也会导致输出静音
0x1C 0x1D 耳机1的输出音量与静音设置(测试发现无法使耳机输出静音)
*************************************************************************************************************************/
bool WM8994_SetMute(WM8994_HANDLE *pHandle, WM8994_OUT_MODULE Module, bool isEnableMute)
{
bool isStatus = FALSE;
u16 RegBuff[2];
switch(Module)
{
case WM8994_HPOUT1: //WM8994 耳机1 Headphone HPOUT1
{
RegBuff[0] = RegBuff[1] = 0xC0; //0db
//寄存器0x610 0x611控制DAC1 达到耳机的左右音量与静音
if(isEnableMute) //使能静音
{
RegBuff[0] |= BIT9; //静音
RegBuff[1] |= BIT9; //静音
}
else
{
RegBuff[0] &= ~BIT9; //取消静音
RegBuff[1] &= ~BIT9; //取消静音
}
isStatus = pHandle->Func_WriteReg(pHandle->SlaveAddr, 0x610, RegBuff, 2);
}break;
default:break;
}
return isStatus;
}
/*************************************************************************************************************************
*函数 : bool WM8994_SetDataBitSize(WM8994_HANDLE *pHandle, WM8994_DATA_BIT_SIZE DataBitSize)
*功能 : WM8994 设置数据位宽(AIF1接口)
*参数 : pHandle:句柄;DataBitSize:数据位宽,见WM8994_DATA_BIT_SIZE
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-20
*最后修改时间 : 2020-02-20
*说明 : 设置数据位宽,通过0x300寄存器的6:5进行配置,配置的是AIF1接口
*************************************************************************************************************************/
bool WM8994_SetDataBitSize(WM8994_HANDLE *pHandle, WM8994_DATA_BIT_SIZE DataBitSize)
{
u16 temp;
if(pHandle->Func_ReadReg(pHandle->SlaveAddr, 0x300, &temp, 1) == FALSE) //读取失败了用默认值
{
temp = 0x4010;
}
temp &= ~(0x03 << 5); //清除之前的配置
temp |= (DataBitSize & 0X03) << 5; //重新设置位宽
return WM8994_WriteOneReg(pHandle, 0x300, temp); //重新写入
}
//使能系统命令行
#if SYS_CMD_EN_
#include "sys_cmd.h"
#include "string.h"
const SYS_CMD_TYPE CMD_WM8994_WR = {"tt写WM8994一个寄存器 W=123 0x1234", TRUE};
//设置一个寄存器(命令调试,方便简单的命令配置WM8994)
void CMD_WM8994_WriteReg(SYS_CMD_HANDLE *pHandle,char *pStr)
{
u16 reg,data;
u8 len;
char *p;
u8 num;
len = strlen(pStr); //获取长度
//寄存器地址
p = strstr(pStr," "); //搜索空格
if(p == NULL)
{
pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数1!rn");
return;
}
num = p - pStr;
if((num > 5) || (num == 0))
{
pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数2!rn");
return;
}
//寄存器地址
reg = SYS_CMD_StringToDec(pStr, num);
if(reg>0xffff)
{
pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数3!rn");
return;
}
//寄存器值
pStr = p+1; //跳过空格
p = strstr(pStr,"0X"); //搜索0X
if(p == NULL)
{
pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数4!rn");
return;
}
pStr = p+strlen("0X"); //跳过前面的3个字节
num = strlen(pStr);
if((num > 4) || (num == 0))
{
pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数5!rn");
return;
}
data = SYS_CMD_StringToHex(pStr, num);
if(data>0xffff)
{
pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数6!rn");
return;
}
pHandle->DataPrintf("[WM8994写]:REG%d=0x%Xt", reg, data);
if(WM8994_WriteOneReg(&g_SysGlobal.mWM8994_Handle, reg, data) == TRUE)
{
pHandle->DataPrintf("成功rn");
}
else
{
pHandle->DataPrintf("失败rn");
}
}
#endif //SYS_CMD_EN_
/*************************************************************************************************************
* 文件名 : WM8994.h
* 功能 : STM32F7 WM8994驱动
* 作者 : cp1300@139.com
* 创建时间 : 2020-02-09
* 最后修改时间 : 2020-02-09
* 详细: 使用的IIC与WM8994通讯
*************************************************************************************************************/
#ifndef __WM8994_H__
#define __WM8994_H__
#include "system.h"
//WM8994 输出模块定义
typedef enum
{
WM8994_HPOUT1 = 0, //WM8994 耳机1 Headphone HPOUT1
}WM8994_OUT_MODULE;
//数据位宽设置
typedef enum
{
WM8994_DATA_SIZE_16BIT = 0, //16bit
WM8994_DATA_SIZE_20BIT = 1, //20bit
WM8994_DATA_SIZE_24BIT = 2, //24bit
WM8994_DATA_SIZE_32BIT = 3, //32bit
}WM8994_DATA_BIT_SIZE;
//WM8994 句柄
typedef struct
{
bool (*Func_ReadReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum); //功能接口-读寄存器
bool (*Func_WriteReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum); //功能接口-写寄存器
u8 SlaveAddr; //通讯地址
}WM8994_HANDLE;
//WM8994初始化
bool WM8994_Init(WM8994_HANDLE *pHandle, u8 SlaveAddr,
bool (*Func_ReadReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum),
bool (*Func_WriteReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum));
bool WM8994_SetVolume(WM8994_HANDLE *pHandle, WM8994_OUT_MODULE Module, u8 Volume); //WM8994 音量设置
bool WM8994_SetMute(WM8994_HANDLE *pHandle, WM8994_OUT_MODULE Module, bool isEnableMute); //WM8994 静音设置
bool WM8994_EnableDAC(WM8994_HANDLE *pHandle, bool isEnable); //WM8994 DAC使能(开启或关闭DAC输出)
bool WM8994_SetFrequency(WM8994_HANDLE *pHandle, u32 AudioFreq); //WM8994 采样率设置
bool WM8994_Reset(WM8994_HANDLE *pHandle); //WM8994 复位(所有寄存器值为默认)
bool WM8994_SetDataBitSize(WM8994_HANDLE *pHandle, WM8994_DATA_BIT_SIZE DataBitSize); //WM8994 设置数据位宽(AIF1接口)
//使能系统命令行
#if SYS_CMD_EN_
#include "sys_cmd.h"
#include "string.h"
extern const SYS_CMD_TYPE CMD_WM8994_WR;
//设置一个寄存器
void CMD_WM8994_WriteReg(SYS_CMD_HANDLE *pHandle,char *pStr);
#endif //SYS_CMD_EN_
#endif //__WM8994_H__
初始化(先初始化IIC接口)
//初始化硬件IIC-注意硬件IIC与软件IIC共用IO,不能重复使用与初始化
IIC_Init(IIC_CH3, 200, 0); //硬件IIC初始化
//软件IIC初始化
/*if(SIIC_Init(&g_SysGlobal.mIIC_Handle, GPIOH, GPIOH, 8, 7, 2) == FALSE)
{
DEBUG("软件IIC初始化失败!rn");
}*/
所需的IIC寄存器读写接口(注意WM8994的寄存器均是16bit的)
//WM8994IIC读取寄存器接口-16bit地址与16bit寄存器
bool WM8994_IIC_ReadReg(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum)
{
u8 i;
if(IIC_MasterReadReg(FT5336_IIC_CH, SlaveAddr, RegAddr, FALSE, (u8 *)pDataBuff, RegNum*2) == IIC_OK)
{
for(i = 0;i < RegNum;i ++) //进行高低字节对调
{
pDataBuff = SWAP16(pDataBuff);
}
return TRUE;
}
else
{
return FALSE;
}
}
//WM8994 IIC写寄存器接口-16bit地址与16bit寄存器
bool WM8994_IIC_WriteReg(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum)
{
u8 i;
for(i = 0;i < RegNum;i ++) //进行高低字节对调
{
pDataBuff = SWAP16(pDataBuff);
}
if(IIC_MasterWriteReg(FT5336_IIC_CH, SlaveAddr, RegAddr, FALSE, (u8 *)pDataBuff, RegNum*2) == IIC_OK)
{
return TRUE;
}
else
{
return FALSE;
}
}
//初始化
bool isStatus = WM8994_Init(&g_SysGlobal.mWM8994_Handle, 0x34, WM8994_IIC_ReadReg, WM8994_IIC_WriteReg);
最后的联调会与SAI驱动一起给出。
描述
- WM8994 是一款高度集成的超低功耗高保真 CODEC,专为智能手机和其他具有丰富多媒体功能的便携式设备而设计。
- 集成的立体声 D/AB 扬声器驱动器和 W 类耳机驱动器,可最大限度降低音频播放期间的功耗。
- 该器件只需要两个电压电源,所有其他内部电源均由集成 LDO 生成。
- 立体声全双工异步采样率转换和多通道数字混合,加上强大的模拟混合功能,使器件能够支持各种不同的架构和用例。
- 完全可编程参数均衡器提供扬声器补偿,ADC 或 DAC 路径中可以使用动态范围控制器,用于保持恒定的信号电平、最大限度地提高响度并保护扬声器免受过载和截止失真。
- 智能数字麦克风接口提供功率调节、低抖动时钟输出和多达四个数字麦克风的抽取滤波器。 MIC 活动检测可以触发中断。
- 有源接地环路噪声抑制和直流偏置校正有助于防止爆裂噪音,并抑制耳机输出上的接地噪声。
特征
- 高保真 24 位 4 通道 DAC 和 2 通道 ADC
- DAC 播放期间的 100dB SNR('A' 加权)
- 智能 MIC 接口 电源、时钟和数据输入,可存储多达四个数字高性能 MIC /模拟 MIC 接口/ MIC 活动监视器 + 中断/允许处理器休眠
- 1W 立体声 / 2W 单声道 D/AB 扬声器驱动器
- W 类耳机驱动器 集成充电泵 6mW 总功率,用于 DAC 播放至耳机
- 4 线输出(单端或差分)
- BTL 耳机驱动器
- 用于多处理器架构的数字音频接口异步立体声双工采样率转换 强大的混音和数字环回功能
- ReTuneTM 移动 5 频段、6 通道参数均衡器
- 可编程动态范围控制器
- 双 FLL 提供所有必要的时钟自时钟模式,允许处理器休眠所有标准采样速率,从 8kHz 到 96kHz
- 有源降噪电路直流偏置校正可消除爆裂声和咔嗒声,并消除接地环路噪声消除
- 集成 LDO 调节器
- 72 球(脚) W-CSP 封装(4.511 x 4.023 x 0.7mm)
总体框图
开发板实际应用电路图
接口支持
4路单/差分麦克风,3路I2S/PCM接口,1路立体声耳机接口,1路单声道差分耳机接口,1路喇叭(手机听筒),1路立体声喇叭。
1.调试准备
首先准备的是使用软件IIC接口进行通信(先用软件IIC调试成功后再移植硬件IIC,降低调试难度)。
IIC使用的是PH8(SDA),PH7(SCL),地址为0x34,初始化软件IIC接口
2.关于IIC接口
WM8994文档中写的很清楚,当CIFMODE接地时为IIC通信方式(应该大部分都是使用IIC通信),但是我按照手册上面的时序,发现读写都正常,就是读取的数据一直是FF,而且能正常收到ACK,如果随便改一个地址就会通信失败,证明读写是对的,但是折腾了几天发现读取的数据一直是FF,最后查明原因无论是软件还是硬件IIC,输出都得是开漏输出才行。
通信接口配置
寄存器很多,平时使用就几个寄存器,就初始化时麻烦,但是这个软件WISCE能一键给你搞定。
软件使用比较简单,上面有下载链接,自己可以折腾一下,我使用的是第一个配置,AF1 输出HPOUT1,底部就会显示要设置的寄存器与值。
以下是具体的驱动代码(只实现了HPOUT1 也就是耳机1输出所需的接口)
/*************************************************************************************************************
* 文件名 : WM8994.c
* 功能 : STM32F7 WM8994驱动
* 作者 : cp1300@139.com
* 创建时间 : 2020-02-18
* 最后修改时间 : 2020-02-19
* 详细: 使用的IIC与WM8994通讯
注意:关闭写寄存器与SYS_CLK同步,否则如果没有提供MCLK时钟并配置SYS_CLK会导致写入的寄存器无效,建议关闭掉
如果不关闭一定要先将SAI初始化完成,并提供MCLK时钟,否则对WM8994的寄存器配置将无效
正常使用先调用WM8994_Init(),然后初始化好SAI并输出音频数据,调用WM8994_SetFrequency()设置采样率,
WM8994_SetDataBitSize()设置位宽,最后WM8994_EnableDAC()使能DAC
*************************************************************************************************************/
#include "stm32f7xx.h"
#include "system.h"
#include "main.h"
#include "WM8994.h"
#include "SoftwareIIC.h"
const u16 WM8994_INIT_REG_TABLE[][2] =
{
//全自动的AIF1设置
{0x000, 0x0000}, //寄存器0写入任意数据将会导致芯片复位,复位后请第一时间关闭写同步0x101寄存器写0x0004(只开启IIC读指针自增模式)
{0xFFFF, 1}, //0Xffff代表延时,延时1ms
{0x101, 0x0004}, //关闭写寄存器与SYS_CLK同步,否则如果没有提供MCLK时钟并配置SYS_CLK会导致写入的寄存器无效,建议关闭掉
{0xFFFF, 1}, //0Xffff代表延时,延时1ms
{0x420, 0X0200}, //AIF1 Slot0 DAC1 L/R静音-默认不让任何声音输出,正常使用时请调用WM8994_EnableDAC()使能DAC
{0x422, 0X0200}, //AIF1 Slot1 DAC2 L/R取消静音-默认不让任何声音输出,正常使用时请调用WM8994_EnableDAC()使能DAC
{0x102, 0x0003},
{0x817, 0x0000},
{0x102, 0x0000},
{0x39, 0x0064},
{0x01, 0x0003},
{0xFFFF, 50}, //0Xffff代表延时,延时50ms
{0x601, 0x0001},
{0x602, 0x0001},
{0x210, 0x0083}, //采样时钟设置48KHz
{0x300, 0x4010}, //AIF1接口格式设置I2S:标准的I2S数据格式
{0x302, 0x0000}, //从机模式
{0x208, 0x000A}, //时钟使能-不开启PLL,因为单片机直接提供了有效的MCLK时钟(256倍的采样频率)
{0x200, 0x0001}, //AIF1CLK启用,不分频,使用MCLK1作为AIF1CLK时钟源
{0x51, 0x0005},
{0x01, 0x0303},
{0x60, 0x0022}, //启用HPOUT1输出,耳机1输出使能,先使能,然后延时
{0x4C, 0x9F25},
{0xFFFF, 15}, //0Xffff代表延时,延时15ms
{0x05, 0x0303},
{0x2D, 0x0001},
{0x2E, 0x0001},
{0x03, 0x0030},
{0x54, 0x0033},
{0xFFFF, 250}, //0Xffff代表延时,延时250ms
{0x60, 0x00EE}, //HPOUT1输出短路移除,中间级启用-驱动能力会变强
{0x610, 0x00C0}, //DAC1L取消静音-音量设置0db
{0x611, 0x00C0}, //DAC1R取消静音-音量设置0db
//{0x420, 0x0000}, //AIF1 Slot0 DAC1 L/R取消静音
//{0x422, 0x0000}, //AIF1 Slot1 DAC2 L/R取消静音
};
static bool WM8994_WriteOneReg(WM8994_HANDLE *pHandle, u16 RegAddr, u16 Data);//WM8994 写入一个寄存器值
/*************************************************************************************************************************
*函数 : bool WM8994_Init(WM8994_HANDLE *pHandle, u8 SlaveAddr,
bool (*Func_ReadReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum),
bool (*Func_WriteReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum))
*功能 : WM8994初始化
*参数 : pHandle:句柄;SlaveAddr通讯地址;Func_ReadReg:读寄存器接口;Func_WriteReg:写寄存器接口
*返回 : TRUE:初始化成功;FALSE:初始化失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-01-30
*最后修改时间 : 2020-01-30
*说明 : 需要先提前初始化IIC接口
*************************************************************************************************************************/
bool WM8994_Init(WM8994_HANDLE *pHandle, u8 SlaveAddr,
bool (*Func_ReadReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum),
bool (*Func_WriteReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum))
{
u16 temp;
u8 retry = 0;
u16 i = 0;
u16 addr;
if(pHandle == NULL) return FALSE;
pHandle->SlaveAddr = SlaveAddr; //通讯地址
pHandle->Func_ReadReg = Func_ReadReg; //读寄存器接口
pHandle->Func_WriteReg = Func_WriteReg; //写寄存器接口
WM8994_WriteOneReg(pHandle, 0, 1); //写寄存器0,任意值导致WM8994复位
SYS_DelayMS(1);
if(pHandle->Func_ReadReg(pHandle->SlaveAddr, 0, &temp, 1) == TRUE) //读取寄存器0,id
{
uart_printf("WM8994 id:0x%04Xrn",temp);
}
else
{
uart_printf("读取WM8994 id失败rn");
}
//寄存器初始化
for(i = 0;i < sizeof(WM8994_INIT_REG_TABLE)/2/2;i ++)
{
addr = WM8994_INIT_REG_TABLE[0];
temp = WM8994_INIT_REG_TABLE[1];
if(addr == 0xFFFF) //代表延时
{
SYS_DelayMS(temp);
continue;
}
uart_printf("WM8994 REG 0x%04X->0x%04Xrn", addr, temp);
WM8994_WriteOneReg(pHandle, addr, temp); //写入寄存器
}
WM8994_SetVolume(pHandle, WM8994_HPOUT1, 30); //设置声音-注意默认的声音特别大,这里设置稍微小点
return TRUE;
}
/*************************************************************************************************************************
*函数 : bool WM8994_WriteOneReg(WM8994_HANDLE *pHandle, u16 RegAddr, u16 Data)
*功能 : WM8994 写入一个寄存器值
*参数 : pHandle:句柄;AudioFreq:RegAddr:寄存器地址;Data:数据
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-19
*最后修改时间 : 2020-02-19
*说明 :
*************************************************************************************************************************/
bool WM8994_WriteOneReg(WM8994_HANDLE *pHandle, u16 RegAddr, u16 Data)
{
return pHandle->Func_WriteReg(pHandle->SlaveAddr, RegAddr, &Data, 1); //写寄存器
}
/*************************************************************************************************************************
*函数 : bool WM8994_Reset(WM8994_HANDLE *pHandle)
*功能 : WM8994 复位(所有寄存器值为默认)
*参数 : pHandle:句柄;
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-19
*最后修改时间 : 2020-02-19
*说明 :
*************************************************************************************************************************/
bool WM8994_Reset(WM8994_HANDLE *pHandle)
{
return WM8994_WriteOneReg(pHandle, 0x000, 0x0000); //寄存器0写入任意值复位WM8994
}
/*************************************************************************************************************************
*函数 : bool WM8994_SetFrequency(WM8994_HANDLE *pHandle, u32 AudioFreq)
*功能 : WM8994 采样率设置
*参数 : pHandle:句柄;AudioFreq:采样率设置值(单位Hz)
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-19
*最后修改时间 : 2020-02-19
*说明 : 只支持:(8KHz~96KHz的标注采样率)8KHz,11.025KHz,12KHz,16KHz,22.05KHz,24KHz,32KHz,44.1KHz,88.2KHz,96KHz
设置的是AIF1接口,并且ratio固定为256
*************************************************************************************************************************/
bool WM8994_SetFrequency(WM8994_HANDLE *pHandle, u32 AudioFreq)
{
u16 tempreg;
switch (AudioFreq)
{
case (8000): tempreg = 0x0003;break; //8KHz
case (11025):tempreg = 0x0013;break; //11.025KHz
case (12000):tempreg = 0x0023;break; //12KHz
case (16000):tempreg = 0x0033;break; //16KHz
case (22050):tempreg = 0x0043;break; //22.05KHz
case (24000):tempreg = 0x0053;break; //24KHz
case (32000):tempreg = 0x0063;break; //32KHz
case (44100):tempreg = 0x0073;break; //44.1KHz
case (48000):tempreg = 0x0083;break; //48KHz
case (88200):tempreg = 0x0093;break; //88.2KHz
case (96000):tempreg = 0x00A3;break; //96KHz
default: //不支持的采样率
{
DEBUG("不支持的采样率:%dHzrn", AudioFreq);
return FALSE;
}break;
}
return WM8994_WriteOneReg(pHandle, 0x210, tempreg);
}
/*************************************************************************************************************************
*函数 : bool WM8994_SetVolume(WM8994_HANDLE *pHandle, WM8994_OUT_MODULE Module, u8 Volume)
*功能 : WM8994 音量设置
*参数 : pHandle:句柄;WM8994_OUT_MODULE:WM8994输出模块,见WM8994_OUT_MODULE;Volume:音量范围0-100
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-19
*最后修改时间 : 2020-02-19
*说明 : 设置音量为0会开启静音,设置音量为其他值则自动关闭静音,耳机1音量设置寄存器为0x1C 0x1D,范围0-63,按比例扩大范围到0-100
*************************************************************************************************************************/
bool WM8994_SetVolume(WM8994_HANDLE *pHandle, WM8994_OUT_MODULE Module, u8 Volume)
{
bool isStatus = FALSE;
u16 RegBuff[2];
if(Volume >= 100) Volume = 63;
else if(Volume > 0) //按照比例计算
{
Volume = Volume * 63 / 100;
}
switch(Module)
{
case WM8994_HPOUT1: //WM8994 耳机1 Headphone HPOUT1 通过0x1C 0x1D设置音量
{
//寄存器0x1C 0x1D控制耳机的左右音量与静音
if(Volume == 0) //声音最小-直接静音-实测发现0x1C 0x1D的耳机静音功能无效,设置后依旧有很小的声音,所以直接调用静音设置
{
WM8994_SetMute(pHandle, Module, TRUE); //静音
RegBuff[0] = RegBuff[1] = 0x0000; //关闭声音,直接静音
RegBuff[1] |= BIT8; //耳机输出PGA音量更新,向该位写入1将同时更新HPOUT1LVOL和HPOUT1RVOL。
}
else
{
WM8994_SetMute(pHandle, Module, FALSE); //取消静音
RegBuff[0] = RegBuff[1] = (Volume & 0x3F) | BIT6; //设置声音并取消静音
RegBuff[1] |= BIT8; //耳机输出PGA音量更新,向该位写入1将同时更新HPOUT1LVOL和HPOUT1RVOL。
}
isStatus = pHandle->Func_WriteReg(pHandle->SlaveAddr, 0x01C, RegBuff, 2);//写入寄存器
}break;
default:break;
}
return isStatus;
}
/*************************************************************************************************************************
*函数 : bool WM8994_EnableDAC(WM8994_HANDLE *pHandle, bool isEnable)
*功能 : WM8994 DAC使能(开启或关闭DAC输出)
*参数 : pHandle:句柄;isEnable:是否使能DAC
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-19
*最后修改时间 : 2020-02-19
*说明 : 0x420 0x422 控制DAC1 DAC2静音,实现关闭DAC功能
用于在没有音乐数据或无效的数据的时候,临时禁用DAC输出,防止DAC有杂音
0x05寄存器可以用于DAC输出使能,1个寄存器功能太多,不适合单独控制(需要读改写操作)
*************************************************************************************************************************/
bool WM8994_EnableDAC(WM8994_HANDLE *pHandle, bool isEnable)
{
if(isEnable) //使能-关闭DAC静音功能
{
WM8994_WriteOneReg(pHandle, 0x420, 0x0000); //关闭DAC1静音
WM8994_WriteOneReg(pHandle, 0x422, 0x0000); //关闭DAC2静音
}
else //关闭DAC,使能DAC静音
{
WM8994_WriteOneReg(pHandle, 0x420, 0X0200); //开启DAC1静音
WM8994_WriteOneReg(pHandle, 0x422, 0X0200); //开启DAC2静音
}
}
/*************************************************************************************************************************
*函数 : bool WM8994_SetMute(WM8994_HANDLE *pHandle, WM8994_OUT_MODULE Module, bool isEnableMute)
*功能 : WM8994 静音设置
*参数 : pHandle:句柄;Module:WM8994内部功能模块,见WM8994_OUT_MODULE;isEnableMute:是否使能静音
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-19
*最后修改时间 : 2020-02-20
*说明 : 0x610 0x611 DAC1的音量与静音设置(默认不使用此处设置音量,保持0db输入输出即可)
0x420 DAC1 数据输入静音设置-也会导致输出静音
0x1C 0x1D 耳机1的输出音量与静音设置(测试发现无法使耳机输出静音)
*************************************************************************************************************************/
bool WM8994_SetMute(WM8994_HANDLE *pHandle, WM8994_OUT_MODULE Module, bool isEnableMute)
{
bool isStatus = FALSE;
u16 RegBuff[2];
switch(Module)
{
case WM8994_HPOUT1: //WM8994 耳机1 Headphone HPOUT1
{
RegBuff[0] = RegBuff[1] = 0xC0; //0db
//寄存器0x610 0x611控制DAC1 达到耳机的左右音量与静音
if(isEnableMute) //使能静音
{
RegBuff[0] |= BIT9; //静音
RegBuff[1] |= BIT9; //静音
}
else
{
RegBuff[0] &= ~BIT9; //取消静音
RegBuff[1] &= ~BIT9; //取消静音
}
isStatus = pHandle->Func_WriteReg(pHandle->SlaveAddr, 0x610, RegBuff, 2);
}break;
default:break;
}
return isStatus;
}
/*************************************************************************************************************************
*函数 : bool WM8994_SetDataBitSize(WM8994_HANDLE *pHandle, WM8994_DATA_BIT_SIZE DataBitSize)
*功能 : WM8994 设置数据位宽(AIF1接口)
*参数 : pHandle:句柄;DataBitSize:数据位宽,见WM8994_DATA_BIT_SIZE
*返回 : TRUE:成功;FALSE:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2020-02-20
*最后修改时间 : 2020-02-20
*说明 : 设置数据位宽,通过0x300寄存器的6:5进行配置,配置的是AIF1接口
*************************************************************************************************************************/
bool WM8994_SetDataBitSize(WM8994_HANDLE *pHandle, WM8994_DATA_BIT_SIZE DataBitSize)
{
u16 temp;
if(pHandle->Func_ReadReg(pHandle->SlaveAddr, 0x300, &temp, 1) == FALSE) //读取失败了用默认值
{
temp = 0x4010;
}
temp &= ~(0x03 << 5); //清除之前的配置
temp |= (DataBitSize & 0X03) << 5; //重新设置位宽
return WM8994_WriteOneReg(pHandle, 0x300, temp); //重新写入
}
//使能系统命令行
#if SYS_CMD_EN_
#include "sys_cmd.h"
#include "string.h"
const SYS_CMD_TYPE CMD_WM8994_WR = {"tt写WM8994一个寄存器 W=123 0x1234", TRUE};
//设置一个寄存器(命令调试,方便简单的命令配置WM8994)
void CMD_WM8994_WriteReg(SYS_CMD_HANDLE *pHandle,char *pStr)
{
u16 reg,data;
u8 len;
char *p;
u8 num;
len = strlen(pStr); //获取长度
//寄存器地址
p = strstr(pStr," "); //搜索空格
if(p == NULL)
{
pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数1!rn");
return;
}
num = p - pStr;
if((num > 5) || (num == 0))
{
pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数2!rn");
return;
}
//寄存器地址
reg = SYS_CMD_StringToDec(pStr, num);
if(reg>0xffff)
{
pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数3!rn");
return;
}
//寄存器值
pStr = p+1; //跳过空格
p = strstr(pStr,"0X"); //搜索0X
if(p == NULL)
{
pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数4!rn");
return;
}
pStr = p+strlen("0X"); //跳过前面的3个字节
num = strlen(pStr);
if((num > 4) || (num == 0))
{
pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数5!rn");
return;
}
data = SYS_CMD_StringToHex(pStr, num);
if(data>0xffff)
{
pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数6!rn");
return;
}
pHandle->DataPrintf("[WM8994写]:REG%d=0x%Xt", reg, data);
if(WM8994_WriteOneReg(&g_SysGlobal.mWM8994_Handle, reg, data) == TRUE)
{
pHandle->DataPrintf("成功rn");
}
else
{
pHandle->DataPrintf("失败rn");
}
}
#endif //SYS_CMD_EN_
/*************************************************************************************************************
* 文件名 : WM8994.h
* 功能 : STM32F7 WM8994驱动
* 作者 : cp1300@139.com
* 创建时间 : 2020-02-09
* 最后修改时间 : 2020-02-09
* 详细: 使用的IIC与WM8994通讯
*************************************************************************************************************/
#ifndef __WM8994_H__
#define __WM8994_H__
#include "system.h"
//WM8994 输出模块定义
typedef enum
{
WM8994_HPOUT1 = 0, //WM8994 耳机1 Headphone HPOUT1
}WM8994_OUT_MODULE;
//数据位宽设置
typedef enum
{
WM8994_DATA_SIZE_16BIT = 0, //16bit
WM8994_DATA_SIZE_20BIT = 1, //20bit
WM8994_DATA_SIZE_24BIT = 2, //24bit
WM8994_DATA_SIZE_32BIT = 3, //32bit
}WM8994_DATA_BIT_SIZE;
//WM8994 句柄
typedef struct
{
bool (*Func_ReadReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum); //功能接口-读寄存器
bool (*Func_WriteReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum); //功能接口-写寄存器
u8 SlaveAddr; //通讯地址
}WM8994_HANDLE;
//WM8994初始化
bool WM8994_Init(WM8994_HANDLE *pHandle, u8 SlaveAddr,
bool (*Func_ReadReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum),
bool (*Func_WriteReg)(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum));
bool WM8994_SetVolume(WM8994_HANDLE *pHandle, WM8994_OUT_MODULE Module, u8 Volume); //WM8994 音量设置
bool WM8994_SetMute(WM8994_HANDLE *pHandle, WM8994_OUT_MODULE Module, bool isEnableMute); //WM8994 静音设置
bool WM8994_EnableDAC(WM8994_HANDLE *pHandle, bool isEnable); //WM8994 DAC使能(开启或关闭DAC输出)
bool WM8994_SetFrequency(WM8994_HANDLE *pHandle, u32 AudioFreq); //WM8994 采样率设置
bool WM8994_Reset(WM8994_HANDLE *pHandle); //WM8994 复位(所有寄存器值为默认)
bool WM8994_SetDataBitSize(WM8994_HANDLE *pHandle, WM8994_DATA_BIT_SIZE DataBitSize); //WM8994 设置数据位宽(AIF1接口)
//使能系统命令行
#if SYS_CMD_EN_
#include "sys_cmd.h"
#include "string.h"
extern const SYS_CMD_TYPE CMD_WM8994_WR;
//设置一个寄存器
void CMD_WM8994_WriteReg(SYS_CMD_HANDLE *pHandle,char *pStr);
#endif //SYS_CMD_EN_
#endif //__WM8994_H__
初始化(先初始化IIC接口)
//初始化硬件IIC-注意硬件IIC与软件IIC共用IO,不能重复使用与初始化
IIC_Init(IIC_CH3, 200, 0); //硬件IIC初始化
//软件IIC初始化
/*if(SIIC_Init(&g_SysGlobal.mIIC_Handle, GPIOH, GPIOH, 8, 7, 2) == FALSE)
{
DEBUG("软件IIC初始化失败!rn");
}*/
所需的IIC寄存器读写接口(注意WM8994的寄存器均是16bit的)
//WM8994IIC读取寄存器接口-16bit地址与16bit寄存器
bool WM8994_IIC_ReadReg(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum)
{
u8 i;
if(IIC_MasterReadReg(FT5336_IIC_CH, SlaveAddr, RegAddr, FALSE, (u8 *)pDataBuff, RegNum*2) == IIC_OK)
{
for(i = 0;i < RegNum;i ++) //进行高低字节对调
{
pDataBuff = SWAP16(pDataBuff);
}
return TRUE;
}
else
{
return FALSE;
}
}
//WM8994 IIC写寄存器接口-16bit地址与16bit寄存器
bool WM8994_IIC_WriteReg(u16 SlaveAddr, u16 RegAddr, u16 *pDataBuff, u16 RegNum)
{
u8 i;
for(i = 0;i < RegNum;i ++) //进行高低字节对调
{
pDataBuff = SWAP16(pDataBuff);
}
if(IIC_MasterWriteReg(FT5336_IIC_CH, SlaveAddr, RegAddr, FALSE, (u8 *)pDataBuff, RegNum*2) == IIC_OK)
{
return TRUE;
}
else
{
return FALSE;
}
}
//初始化
bool isStatus = WM8994_Init(&g_SysGlobal.mWM8994_Handle, 0x34, WM8994_IIC_ReadReg, WM8994_IIC_WriteReg);
最后的联调会与SAI驱动一起给出。
举报
更多回帖