WM8994驱动 STM32 WM8994驱动( STM32f746gdiscovery WM8994驱动)

描述

  • 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接口(软件IIC见:https://blog.csdn.net/cp1300/article/details/75644988

 

 

2.关于IIC接口

WM8994文档中写的很清楚,当CIFMODE接地时为IIC通信方式(应该大部分都是使用IIC通信),但是我按照手册上面的时序,发现读写都正常,就是读取的数据一直是FF,而且能正常收到ACK,如果随便改一个地址就会通信失败,证明读写是对的,但是折腾了几天发现读取的数据一直是FF,最后查明原因无论是软件还是硬件IIC,输出都得是开漏输出才行。

通信接口配置

 

 

读写时序

 

  1. 寄存器的配置(依赖IIC驱动),寄存器列表见:https://blog.csdn.net/cp1300/article/details/104293449

软件IIC支持见:https://blog.csdn.net/cp1300/article/details/75644988

硬件IIC支持见:https://blog.csdn.net/cp1300/article/details/104347417

最新版WM8994手册:https://download.csdn.net/download/cp1300/12154990

WM8994寄存器设置软件(WISCESetup WM8994配置软件):https://download.csdn.net/download/cp1300/12172239

寄存器很多,平时使用就几个寄存器,就初始化时麻烦,但是这个软件WISCE能一键给你搞定。

软件使用比较简单,上面有下载链接,自己可以折腾一下,我使用的是第一个配置,AF1 输出HPOUT1,底部就会显示要设置的寄存器与值。

以下是具体的驱动代码(只实现了HPOUT1 也就是耳机1输出所需的接口)

/*************************************************************************************************************
 * 文件名		:	WM8994.c
 * 功能			:	STM32F7 WM8994驱动
 * 作者			:	[email protected]
 * 创建时间		:	2020-02-18
 * 最后修改时间	:	2020-02-19
 * 详细:			使用的IIC与WM8994通讯
					注意:关闭写寄存器与SYS_CLK同步,否则如果没有提供MCLK时钟并配置SYS_CLK会导致写入的寄存器无效,建议关闭掉
							如果不关闭一定要先将SAI初始化完成,并提供MCLK时钟,否则对WM8994的寄存器配置将无效
					正常使用先调用WM8994_Init(),然后初始化好SAI并输出音频数据,调用WM8994_SetFrequency()设置采样率,最后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:初始化失败
*依赖			: 	底层宏定义
*作者       	:	[email protected]
*时间     		:	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%04X\r\n",temp);
	}
	else
	{
		uart_printf("读取WM8994 id失败\r\n");
	}
	
	//寄存器初始化
	for(i = 0;i < sizeof(WM8994_INIT_REG_TABLE)/2/2;i ++)
	{
		addr = WM8994_INIT_REG_TABLE[i][0];
		temp  = WM8994_INIT_REG_TABLE[i][1];
		if(addr == 0xFFFF)	//代表延时
		{
			SYS_DelayMS(temp);
			continue;
		}
		uart_printf("WM8994 REG 0x%04X->0x%04X\r\n", addr, temp);
		WM8994_WriteOneReg(pHandle, addr, temp);					//写入寄存器
	}
	
	return TRUE;
}


/*************************************************************************************************************************
*函数        	:	bool WM8994_WriteOneReg(WM8994_HANDLE *pHandle, u16 RegAddr, u16 Data)	
*功能        	:	WM8994 写入一个寄存器值
*参数        	:	pHandle:句柄;AudioFreq:RegAddr:寄存器地址;Data:数据
*返回        	:	TRUE:成功;FALSE:失败
*依赖			: 	底层宏定义
*作者       	:	[email protected]
*时间     		:	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:失败
*依赖			: 	底层宏定义
*作者       	:	[email protected]
*时间     		:	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:失败
*依赖			: 	底层宏定义
*作者       	:	[email protected]
*时间     		:	2020-02-19
*最后修改时间	:	2020-02-19
*说明        	:	只支持:(8KHz~96KHz的标注采样率)8KHz,11.025KHz,16KHz,22.05KHz,32KHz,44.1KHz,96KHz
					设置的是AIF1接口,并且ratio固定为256
*************************************************************************************************************************/
bool WM8994_SetFrequency(WM8994_HANDLE *pHandle, u32 AudioFreq)
{
	bool isStatus = FALSE;

	switch (AudioFreq) 
	{
		case  WM8994_AUDIO_FREQUENCY_8K:	//AIF1 Sample Rate = 8 (KHz), ratio=256
		{
			isStatus = WM8994_WriteOneReg(pHandle, 0x210, 0x0003);
		}break;
		case  WM8994_AUDIO_FREQUENCY_11K:	//AIF1 Sample Rate = 11.025 (KHz), ratio=256
		{
		   isStatus = WM8994_WriteOneReg(pHandle, 0x210, 0x0013);
		}break;
		case  WM8994_AUDIO_FREQUENCY_12K:	//AIF1 Sample Rate = 12 (KHz), ratio=256
		{
		   isStatus = WM8994_WriteOneReg(pHandle, 0x210, 0x0023);
		}break;		
		case WM8994_AUDIO_FREQUENCY_16K:	//AIF1 Sample Rate = 16 (KHz), ratio=256
		{
			isStatus = WM8994_WriteOneReg(pHandle, 0x210, 0x0033);
		}break;
		case  WM8994_AUDIO_FREQUENCY_22K:	//AIF1 Sample Rate = 22.050 (KHz), ratio=256
		{
			isStatus = WM8994_WriteOneReg(pHandle, 0x210, 0x0043);
		}break;
		case  WM8994_AUDIO_FREQUENCY_24K:	//AIF1 Sample Rate = 24.000 (KHz), ratio=256
		{
			isStatus = WM8994_WriteOneReg(pHandle, 0x210, 0x0053);
		}break;
		case  WM8994_AUDIO_FREQUENCY_32K:	//AIF1 Sample Rate = 32.000 (KHz), ratio=256
		{
			isStatus = WM8994_WriteOneReg(pHandle, 0x210, 0x0063);
		}break;
		case  WM8994_AUDIO_FREQUENCY_44_1K:	//AIF1 Sample Rate = 44.1 (KHz), ratio=256
		{
			isStatus = WM8994_WriteOneReg(pHandle, 0x210, 0x0073);
		}break;
		case  WM8994_AUDIO_FREQUENCY_48K:	//AIF1 Sample Rate = 48 (KHz), ratio=256
		{
			isStatus = WM8994_WriteOneReg(pHandle, 0x210, 0x0083);
		}break;
		case  WM8994_AUDIO_FREQUENCY_88_2K:	//AIF1 Sample Rate = 88.2 (KHz), ratio=256
		{
			isStatus = WM8994_WriteOneReg(pHandle, 0x210, 0x0093);
		}break;
		case  WM8994_AUDIO_FREQUENCY_96K:	//AIF1 Sample Rate = 96 (KHz), ratio=256
		{
			isStatus = WM8994_WriteOneReg(pHandle, 0x210, 0x00A3);
		}break;
		default:	//不支持的采样率
		{			
			DEBUG("不支持的采样率:%dHz\r\n", AudioFreq);
			isStatus = FALSE;
		}break;
	}
	return isStatus;
}




/*************************************************************************************************************************
*函数        	:	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:失败
*依赖			: 	底层宏定义
*作者       	:	[email protected]
*时间     		:	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)			//声音最小-直接静音
			{
				RegBuff[0] = RegBuff[1] = 0x0000;					//关闭声音,直接静音
				RegBuff[1] |= BIT8;									//耳机输出PGA音量更新,向该位写入1将同时更新HPOUT1LVOL和HPOUT1RVOL。
			}
			else
			{
				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:失败
*依赖			: 	底层宏定义
*作者       	:	[email protected]
*时间     		:	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:失败
*依赖			: 	底层宏定义
*作者       	:	[email protected]
*时间     		:	2020-02-19
*最后修改时间	:	2020-02-19
*说明        	:	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
		{
			//寄存器0x1C 0x1D控制耳机的左右音量与静音,设置的时候先读取数据,修改后写入进去
			if(pHandle->Func_ReadReg(pHandle->SlaveAddr, 0x01C, RegBuff, 2) == FALSE)	//读取失败了使用默认值
			{
				RegBuff[0] = RegBuff[1] = 0x2D;
			}
			if(isEnableMute)	//使能静音
			{
				RegBuff[0]  &= ~BIT6;	//静音
				RegBuff[1]  &= ~BIT6;	//静音
			}
			else
			{
				RegBuff[0]  |= BIT6;	//取消静音
				RegBuff[1]  |= BIT6;	//取消静音
			}
			isStatus = pHandle->Func_WriteReg(pHandle->SlaveAddr, 0x01C, RegBuff, 2);
		}break;
		default:break;
	}
	
	return isStatus;
}


//使能系统命令行
#if SYS_CMD_EN_
#include "sys_cmd.h"
#include "string.h"

const SYS_CMD_TYPE  CMD_WM8994_WR		=	{"W=", CMD_WM8994_WriteReg, "\t\t写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!\r\n");
		return;
	}
	num = p - pStr;
	if((num > 5) || (num == 0))
	{
		pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数2!\r\n");
		return;
	}
	//寄存器地址
	reg = SYS_CMD_StringToDec(pStr, num);
	if(reg>0xffff)
	{
		pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数3!\r\n");
		return;
	}
	
	//寄存器值
	pStr = p+1;				//跳过空格
	p = strstr(pStr,"0X");	//搜索0X
	
	if(p == NULL)
	{
		pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数4!\r\n");
		return;
	}
	pStr = p+strlen("0X");	//跳过前面的3个字节
	num = strlen(pStr);
	if((num > 4) || (num == 0))
	{
		pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数5!\r\n");
		return;
	}
	data = SYS_CMD_StringToHex(pStr, num);
	if(data>0xffff)
	{
		pHandle->DataPrintf("[WM8994写错误]:格式不对或非法参数6!\r\n");
		return;
	}
	
	pHandle->DataPrintf("[WM8994写]:REG%d=0x%X\t", reg, data);
	if(WM8994_WriteOneReg(&g_SysGlobal.mWM8994_Handle, reg, data) == TRUE)
	{
		pHandle->DataPrintf("成功\r\n");
	}
	else
	{
		pHandle->DataPrintf("失败\r\n");
	}	
} 



#endif //SYS_CMD_EN_

 

/*************************************************************************************************************
 * 文件名		:	WM8994.h
 * 功能			:	STM32F7 WM8994驱动
 * 作者			:	[email protected]
 * 创建时间		:	2020-02-09
 * 最后修改时间	:	2020-02-09
 * 详细:			使用的IIC与WM8994通讯
*************************************************************************************************************/	
#ifndef __WM8994_H__
#define __WM8994_H__
#include "system.h"

//WM8994 播放音频采样率定义列表
#define WM8994_AUDIO_FREQUENCY_96K           ((u32)96000)	//96KHz
#define WM8994_AUDIO_FREQUENCY_88_2K         ((u32)88200)	//88.2KHz
#define WM8994_AUDIO_FREQUENCY_48K           ((u32)48000)	//48KHz
#define WM8994_AUDIO_FREQUENCY_44_1K         ((u32)44100)	//44.1KHz
#define WM8994_AUDIO_FREQUENCY_32K           ((u32)32000)	//32KHz
#define WM8994_AUDIO_FREQUENCY_24K           ((u32)24050)	//24KHz
#define WM8994_AUDIO_FREQUENCY_22K           ((u32)22050)	//22.05KHz
#define WM8994_AUDIO_FREQUENCY_16K           ((u32)16000)	//16KHz
#define WM8994_AUDIO_FREQUENCY_12K           ((u32)12000)	//12KHz
#define WM8994_AUDIO_FREQUENCY_11K           ((u32)11025)	//11.025KHz
#define WM8994_AUDIO_FREQUENCY_8K            ((u32)8000) 	//8KHz


//WM8994 输出模块定义
typedef enum
{
	WM8994_HPOUT1			=	0,	//WM8994 耳机1 Headphone HPOUT1
}WM8994_OUT_MODULE;



//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 复位(所有寄存器值为默认)	
	
//使能系统命令行
#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初始化失败!\r\n");
	}*/

所需的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[i] = SWAP16(pDataBuff[i]);
		}
		
		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[i] = SWAP16(pDataBuff[i]);
	}
	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驱动一起给出。

发布了145 篇原创文章 · 获赞 372 · 访问量 81万+

猜你喜欢

转载自blog.csdn.net/cp1300/article/details/104401193