FPGA学习——蜂鸣器实现音乐播放器并播放两只老虎

文章目录

  • 一、蜂鸣器简介
    • 1.1 蜂鸣器分类
    • 1.2 PWM
  • 二、C4开发板原理图
  • 三、如何产生不同的音调
  • 四、代码实现及分析
  • 五、总结

一、蜂鸣器简介

1.1 蜂鸣器分类

蜂鸣器一般分为有源蜂鸣器和无源蜂鸣器。二者的区别在于,有源蜂鸣器内部含有振动源和功放电路,只需上电便可发出鸣叫。而无源蜂鸣器内部不含振动源和功放电路,因此我们需要给予其PWM方波,才能驱动无源蜂鸣器正常工作。

1.2 PWM

PWM即脉冲脉宽调制,PWM的占空比是指在一个完整的时钟周期内,高电平所占时间占整个时钟周期的比例(50%占空比即高低电平各占一半时钟周期),为方便代码编写,本项目产生的PWM均为50%占空比。

二、C4开发板原理图

在这里插入图片描述

博主所用开发板为Cyclone Ⅳ开发板,开发板芯片为:EP4CE6F17C8,由开发板原理图可以看出,本开发板蜂鸣器低电平有效。

三、如何产生不同的音调

我们可以通过给予无源蜂鸣器不同频率的PWM方波信号从而实现不同的音调音符。
相关数据参考可见下图:
在这里插入图片描述
举个例子:博主所用开发板晶振为50MHz,而低音Do的频率为262,因此我们需要在一秒内产生50MHz/262次PWM方波信号,此时蜂鸣器变会发出低音Do(如有错误请指正,博主是这样理解的,乐理知识匮乏,请见谅)。

两只老虎的乐谱如下:

在这里插入图片描述

四、代码实现及分析

本次项目较为简单,仅有一个蜂鸣器模块。

源码分析:

  • 本次项目首先需要一个音符计数器,用来存放歌曲中的音符数目,由乐谱可知两只老虎共含有34个音符,因此我们需要一个6位宽的计数器用来计数到34(后续发现好像乐谱中间隔比较大的是空拍?各位可以自行调整)
  • 除此之外,本次项目需要一个节拍计数器,不过这方面也是乐理知识,博主不太懂,两只老虎好像是一秒四拍,所以我们需要设计一个250ms计数器用来记一拍(也就是一个音符播放的时间)
  • 同时我们自然需要一个计数音符频率的计数器。由于不同音符的频率不尽相同,因此我们可以很自然地想到需要引入一个中间信号,通过case第几个音符,给予中间信号不同的频率值。
  • 另外由于本项目生成的PWM均为50%占空比,因此需要一个中间信号duty,duty为音符频率的一半,音符频率计数器小于duty时蜂鸣器输出0,否则输出1.
