FPGA 20个例程篇:18.SD卡存放音频WAV播放(下)

news2024/9/24 21:25:13

第七章 实战项目提升,完善简历

18.SD卡存放音频WAV播放(下)

      进一步地我们再结合图1的示意图来分析wav_play模块的时序逻辑设计,大家可以清楚地看到WM8731在Right justified和主从时钟模式下,是先发左声道后发右声道数据的,这里需要强调4点也是之前困扰笔者很久的问题:     

      1. WAV格式的音频数据采用了16Bit双声道编码格式,相当于一个基本音频数据单元是32Bit,这也就是为什么要把SD卡扇区中读到的4个字节数据拼接到一起后存入FIFO中,主要是为了方便wav_play模块的数据拆分;

       2. 在这个例程中我们选取的是Right justified、主时钟、默认32bit模式,注意到手册里明确写道在主时钟模式下,DACLRC/ADCLRC是输出64个BCLK时钟周期即32个BCLK高电平,32个BCLK低电平;

        3. 在Right justified、默认32bit模式下,前32个BCLK对应DACLRC/ADCLRC的高电平,这时应该在后16个BCLK中输入左声道16位的数据,后32个BCLK对应对应DACLRC/ADCLRC的低电平,这时应该在后16个BCLK中输入右声道16位的数据,而对应的左右声道的前16个BCLK可以做补零操作,且DACDAT/ADCDAT的数据应该在BCLK时钟下降沿更新;

      4. 注意到WAV下16 Bit双声道编码格式为:左声道数据低字节、左声道数据高字节、

      右声道数据低字节、右声道数据高字节,而WM8731在Right justified、默认32bit模式下的编码格式为:左声道数据高字节、左声道数据低字节、右声道数据高字节、右声道数据低字节,所以需要在程序里把上游wav_query模块从FIFO中读到的32位数据进行数据拼接,重新组成左声道和右声道的数据。

图1 WM8731在Right justified和主从时钟模式下的说明

      如表1所示是wav_play模块信号列表,在这个模块里我们先把上游wav_query模块从FIFO中读到的32位数据进行数据拆分处理,再拼接成32位的左声道数据和32位的右声道数据,最后按照Right justified、主时钟、默认32bit模式,在BCLK和ADCLRC的作用下把数据一位位地送到DACDAT上。

      显然本模块的CLK对应50Mhz时钟比BCLK快很多,可以捕获到BCLK的时钟下降沿和ADCLRC的时钟上升沿,在这里wav_data和wav_data_vld分别对应上游模块的数据信号和数据指示信号,而wav_playrdy作为读准备信号例化到上游wav_query模块,激发FIFO的读使能信号,如图2所示是WAV音频播放模块的代码设计。

信号列表

信号名

I/O

位宽

clk

I

1

rst_n

I

1

wav_bclk

I

1

wav_adclrc

I

1

wav_data

I

32

wav_data_vld

I

1

wav_playrdy

O

1

wav_dacdata

O

1

表1 wav_play模块信号列表

图2 WAV音频播放模块的代码设计

      如表2和表3所示分别是config_wm8731和i2c_wm8731模块的信号列表,显然我们需要去初始化WM8731后,芯片才能按照我们的想法工作,其中config_wm8731模块存储了10个寄存器地址和参数值,i2c_wm8731模块则实现了整个IIC配置的时序逻辑,依次配置10个寄存器,完成IIC初始化后,通过i2c_config_done信号指示初始完成,如图3和4所示分别是2个模块的代码设计。

信号列表

信号名

I/O

位宽

lut_index

I

4

lut_data

O

24

lut_size

O

4

表2 config_wm8731模块信号列表

信号列表

信号名

I/O

位宽

clk

I

1

rst_n

I

1

i2c_config_size

I

4

i2c_config_data

I

24

i2c_sda

I/O

1

i2c_scl

O

1

i2c_config_index

O

4

i2c_config_done

O

1

表3 i2c_wm8731模块信号列表

