STM32H743VIT6使用STM32CubeMX通过I2S驱动WM8978(2)

接前一篇文章:STM32H743VIT6使用STM32CubeMX通过I2S驱动WM8978(1)

本文参考以下文章及视频:

STM32CbueIDE Audio播放音频 WM8978 + I2S_stm32 cube配置i2s录音和播放-CSDN博客

STM32第二十二课(I2S,HAL,cubemx)_i2s cubemax-CSDN博客

STM32:I2S驱动WM8978_stm32 iis输出-CSDN博客

STM32:利用VM8978和I2S实现录音的频率分析-CSDN博客

第35讲-I2S 6(配套例程讲解)_哔哩哔哩_bilibili

第83讲 音乐播放器实验讲解_哔哩哔哩_bilibili

特此致谢!

上一回开始讲解WM8978的第一个函数即初始化函数wm8978_init。讲了WM8978的复位函数,也就是对于寄存器0的配置操作,本文接下来讲解对于其它寄存器的配置。

为了便于理解和回顾,再次贴出正点原子和野火的代码,分别如下:

  • 正点原子代码
//WM8978初始化
//返回值:0,初始化正常
//     其它,错误代码
u8 WM8978_Init(void)
{
	u8 res;

	IIC_Init(); //初始化I2C接口

	res = WM8978_Write_Reg(0, 0); //软复位WM8978
	if(res) //发送指令失败,WM8978异常
        return 1;

    //以下为通用设置
	WM8978_Write_Reg(1, 0x01B); //R1,MICEN设置为1(MIC使能),BIASEN设置为1(模拟器工作),VMIDSEL[1:0]设置为11(5K)
	WM8978_Write_Reg(2, 0x1B0); //R2,ROUT1、LOUT1输出使能(耳机可以工作),BOOSTENR、BOOSTENL使能
	WM8978_Write_Reg(3, 0x06C);	//R3,LOUT2、ROUT2输出使能(喇叭工作),RMIX、LMIX使能
	WM8978_Write_Reg(6, 0);	//R6,MCLK由外部提供
	WM8978_Write_Reg(43, 1<<4);	//R43,INVROUT2反向,驱动喇叭
	WM8978_Write_Reg(47, 1<<8);	//R47,PGABOOSTL,左通道MIC获得20倍增益
	WM8978_Write_Reg(48, 1<<8);	//R48,PGABOOSTR,右通道MIC获得20倍增益
	WM8978_Write_Reg(49, 1<<1);	//R49,TSDEN,开启过热保护
	WM8978_Write_Reg(49, 1<<2);	//R49,SPEAKER BOOST,1.5x
	WM8978_Write_Reg(10, 1<<3);	//R10,SOFTMUTE关闭,128x采样,最佳SNR(信噪比)
	WM8978_Write_Reg(14, 1<<3);	//R14,ADC 128x采样率

	return 0;
}
  • 野火代码
/**
  * @brief  配置I2C GPIO,并检查I2C总线上的WM8978是否正常
  * @param  无
  * @retval 1,初始化成功
  *         0,初始化失败
  */
uint8_t wm8978_Init(void)
{
	uint8_t res;

	I2cMaster_Init(); //初始化I2C接口

	res = wm8978_Reset(); //硬件复位WM8978所有寄存器到缺省状态
	wm8978_CtrlGPIO1(1); //控制WM8978的一个GPIO接口,控制其为放音状态

	return res;
}
/**
  * @brief  复位wm8978
  * @param  无
  * @retval 1:复位成功
  * 		0:复位失败
  */