module beep (input       wire        clk     ,input       wire        rst_n   ,input       wire        beep_en ,output      reg         beep     //输出蜂鸣器
);//内部参数定义
parameter   CYCLE = 26'd50_000_000  ;
parameter   TIME  = 24'd12_500_000  ;
parameter   NUM   = 6'd34           ;
parameter   DOL   = CYCLE/262       ,REL   = CYCLE/294       ,MIL   = CYCLE/330       ,FAL   = CYCLE/349       ,SOL   = CYCLE/392       ,LAL   = CYCLE/440       ,XIL   = CYCLE/494       ,DOM   = CYCLE/523       ,REM   = CYCLE/587       ,MIM   = CYCLE/659       ,FAM   = CYCLE/698       ,SOM   = CYCLE/784       ,LAM   = CYCLE/880       ,XIM   = CYCLE/988       ,DOH   = CYCLE/1047      ,REH   = CYCLE/1175      ,MIH   = CYCLE/1319      ,FAH   = CYCLE/1397      ,SOH   = CYCLE/1568      ,LAH   = CYCLE/1760      ,XIH   = CYCLE/1967      ;//内部信号定义
reg    [5:0]        cnt_num     ;//音符个数寄存器
wire                add_cnt_num ;
wire                end_cnt_num ;reg    [23:0]       cnt_250     ;//一拍时间寄存器
wire                add_cnt_250 ;
wire                end_cnt_250 ;reg     [17:0]      cnt_frq     ;//音符频率寄存器
wire                add_cnt_frq ;
wire                end_cnt_frq ;reg     [17:0]      frq         ;//中间信号,存储音符频率
wire    [16:0]      duty        ;//中间信号,用于比较产生50%PWM//250ms计数器
always @(posedge clk or negedge rst_n) beginif(!rst_n)begincnt_250 <= 1'b0;endelse if(add_cnt_250)beginif(end_cnt_250)begincnt_250 <= 1'b0;endelse begincnt_250 <= cnt_250 + 1'b1;endendelse begincnt_250 <= cnt_250;end
endassign add_cnt_250 = beep_en;
assign end_cnt_250 = add_cnt_250 && cnt_250 == TIME - 1'b1;//音符个数寄存器
always @(posedge clk or negedge rst_n) beginif(!rst_n)begincnt_num <= 1'b0;endelse if(add_cnt_num)beginif(end_cnt_num)begincnt_num <= 1'b0;endelse begincnt_num <= cnt_num + 1'b1;endendelse begincnt_num <= cnt_num;end
endassign add_cnt_num = end_cnt_250;
assign end_cnt_num = add_cnt_num && cnt_num == NUM - 1'b1;//音符频率计数器
always @(posedge clk or negedge rst_n) beginif(!rst_n)begincnt_frq <= 1'b0;endelse if(add_cnt_frq)beginif(end_cnt_frq || end_cnt_250)begincnt_frq <= 1'b0;endelse begincnt_frq <= cnt_frq + 1'b1;endendelse begincnt_frq <= cnt_frq;end
endassign add_cnt_frq = beep_en;
assign end_cnt_frq = add_cnt_frq && cnt_frq == frq - 1'b1;//音频赋值
always@(*)begincase(cnt_num)6'd0     :   frq = DOM;6'd1     :   frq = REM;6'd2     :   frq = MIM;6'd3     :   frq = DOM;6'd4     :   frq = DOM;6'd5     :   frq = REM;6'd6     :   frq = MIM;6'd7     :   frq = DOM;6'd8     :   frq = MIM;6'd9     :   frq = FAM;6'd10    :   frq = SOM;6'd11    :   frq = MIM;6'd12    :   frq = FAM;6'd13    :   frq = SOM;6'd14    :   frq = SOM;6'd15    :   frq = LAM;6'd16    :   frq = SOM;6'd17    :   frq = FAM;6'd18    :   frq = MIM;6'd19    :   frq = DOM;6'd20    :   frq = SOM;6'd21    :   frq = LAM;6'd22    :   frq = SOM;6'd23    :   frq = FAM;6'd24    :   frq = MIM;6'd25    :   frq = DOM;6'd26    :   frq = REM;6'd27    :   frq = SOL;6'd28    :   frq = DOM;6'd29    :   frq = 0  ;6'd30    :   frq = REM;6'd31    :   frq = SOL;6'd32    :   frq = DOM;6'd33    :   frq = 0  ;default  :   frq = 0  ;endcase
end//beep输出赋值
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginbeep <= 1'b1;endelse if(cnt_frq < duty && beep_en)beginbeep <= 1'b0;endelse beginbeep <= 1'b1;end
end//生成占空比为50%的音频PWM方波的比较信号
assign duty = frq >> 1;endmodule

五、总结

本项目较为简单,基本是在做计数器的练习和PWM方波信号产生练习,希望大家能够掌握。

如有没有讲清楚的地方还请大家指正。

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

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

相关文章