图3 WM8731初始化寄存器值模块的代码设计

图4 WM8731初始化寄存器设置模块的代码设计

      如图5所示是SD卡存放音频WAV播放顶层模块的代码设计,大家需要把各个模块的相关信号例化到一起,在这个例程中首先我们在SD卡中事先存储好了很多首WAV格式的歌曲,然后按下按键KEY1,FPGA会按照SD卡的扇区依次遍历各个扇区直到找到WAV文件头格式的歌曲,把WAV格式的音频数据按照WM8731配置的Right justified、主时钟、默认32bit模式播放歌曲,接着当播放完一首歌曲后,再按下按键KEY1,FPGA会再去查找SD卡扇区的下一首WAV文件头格式的歌曲,找到后继续播放下一首。

     为了便于调试观察,这里笔者也把各个模块的关键信号添加到ILA IP核中,同时通过LED0点亮代表SD卡和WM8731均初始化完毕,通过LED1闪烁代表当前正在播放SD卡中的音频数据,插上SD卡后即可观察到板载的LED0点亮,按下按键KEY1很快板载的LED1会不断地闪烁,同时把耳机座子插到豌豆开发板的绿色耳机接口处,即可播放出动听美妙的战歌Counting Stars。

图5 SD卡存放音频WAV播放顶层模块的代码设计

SD卡音乐WM8731播放

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode】专题一 二叉树层序遍历

二叉树层序遍历 在本文中,我将会选取LeetCode上二叉树层序遍历的多道例题,并给出解答,通过多道题我们就可以发现,二叉树的层序遍历并不复杂,并且有着共通点。 102. 二叉树的层序遍历 给你二叉树的根节点 root &…

【Labivew】简易计算器

🚩write in front🚩 🔎大家好,我是謓泽,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎 🏅2021年度博客之星物联网与嵌入式开发TOP5&#xff5…

Secure CRT远程连接很快断线问题

问题描述 我们使用Secure CRT连接远程主机时可能会遇到几分钟没操作就无法操作了,需要断开重新连接,非常的麻烦,假如客户端或者服务端能够在快要超时的时候给对方发送一个心跳,得到对方响应就重置下超时时间,这样就能…

arm架构 --- 中断

ARM的异常 终止程序的正常执行过程而不得不去完成的一些特殊工作 中断是异常的一种,包括外部硬件产生的异常和芯片内部硬件产生的内部中断。 ARM有七种处理器模式,其中用户模式和系统模式之外的5钟处理器模式叫做异常模式,用户模式之外的6…

osgEarth示例分析——osgearth_terrainprofile

前言 osgearth_terrainprofile示例,涉及到一个新的类 TerrainProfileCalculator(地形轮廓计算器类),用来计算两个点连线之间的地形数据。左下角会根据点击的起点和终点进行计算,并更新显示地形信息。 效果 拖动地球,到某一个视…

[附源码]Python计算机毕业设计SSM基于的智慧校园安防综合管理系统(程序+LW)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

软件安全测试-Web安全测试详解-XSS攻击

目录 1. XSS攻击 1.1 XSS攻击原理 1.2 XSS能做什么 1.3 XSS三种类型 1.4 XSS三种途径 1.5 XSS测试方法 1.5.1 查看代码 1.5.2 准备测试脚本 1.5.3 自动化测试XSS漏洞 1.5.4 XSS注入常用语句 1.6 XSS漏洞防范h3 1.6.1 对输入和URL参数进行过滤(白名单和黑名单) 1.6.…

tensorflow入门(一) 计算图、张量、会话的概念

1、计算图 计算图是tensorflow中最基本的一个概念,tensorflow中的所有计算都被转化成计算图上的节点。tensorflow的名字已经说明了它最重要的两个概念------tensor和flow。张量这个概念在数学或者物理学中可以有不同的解释,在tensorflow中,张…

基于tensorflow的深层神经网络(三)如何用tensorflow优化神经网络