uint8_t wm8978_Reset(void)
{
    //wm8978寄存器缺省值
	const uint16_t reg_default[] = {
	    0x000, 0x000, 0x000, 0x000, 0x050, 0x000, 0x140, 0x000,
	    0x000, 0x000, 0x000, 0x0FF, 0x0FF, 0x000, 0x100, 0x0FF,
	    0x0FF, 0x000, 0x12C, 0x02C, 0x02C, 0x02C, 0x02C, 0x000,
	    0x032, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
	    0x038, 0x00B, 0x032, 0x000, 0x008, 0x00C, 0x093, 0x0E9,
	    0x000, 0x000, 0x000, 0x000, 0x003, 0x010, 0x010, 0x100,
	    0x100, 0x002, 0x001, 0x001, 0x039, 0x039, 0x039, 0x039,
	    0x001, 0x001
	};
	uint8_t res;
	uint8_t i;

	res = wm8978_WriteReg(0x00, 0);

	for (i = 0; i < sizeof(reg_default) / 2; i++)
		wm8978_RegCash[i] = reg_default[i];

	return res;
}
//WM8978寄存器缓存
//由于WM8978的I2C两线接口不支持读取操作,因此寄存器值缓存在内存中
//当写寄存器同步更新缓存,读寄存器时直接返回缓存中的值
static uint16_t wm8978_RegCash[] = {
	0x000, 0x000, 0x000, 0x000, 0x050, 0x000, 0x140, 0x000,
	0x000, 0x000, 0x000, 0x0FF, 0x0FF, 0x000, 0x100, 0x0FF,
	0x0FF, 0x000, 0x12C, 0x02C, 0x02C, 0x02C, 0x02C, 0x000,
	0x032, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
	0x038, 0x00B, 0x032, 0x000, 0x008, 0x00C, 0x093, 0x0E9,
	0x000, 0x000, 0x000, 0x000, 0x003, 0x010, 0x010, 0x100,
	0x100, 0x002, 0x001, 0x001, 0x039, 0x039, 0x039, 0x039,
	0x001, 0x001
};

寄存器1

  • 正点原子代码
    WM8978_Write_Reg(1, 0x01B); //R1,MICEN设置为1(MIC使能),BIASEN设置为1(模拟器工作),VMIDSEL[1:0]设置为11(5K)
  • 野火代码
void wm8978_CfgAudioPath(uint16_t _InPath, uint16_t _OutPath)
{
	uint16_t usReg;

	//查看WM8978数据手册的 REGISTER MAP 章节,第89页
	if ((_InPath == IN_PATH_OFF) && (_OutPath == OUT_PATH_OFF))
	{
		wm8978_PowerDown();
		return;
	}

    //第1步:根据输入通道参数配置寄存器
    //
	//	R1 寄存器 Power manage 1
	//	Bit8    BUFDCOPEN,Output stage 1.5xAVDD/2 driver enable
 	//	Bit7    OUT4MIXEN,OUT4 mixer enable
	//	Bit6    OUT3MIXEN,OUT3 mixer enable
	//	Bit5    PLLEN,不用
	//	Bit4    MICBEN,Microphone Bias Enable (MIC偏置电路使能)
	//	Bit3    BIASEN,Analogue amplifier bias control必须设置为1,模拟放大器才工作
	//	Bit2    BUFIOEN,Unused input/output tie off buffer enable
	//	Bit1:0  VMIDSEL,必须设置为非00值,模拟放大器才工作
	//
	usReg = (1 << 3) | (3 << 0);
	if (_OutPath & OUT3_4_ON) //OUT3和OUT4使能输出GSM模块
	{
		usReg |= ((1 << 7) | (1 << 6));
	}
	if ((_InPath & MIC_LEFT_ON) || (_InPath & MIC_RIGHT_ON))
	{
		usReg |= (1 << 4);
	}
	wm8978_WriteReg(1, usReg); //写寄存器

    ……
}

由正点原子和野火代码的对比可以看到,正点原子的代码简单直接,给出了注释,一目了然;而野火的代码则并不是单独的一句,而是放在了一个更大的函数中(此函数相当于正点原子代码的初始化函数中那许多行代码),这样的代码更优雅、也更正规,也更为全面,函数功能划分也更清楚。总的来说,这两家的代码各有所长。

