嵌入式 > 嵌入式开发 > 详情

基于FPGA的音乐流水灯控制系统

发布时间:2020-07-06 发布时间:
|

FPGA是现场可编程门阵列的简称, 它既有门阵列器件的高度集成和通用性, 又有可编程逻辑器件用户可编程的灵活性。通过 FPGA实现音乐流水灯的控制, 实质上就是将不同音阶与特定频率的方波信号对应起来, 以方波信号驱动蜂鸣器发出音乐, 再根据不同音阶来控制流水灯的闪烁。与借助微处理器实现乐曲演奏相比, 以纯硬件方式完成乐曲演奏电路更直观。EDA工具和硬件描述语言发挥了强大功能,提供了设计可能性。

1、总体设计方案

音乐流水灯主要是点缀公共场合的装饰品, 音乐的播放和流水灯有节奏地闪烁, 同时达到听觉和视觉的完美结合, 成为构成其必不可少的条件。要了解如何产生不同音阶的音乐, 首先要对乐音的特性有所了解。乐音实际上是有固定频率的信号。在乐曲的构成中, 乐音的频率和持续的时间是其构成的要素。音阶的频率可以通过高频时钟进行分频得到。音频的高低可以通过外部的 LED灯的闪烁来显示, 这样在音乐和流水灯的配合下可以使人产生强烈的节奏感。再辅以 LCD来显示音阶的高低长短, 不懂乐理知识的人便可以直观的看到不同音调对应的音阶。

总体设计要求如下:

( 1)分频主要是通过一个可控分频器实现的。采用时钟的频率越高, 分频系数越大, 分频后的音阶频率就越准确。但同时由于分频系数大使用的计数单元增加, 从而耗费更多的硬件逻辑单元, 因此可以采取一个较为适中的时钟频率 12MH z 。

( 2)经过分频后的信号是一个脉宽极窄的时钟信号, 必须对其进行脉冲宽度调整, 增大占空比, 才能有效地驱动蜂鸣器。在脉冲宽度调整时会对此信号再次二分频, 所以在计算时, 以乐音音阶的二倍频率去求取在特定时钟信号下的分频系数, 以便在调整占空比后得到正确的音阶频率。

( 3)乐曲的频率变化多端, 对应的分频系数也不断变化, 因此需要将播放的乐曲的分频系数事先存放在 ROM 中便于读取。如果将分频系数直接作为存储码存放在寄存器中, 势必会占有更大的容量。因此在这里选取索引值来作为存储码以减小容量。

( 4)开发平台上的 LED灯数量有限, 可以选用有规律的闪烁, 例如从左到右依次点亮、渐亮、渐灭等; 也可以用灯闪烁的多少来表示频率的大小。本设计选用第二种。

图 1为音乐流水灯控制系统的总原理框图。可以看到该系统包含乐曲播放控制模块, 流水灯控制模块和 LCD显示模块 3个模块。其中乐曲播放控制模块分为乐谱播放控制模块, 音阶分频模块和音阶频率产生模块。


图1 音乐流水灯控制系统的总体原理框图

2、 模块设计

2.1 、乐曲播放控制模块

乐曲播放控制模块的主要功能是在一定的时钟信号驱动下将事先存储在 ROM 里的乐谱所对应的索引值依次输出, 控制分频, 并产生相应的分频信号频率, 以此来控制蜂鸣器的发声。

2.1.1、音阶分频器的设计

为了能够在播放乐曲的同时显示当前音阶, 用LED的位数来指示当前音阶的高低音。程序中的音阶分频系数通过索引值来进行选取, 即在音乐播放过程中由乐谱存储电路传递来的当前音阶的索引值。

2.1.2 、音阶频率产生的设计

音阶频率产生电路在获取上面的音阶索引值对应的分频系数后, 通过可控计数器进行分频。分频电路中的计数器进行减 1计数, 计数器的进位信号即为分频信号。因为此信号的脉冲宽度极小, 所以需要调整占空比才使外部驱动电路提供足够的驱动蜂鸣器的功率, 而具体是对分频信号再进行二分频实现的。

2.1.3、 乐谱播放控制模块设计

音乐播放就是通过外部的 8 H z时钟驱动, 内部以计数器进行计数、产生地址, 送到 ROM 单元中作为存储器地址, 将对应地址的数据 音阶索引值输出。

在本设计中, 每个音的发出由另一个 8H z的时钟信号来控制。乐谱中的 4分音符由 4个时钟信号来驱动。每个时钟下, 其对应的音阶输出以索引值的形式存储在 ROM中。文中 ROM 的地址线为 10位, 数据线宽度为 4位。ROM 里存储的数据即各音节的索引值, 根据乐谱转换的需要, 16个索引值即可满足乐曲曲谱编写的需求, 所以设置了 4位数据线。地址线的宽度主要取决于乐曲的长度。本设计中用到了约520个 4 bit单元, 为了留有一定裕度, 将数据线宽度定义为 10位, 即 1 024个 4 b i t单元。其中不同的音阶对应的索引值如表 1所示。