前端如何打开钉钉(如何唤起注册表中路径与软件路径不关联的软件)

在前端唤起本地应用时&#xff0c;我查询了资料&#xff0c;在注册表中找到腾讯视频会议的注册表情况&#xff0c;如下&#xff1a; 在前端代码中加入 window.location.href"wemeet:"; 就可以直接唤起腾讯视频会议&#xff0c;但是我无法唤起钉钉 之所以会这样&…

2023年人工智能技术与智慧城市发展白皮书

人工智能与智慧城市是当前热门的话题和概念&#xff0c;通过将人工智能技术应用在城市管理和服务中&#xff0c;利用自动化、智能化和数据化的方式提高城市运行效率和人民生活质量&#xff0c;最终实现城市发展的智慧化&#xff0c;提升城市居民的幸福感。 AI技术在城市中的应…

QT中使用ffmpeg的api进行视频的播放

在了解ffmpeg使用api进行视频的播放之前&#xff0c;我们首先了解一下视频的播放流程。 一、视频的播放流程 首先是我们最常见的视频文件&#xff0c;在播放流程中首先是要打开视频文件&#xff0c;将视频文件中的数据进行解封装&#xff0c;之后再将解封装之后的视频进行解码…

【C#学习笔记】引用类型(2)

文章目录 ObjectEqualsGetTypeToStringGetHashCode string逐字文本复合格式字符串字符串内插 StringBuilderStringBuilder 的工作原理StringBuilder提供的方法访问字符迭代字符查询字符 dynamic Object 支持 .NET 类层次结构中的所有类&#xff0c;并为派生类提供低级别服务。…