关于寄存器1的说明,参见笔者文章:WM8978 —— 带扬声器驱动程序的立体声编解码器(4)-CSDN博客

寄存器1复位默认值为0x000(0b000000000)。

VMID和BIASEN的说明参见WM8978手册第79页,如下:

同时参见WM8978手册第34页,如下:

寄存器2

  • 正点原子代码
    WM8978_Write_Reg(2, 0x1B0); //R2,ROUT1、LOUT1输出使能(耳机可以工作),BOOSTENR、BOOSTENL使能
  • 野火代码
void wm8978_CfgAudioPath(uint16_t _InPath, uint16_t _OutPath)
{
	uint16_t usReg;

	//查看WM8978数据手册的 REGISTER MAP 章节,第89页
	if ((_InPath == IN_PATH_OFF) && (_OutPath == OUT_PATH_OFF))
	{
		wm8978_PowerDown();
		return;
	}

    //第1步:根据输入通道参数配置寄存器
    ……
	//
	//	R2 寄存器 Power manage 2
	//	Bit8	ROUT1EN,ROUT1 output enable 耳机右声道输出使能
	//	Bit7	LOUT1EN,LOUT1 output enable 耳机左声道输出使能
	//	Bit6	SLEEP,0 = Normal device operation   1 = Residual current reduced in device standby mode
	//	Bit5	BOOSTENR,Right channel Input BOOST enable 右通道输入自举电路使能
	//	Bit4	BOOSTENL,Left channel Input BOOST enable 左通道输入自举电路使能
	//	Bit3	INPGAENR,Right channel input PGA enable 右声道输入PGA使能
	//	Bit2	INPGAENL,Left channel input PGA enable 左声道输入PGA使能
	//	Bit1	ADCENR,Enable ADC right channel
	//	Bit0	ADCENL,Enable ADC left channel
	//
	usReg = 0;
	if (_OutPath & EAR_LEFT_ON)
	{
		usReg |= (1 << 7);
	}
	if (_OutPath & EAR_RIGHT_ON)
	{
		usReg |= (1 << 8);
	}
	if (_InPath & MIC_LEFT_ON)
	{
		usReg |= ((1 << 4) | (1 << 2));
	}
	if (_InPath & MIC_RIGHT_ON)
	{
		usReg |= ((1 << 5) | (1 << 3));
	}
	if (_InPath & LINE_ON)
	{
		usReg |= ((1 << 4) | (1 << 5));
	}
	if (_InPath & MIC_RIGHT_ON)
	{
		usReg |= ((1 << 5) | (1 << 3));
	}
	if (_InPath & ADC_ON)
	{
		usReg |= ((1 << 1) | (1 << 0));
	}
	wm8978_WriteReg(2, usReg); //写寄存器

    ……
}

这里不再对正点原子和野火两家代码进行比较(上边已经说得比较清楚了),而重点说明具体的配置实现的功能。

关于寄存器2的说明,参见笔者文章:WM8978 —— 带扬声器驱动程序的立体声编解码器(4)-CSDN博客

寄存器2复位默认值为0x000(0b000000000)。 

  • ROUT1EN和LOUT1EN

参见WM8978手册第63页,如下:

同时参见WM8978手册第52页,如下:

  • SLEEP

参见WM8978手册第63页,如下:

  • BOOSTENR和BOOSTENL

参见WM8978手册第33页,如下:

同时参见WM8978手册第32页,如下:

  • INPPGAENR和INPPGAENL

参见WM8978手册第28页,如下:

同时参见WM8978手册第27页,如下:

  • ADCENR和ADCENL

参见WM8978手册第35页,如下:

同时参见WM8978手册第35页,如下:

更多寄存器配置的详细说明与讲解请看下回。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/539537.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32 串口接收定长,不定长数据