表 1 音阶索引表

按照乐谱, 将音阶对应的索引值连续地存储到ROM中。例如, 乐谱上一个 4分音符的中音 3 , 在ROM存储器中对应的索引值是 10 , 并且连续放置 4次, 而一个 8分音符 5也就是半拍的 5 , 则是将对应索引值 5在 ROM 中连续存放两次。播放时在播放时钟( 8H z )的驱动下, 索引值不断地从 ROM 输出。索引值送到音阶分频模块中, 转换为计数初值输出, 再送到音阶分频产生模块中, 作为计数初值, 产生音阶频率输出驱动蜂鸣器。这样, 就能在蜂鸣器上发出要播放的乐曲了。确定了乐谱后, 即 ROM 的存储内容后, 就可以定制 ROM, 将其初始化文件指定为mif文件即可。

2.2、流水灯控制模块设计

由于此设计是基于 DE270开发板之上的, 因此将对应的音阶输出, 应用 LED灯来显示流水灯闪烁效果。根据音调hight的高低设置点亮灯的数量,当hight 为低时播放低音信号, 为高时播放中音信号。如果要用到高音信号可以将! hight!长度改为 2bit 。选取板上的 oLEDR [ 6..0]前 7盏灯与低音信号对应, oLEDR[ 13..7]与中音信号对应。在本设计中,为了看到明显的流水灯变化, 当发出中音音频时低音显示灯全亮。

2.3、 LCD显示模块设计

首先需要在 SOPC Builder中构建 SOPC系统, 按要求依次添加 NiosII处理器, 4 kB的片上 RAM, LCD模块, 4位输入口, 给处理器分配复位向量地址和异常向量地址。

LCD显示模块用来实现乐谱和音频强度的实时显示, 可以显示 16 ? 2个字符, 其软件流程如图 2所示。


图 2 LCD软件流程图

其中 LCD初始化包括对 LCD的功能设置, 显示开关设置和模式设置。LCD定位到首行首列是通过对LCD写定位指令, 将显示位置确定到第一行第一列。写字符 jian pu到第一行是通过写数据指令将字符jian pu : 和实时变化的乐谱显示在液晶屏的第一行。

低、中、高音分别用 L、M、H表示并且加上对应的音阶值进行显示。LCD显示换行是通过定位指令来实现的。显示音频强度到第二行是用符号# > !的个数表示音调的高低, 一个表示低音 1 , 两个表示低音 2 ,依次类推。

在对 LCD模块进行显示控制时, 用到了写控制命令和写数据命令。这些命令是针对具体配置的硬件电路而编写的 .h头文件。LCD模块的头文件如下:

#definelcd_write_cmd(base,data)

IOWR(base,0,data)

#definelcd_read_cmd(base)

IORD(base,1)

#definelcd_write_data(base,data)

IOWR(base,2,data)

#definelcd_read_data(base)

IORD(base,3)

这样编写是为了和具体的硬件电路相对应, 在LCD模块的硬件描述语言中, 液晶模块 RW 和 RS的地址分配如下:

assi gn LCD_ RW = address[ 0]

assi gn LCD_ RS = address[ 1]

其中 RS信号是命令与数据线, 高电平表示目前数据线上交换的是数据, 低电平表示目前数据线上交换的是命令。液晶模块根据这个信号做出正确的响应。RW 是电平信号, 高电平表示对液晶模块执行读取操作, 低电平表示对液晶模块写入数据或命令。这样便可以确定各读写操作对应于基地址的偏移量。

3、 顶层设计和验证

系统的顶层设计就是将各个底层功能模块例化,在顶层调用, 进行正确的连接, 构成最后的系统。整个系统的硬件电路如图 3所示。


图3 系统硬件电路

至此, 一个硬件音乐流水灯电路就完成了。外部提供两路时钟信号( 12MH z和 8 Hz) , 再将乐曲输出端连接到带有驱动装置的蜂鸣器或扬声器上, 就可以欣赏所添加的乐曲了。若硬件设计上只有一路时钟信号输入, 可在 FPGA 内部设计分频器, 将其分频到8H z 再使用, 还可以在此基础上更改。另外还可以在一个 ROM 种存储多首乐曲, 通过按键选择播放乐曲。

4、 结束语

文中在 FPGA芯片上, 利用 VHDL语言设计了功能强大的 32位 ALU。由于 ALU是 CP U的重要组成部分, 各类系统中都不可避免地需要 ALU, 因此本设计的应用泛围较广。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
什么是总线压限