1、神经网络优化算法 梯度下降算法主要用户优化单个参数的取值,而反向传播算法给出了一个高效的方式在所有参数上使用梯度下降算法,从而使神经网络模型在训练数据上的损失函数尽可能小。反向传播算法是训练神经网络的核心算法,它可以根据定义…

红黑树的插入过程

一棵红黑树是一种特殊的二叉查找树,具有以下性质: 每个节点要么是红色,要么是黑色。根节点是黑色。每个叶子节点(NIL)是黑色。如果一个节点是红色的,那么它的两个儿子都是黑色的。从任意一个节点到其每个叶…

71.qt quick-可伸展菜单-抽屉栏示例 通用QML界面(一键换肤)

在我们之前章节已经提供过了抽屉栏和菜单伸展栏: 63.qt quick-QML侧边滑动栏(不需要任何图片资源,支持自定义左右方向和大小)_诺谦的博客-CSDN博客_qml侧边栏68.qt quick-qml多级折叠下拉导航菜单 支持动态添加/卸载 支持qml/widget加载等_诺谦的博客-CSDN博客_qml下拉菜单 由…

三维家发生工商变更:注册资本减少46%,美凯龙、阿里等股东退出

近日,云工业软件服务商广东三维家信息科技有限公司(下称“三维家”)发生工商变更,注册资本由16.9254亿元变更为9亿元,同比减少46.83%。同时,包括红星美凯龙、阿里巴巴等多名股东退出,变更时间为…

01.Spring源码整体脉络介绍及源码编译——四

IOC是核心 IOC 容器加载过程【重要】:所有模块都依赖IOC,aop,循环依赖都依赖IOC IOC控制反转,控制理念,来解决层与层之间的耦合。DI注入实现 怎么讲Bean交给IOC容器来管理 配置类xml,注解 加载spring上下…

java计算机毕业设计ssm学院校友信息管理系统的设计与实现5yqhy(附源码、数据库)

java计算机毕业设计ssm学院校友信息管理系统的设计与实现5yqhy(附源码、数据库) 项目运行 环境配置: Jdk1.8 Tomcat8.5 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts…

【Java基础篇】基础知识易错集锦(二)

我们同样用几道例题来回顾相对应的基础知识; 解析: 首先我呢区分一下实例变量和局部变量; 局部变量:定义在方法内部的变量;实例变量:定义在类中但在任何方法之外,你也可以理解为全局变量&…

16.C预处理器和C库

文章目录C预处理器和C库16.1翻译程序的第一步16.2明示常量:#define16.3在#define中使用参数16.3.1用宏参数创建字符串:#运算符16.3.2预处理器黏合剂:##运算符16.3.3变参宏:...和__VA_ARGS__16.4宏和函数的选择16.5文件包含&#x…

NCTF2022 calc题目复现

calc(环境变量注入getshell) 经典计算器题目,看着有点眼熟,没错,就是buu三月赛的一道题目。由于那时候web可能都算不上入门,所以也就没有复现。比赛时就网上看了看三月赛的wp,但是没有什么用&a…

IEEE 二进制浮点数的表示

今天,我来将 IEEE 二进制浮点数的表示方式进行一个简单的介绍。 浮点数 在 C 语言中,有两种存储浮点数的方式,分别是 float 和 double ,当然了还有long double。这几种浮点型所容纳的长度不同,当然它们存储的精度也就…

[附源码]JAVA毕业设计新型药物临床信息管理系统(系统+LW)

[附源码]JAVA毕业设计新型药物临床信息管理系统(系统LW) 项目运行 环境项配置: Jdk1.8 Tomcat8.5 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 …

p5.第一章 Python基础入门 -- 运算符、优先级和表达式 (五)

1.2.3.2.11 False等价 False等价布尔值,相当于bool(value) 空容器 空集合set空字典dict空列表list空元组tuple空字符串None0# bool(value)是布尔函数# In: bool(1), bool(0) # Out: (True