本文为大家介绍如何使用 串口 接收定长 和 不定长 的数据。 文章目录 前言一、串口接收定长数据1. 函数介绍2.代码实现 二、串口接收不定长数据1.函数介绍2. 代码实现 三&#xff0c;两者回调函数的区别比较四&#xff0c;空闲中断的介绍总结 前言 一、串口接收定长数据 1. 函…

pbootcms百度推广链接打不开显示404错误页面

PbootCMS官方在2023年4月21日的版本更新中&#xff08;对应V3.2.5版本&#xff09;&#xff0c;对URL参数添加了如下判断 if(stripos(URL,?) ! false && stripos(URL,/?tag) false && stripos(URL,/?page) false && stripos(URL,/?ext_) false…

Composer安装与配置

Composer&#xff0c;作为PHP的依赖管理工具&#xff0c;极大地简化了PHP项目中第三方库的安装、更新与管理过程。本文将详细介绍Composer的安装步骤、基本配置方法&#xff0c;以及一些实用的操作示例&#xff0c;帮助读者快速上手并熟练运用Composer。 一、Composer安装 环…

Python --- 怎么把Python当计算器用?(小白自学笔记)

怎么把Python当计算器用&#xff1f;(小白自学笔记) Part I&#xff1a;标准数学包的导入 今天刚刚装了python&#xff0c;打算用它来取代matlab的基本计算功能&#xff0c;当我的日常计算器用。(这里还有一个捷径&#xff0c;如果你跟我一样也是纯小白的话&#xff0c;直接问c…

如何确保软件通过SmartScreen验证,消除用户下载时的警告提示?

在当前的网络时代&#xff0c;各种软件应用程序深深渗透到人们的日常生活和工作中&#xff0c;许多企业选择自行开发应用程序以推进其业务发展。但在发布应用程序后&#xff0c;软件所有者经常会遇到一个挑战&#xff0c;即用户在下载时可能会遇到微软SmartScreen提示“此应用程…

JVM修炼之路【11】- 解决内存溢出、内存泄漏 以及相关案例

前面的10篇 都是基础的知识&#xff0c;包括类加载的过程 类加载的细节&#xff0c;jvm内存模型 垃圾回收 等等&#xff0c; 这一篇我们开始实战了解一下 各种疑难杂症&#xff1a;怎么监控 怎么发现 怎么解决 内存溢出 内存泄漏 这两个概念在垃圾回收器里面已经讲过了&#…

Java前置一些知识

文章目录 搭建Java环境安装path环境变量Java技术体系 Java执行原理JDK组成跨平台Java内存分配 IDEA管理Java程序 搭建Java环境 安装 oralce官网下载 JDK17 Windows 傻瓜式的点下一步就行&#xff0c;注意&#xff1a;安装目录不要有空格、中文 java 执行工具 javac 编译工具…

2024年第十四届MathorCup数学应用挑战赛C题解析(更新中)

2024年第十四届MathorCup数学应用挑战赛C题解析&#xff08;更新中&#xff09; 题目题目解析(更新中&#xff09;问题一问题二问题三 题目 C题 物流网络分拣中心货量预测及人员排班电商物流网络在订单履约中由多个环节组成&#xff0c;图1是一个简化的物流 网络示意图。其中&a…

状态模式:管理对象状态转换的动态策略

在软件开发中&#xff0c;状态模式是一种行为型设计模式&#xff0c;它允许一个对象在其内部状态改变时改变它的行为。这种模式把与特定状态相关的行为局部化&#xff0c;并且将不同状态的行为分散到对应的状态类中&#xff0c;使得状态和行为可以独立变化。本文将详细介绍状态…

ActiveMQ 01 消息中间件jmsMQ

消息中间件之ActiveMQ 01 什么是JMS MQ 全称&#xff1a;Java MessageService 中文&#xff1a;Java 消息服务。 JMS 是 Java 的一套 API 标准&#xff0c;最初的目的是为了使应用程序能够访问现有的 MOM 系 统&#xff08;MOM 是 MessageOriented Middleware 的英文缩写&am…