Python实现GA遗传算法优化循环神经网络分类模型(LSTM分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;最早是由美国的 John holland于20世…

全面解析大语言模型的工作原理

当ChatGPT在去年秋天推出时&#xff0c;在科技行业乃至世界范围内引起了轰动。当时&#xff0c;机器学习研究人员尝试研发了多年的语言大模型&#xff08;LLM&#xff09;&#xff0c;但普通大众并未十分关注&#xff0c;也没有意识到它们变得多强大。 如今&#xff0c;几乎每个…

无代码开发(BIP旗舰版-YonBuilder)

目录 我的应用 新建领域 菜单管理 应用构建 新建应用 对象建模 新增业务对象 新增业务实体 页面建模 新增页面 编辑页面 发布管理 我的应用 角色管理 yonbuilder开发平台&#xff0c;提供标准服务和专业开发服务&#xff1b; 本篇文章只演示标准服务的可视化应用…

Flink State 和 Fault Tolerance详解

有状态操作或者操作算子在处理DataStream的元素或者事件的时候需要存储计算的中间状态&#xff0c;这就使得状态在整个Flink的精细化计算中有着非常重要的地位&#xff1a; 记录数据从某一个过去时间点到当前时间的状态信息。以每分钟/小时/天汇总事件时&#xff0c;状态将保留…

弹性布局,网格布局,JavaScript

弹性盒子布局&#xff08;Flexbox Layout&#xff09;&#xff1a;通过display: flex;设置容器为弹性盒子&#xff0c;可以实现更复杂的自适应和响应式布局。 网格布局&#xff08;Grid Layout&#xff09;&#xff1a;通过display: grid;设置容器为网格布局&#xff0c;可以将…

Unity 引擎做残影效果——2、屏幕后处理方式

Unity实现残影效果 大家好&#xff0c;我是阿赵。 这里继续介绍Unity里面做残影的方法。之前介绍了BakeMesh的方法做残影&#xff0c;这一期介绍的是用屏幕后处理的方法做残影。 一、原理 之前的BakeMesh方法&#xff0c;是真的生成了很多个网格模型在场景里面。如果用后处理做…

day49-Springboot

Springboot 1. Springboot简介 1.1 简介&#xff1a;Springboot来简化Spring应用开发的一个框架&#xff0c;约定大于配置 1.2 优点&#xff1a; 可以快速的构建独立运行的Spring项目&#xff1b; 框架内有Servlet容器&#xff0c;无需依赖外部&#xff0c;所以不需要达成w…

正则匹配img标签里面src

正则&#xff1a; (?<src\s*\s*\")\S(?\"{1})匹配效果&#xff1a;

Ansible —— playbook 剧本

Ansible —— playbook 剧本 一、playbook的概述1.playbook简介2.什么是Ansible playbook剧本&#xff1f;3.Ansible playbook剧本的特点4.如何使用Ansible playbook剧本&#xff1f;5.playbooks 本身由以下各部分组成 二、playbook示例1.运行playbook2.定义、引用变量3.指定远…

HarmonyOS/OpenHarmony元服务开发-卡片使用动效能力

ArkTS卡片开放了使用动画效果的能力&#xff0c;支持显式动画、属性动画、组件内转场能力。需要注意的是&#xff0c;ArkTS卡片使用动画效果时具有以下限制&#xff1a; 以下示例代码实现了按钮旋转的动画效果&#xff1a; Entry Component struct AttrAnimationExample { St…

Vue axios + Vue使用

相对于原生的阿贾克斯&#xff0c;axios提供的方法使用起来会更加的简便&#xff0c;之前网络数据获取到了&#xff0c;如何和vue一起使用呢&#xff1f; 网络应用的核心就是data中的数据一部分是通过网络获取到的。所以在方法当中发起网络请求&#xff0c;在响应回来之后将服…

mac切换jdk版本

查询mac已有版本 1、打开终端&#xff0c;输入&#xff1a; /usr/libexec/java_home -V注意&#xff1a;输入命令参数区分大小写(必须是-V) 2.目前本地装有两个版本的jdk xxxxedydeMacBook-Pro-9 ~ % /usr/libexec/java_home -V Matching Java Virtual Machines (2):20.0.1 (…

【腾讯云Cloud Studio实战训练营】使用Cloud Studio迅捷开发一个3D家具个性化定制应用

目录 前言&#xff1a; 一、腾讯云 Cloud Studio介绍&#xff1a; 1、接近本地 IDE 的开发体验 2、多环境可选&#xff0c;或连接到云主机 3、随时分享预览效果 4、兼容 VSCode 插件 5、 AI代码助手 二、腾讯云Cloud Studio项目实践&#xff08;3D家具个性化定制应用&…

探索 GPTCache|GPT-4 将开启多模态 AI 时代,GPTCache + Milvus 带来省钱秘籍

世界正处于数字化的浪潮中&#xff0c;为了更好理解和分析大量数据&#xff0c;人们对于人工智能&#xff08;AI&#xff09;解决方案的需求呈爆炸式增长。 此前&#xff0c;OpenAI 推出基于 GPT-3.5 模型的智能对话机器人 ChatGPT&#xff0c;在自然语言处理&#xff08;NLP&a…

【MYSQL】MYSQL学习笔记【基础篇】【未完待续】

文章目录 MYSQL入门一、MYSQL概述1. 数据库相关概念1.1 数据库&#xff0c;数据库管理系统与SQL1.2 数据库种类以及主流数据库管理系统排名1.3 MySQL数据库安装1.4 数据模型 二、SQL2.1 通用语法与注释2.2 SQL分类2.3 图形化界面2.4 DDL2.4.1 数据库操作2.4.2 表操作2.4.2.1 表…

介绍一下JS垃圾回收机制

JavaScript中的垃圾回收机制负责自动管理内存&#xff0c;回收不再使用的对象所占用的内存空间。在JavaScript中&#xff0c;开发者不需要显式地分配和释放内存&#xff0c;垃圾回收器会自动完成这些操作。以下是关于JavaScript垃圾回收机制的一些关键概念&#xff1a; 内存生命…