django基于python的法院执法案件管理系统

本课题使用Python语言进行开发。代码层面的操作主要在PyCharm中进行&#xff0c;将系统所使用到的表以及数据存储到MySQL数据库中&#xff0c;方便对数据进行操作本课题基于WEB的开发平台&#xff0c;设计的基本思路是&#xff1a; 框架&#xff1a;django/flask 后端&#xff…

LwIP 之八 详解 IP RAW 编程、示例、API 源码、数据流

我们最为熟知的网络通信程序接口应该是 Socket。LwIP 自然也提供了 Socket 编程接口,不过,LwIP 的 Socket 编程接口都是使用最底层的接口来实现的。我们这里要学习的 IP RAW 编程则是指的直接使用 LwIP 的提供的 RAW API 来直接实现应用层功能。这里先来一张图,对 LwIP 内部…

【Godot4自学手册】第三十六节圆形移动或扇形移动的铁球

在第三十四节我实现了来回无限滚动的伤害铁刺球&#xff0c;这一节我准备实现一个圆形移动或扇形移动&#xff0c;并带有链条的铁球。效果如下&#xff1a; 一、实现原理 绕一点做圆周运动&#xff0c;简单的说就是&#xff1a; 每一帧根据旋转的角度计算出下一个位置的坐标…

【c++leetcode】14. Longest Common Prefix

问题入口 解决方案 class Solution { public:string longestCommonPrefix(vector<string>& v) {string ans "";sort(v.begin(), v.end());int n v.size();string first v[0],last v[n - 1];for(int i 0; i < min(first.size(),last.size()); i){…

实现网站图片水印

要实现网站图片水印&#xff0c;有几种方式&#xff1a;1、对于自己想要上传图片先通过某些软件增加水印&#xff0c;然后再上传到图片服务器。2、通过上传客户端&#xff08;eg&#xff1a;picgo&#xff09;功能或插件直接自动水印以及上传服务器。本文主要聚焦于第二种方式&…

前端重置表单的多个Demo

目录 前言1. 纯重置2. reset重置3. resetFields重置4. 彩蛋 前言 由于从Java转全栈&#xff0c;对于前端的相关知识目前 以点科普面&#xff0c;此处的总结 重置前端表单内容&#xff0c;防止影响后续操作 其基本知识只需要通过点击按钮触发重置表单 1. 纯重置 可以通过按钮…

跟TED演讲学英文:The exciting, perilous journey toward AGI by Ilya Sutskever

The exciting, perilous journey toward AGI Link: https://www.ted.com/talks/ilya_sutskever_the_exciting_perilous_journey_toward_agi? Speaker: Ilya Sutskever Date: October 2023 文章目录 The exciting, perilous journey toward AGIIntroductionVocabularyTranscr…

修改cmd默认编码(win10系统) 亲测有效

win10系统,CMD默认字符编码序号是936,输入"chcp"命令可以看到此编号,右键cmd窗口–属性,同样也可以看到此编号.如下图: 我需要把字符编码序号936变更为65001,即UTF-8编码. 网上搜到的教程主要有两种: 教程一修改注册表的方法:https://learnku.com/articles/55553 测…

Ubuntu (Linux系统) 下载安装 Qt 环境

在官网http://download.qt.io/archive/qt/ 下载安装包&#xff0c;默认linux平台下提供的安装包以run后缀结尾 也可以选择其它地址下载 Qt官网下载地址&#xff1a;https://download.qt.io&#xff1b; 国内镜像下载地址&#xff1a;https://mirrors.cloud.tencent.com/qt/ 。建…

Alterac Valley

Alterac Valley 奥特兰克山谷 不要怕死&#xff0c;冲就对了&#xff0c;为了部落&#xff01;&#xff01;&#xff01;55级的我未来就是这个服务器的督军&#xff0c;跟我冲啊