本篇为各位朋友介绍基于FPGA的电子琴设计(按键和蜂鸣器)----第一版。

功能说明:

外部输入七个按键,分别对应音符的“1、2、3、4、5、6、7”,唱作do、re、mi、fa、sol、la、si。当某个按键按下时,蜂鸣器发出对应的声音----1. 默认发出0.2秒(可以调整)。2. 蜂鸣器发出对应的中音。

使用平台:本次设计应用Altera的平台设计(芯片:EP4CE10F17C8N)。

仿真平台:Modelsim。

作者QQ:746833924

说明:本篇设计中不涉及到IP和原语,代码在其他平台依然可以适用;当其他板卡电路不同时,会导致不同的现象出现,如有需要修改代码请联系作者;如需作者使用的板卡,请联系作者;

蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。

蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。

压电式蜂鸣器 压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。有的压电式蜂鸣器外壳上还装有发光二极管。多谐振荡器由晶体管或集成电路构成。当接通电源后(1.515V直流工作电压),多谐振荡器起振,输出1.52.5kHZ的音频信号,阻抗匹配器推动压电蜂鸣片发声。

电磁式蜂鸣器电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场。振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。

按照内部有无震荡源可以分为有源蜂鸣器和无源蜂鸣器。有源蜂鸣器内部带震荡源,所以只要一通电就会发出声音;而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。必须用一定频率的方波去驱动它。

蜂鸣器给予不同的频率是可以发出近似1、2、3、4、5、6、7这七个基本音符。

设计思想如下:

    key_ctrl模块负责将外部的按键信号进行消抖,并且产生对应边沿变化时的脉冲;piano_beep_ctrl模块负责根据脉冲信号产生输出控制脉冲(一个周期)和应该输出音符对应波形的半周期数;beep_ctrl模块根据piano_beep_ctrl产生脉冲时,接收半周期数,然后产生对应的方波持续0.2秒。

key_ctrl模块设计思想为:按键信号是由外部机械式按键产生,每次按下或者抬起时,会产生一定的抖动。如果直接对其进行边沿检测就会导致多次触发。故而需要设计按键消抖,进而对消抖之后的波形进行边沿检测。消抖原理为:外部按键信号发生改变后,如果能够持续20ms,没有新的改变,就认为此次改变不是抖动,而是真正的按下,然后进行采样即可。

// 记录任意边沿之后没有遇到新的边沿的时间长度是否达到20Ms

//---------------------------------------------------------------------------------------

always@(posedgeclk)begin

if(rst_n ==1'b0)

 cnt_20ms <=20'd0;

else

 if(pulse_key_negedge ==1'b1||pulse_key_posedge ==1'b1)

   cnt_20ms <=20'd1;

 else

   if(cnt_20ms >20'd0&&cnt_20ms <T_20ms)

     cnt_20ms <=cnt_20ms +1'b1;

   else

       cnt_20ms <=20'd0;

end

// ---------------------------------------------------------------------------------------

// 任意边沿之后没有遇到新的边沿的时间长度达到20Ms,认为按键稳定,此时采样

//--------------------------------------------------------------------------------------

initial key_wave = 1'b1;

always@(posedgeclk)begin

if(rst_n ==1'b0)

 key_wave <=1'b1;

else

 if(cnt_20ms ==T_20ms)

   key_wave <=key_rr;

 else

   key_wave <=key_wave;

end

//--------------------------------------------------------------------------------------

// 对消抖之后的按键信号进行边沿检测

//---------------------------------------------------------------------------------------------

initialkey_wave_r =1'b1;

always@(posedgeclk)key_wave_r <=key_wave;

assignflag_neg =(key_wave_r ==1'b1&&key_wave ==1'b0)?1'b1:1'b0;

assignflag_pos =(key_wave_r ==1'b0&&key_wave ==1'b1)?1'b1:1'b0;

//--------------------------------------------------------------------------------------------

piano_beep_crtl模块中,计算半周期数的方法如下:

假如要发出中音“1”,就需要输出频率为523.3hz的方波。此方波对应的周期为1910949.742021785 ns,我们取1910950ns。因为我们使用的基本时钟为50MHz,周期为20ns,以及我们预计计数一半取反来生成方波,所以只需要计数一般,即:1910950/2/20 = 47774;

将其他的全部计算出来:

// 1 : 523.3Hz num : 47774

// 2 : 587.3Hz num : 42568

// 3 : 659.3Hz num : 37919

// 4 : 698.5Hz num : 35791

// 5 : 784Hz num : 31888

// 6 : 880Hz num : 28409

// 7 : 987.8Hz num : 25309

// 产生输出脉冲:无论外部那个脉冲有效,都对外产生一个脉冲

always @ (posedge clk) begin

if (rst_n == 1'b0)

 flag <= 1'b0;

else

 flag <= |key_flag;

end

// 如果外部多个脉冲同时有效,那么输出num为0

always @ (posedge clk) begin

if (rst_n == 14'b0)

 num <= 32'd0;

else

 case (key_flag)

   7'b100_0000    :   num <= 32'd47774;

   7'b010_0000    :   num <= 32'd42568;

   7'b001_0000    :   num <= 32'd37919;

   7'b000_1000    :   num <= 32'd35791;

   7'b000_0100    :   num <= 32'd31888;

   7'b000_0010    :   num <= 32'd28409;

   7'b000_0001    :   num <= 32'd25309;

   default        :   num <= 32'd0;

 endcase

end

以上即为piano_beep_ctrl模块的设计思想;

在beep_ctrl中,首先设计一个当输入脉冲时,就让一个计数器cnt_200ms记录0.2秒。

// 外部输入一个脉冲,cnt_200ms计数器记录200ms的时间

// 如果第一个脉冲输入后,没有计时到200ms,第二个脉冲没有任何作用

always @ (posedge clk) begin

if (rst_n == 1'b0)

 cnt_200ms <= 32'd0;

else

 if (flag == 1'b1 && cnt_200ms == 32'd0)

   cnt_200ms <= cnt_200ms + 1'b1;

 else

   if (cnt_200ms > 32'd0 && cnt_200ms < T_200ms - 1'b1)

     cnt_200ms <= cnt_200ms + 1'b1;

   else

     cnt_200ms <= 32'd0;

end

由于外部给予半周期数时,只有一个周期有效,所以需要寄存一下。

//外部输入脉冲时,寄存外部输入的半周期的时钟数

always @ (posedge clk) begin

if (rst_n == 1'b0)

 num_r <= 32'd0;

else

 if (flag == 1'b1 && cnt_200ms == 32'd0)

   num_r <= num;

 else

   num_r <= num_r;

end

当200ms计数器开始计数后,我们启动另外一个计数器ocnt,来记录需要输出方波的半周期数。然后当到半周期数的时候,将输出值取反。

// 当200ms开始计时后,输出计数器开始计数,

// 只需要计数到外部输入的半周期时钟数即可

always @ (posedge clk) begin

if (rst_n == 1'b0)

 ocnt <= 32'd0;

else

 if (cnt_200ms > 32'd0)

   if (ocnt < num_r)

     ocnt <= ocnt + 1'b1;

   else

     ocnt <= 32'd0;

 else

   ocnt <= 32'd0;

end

// 当外部输入的半周期时钟数为0时,蜂鸣器不动作

// 当不为0时,到半周期时钟数,将输出取反

always @ (posedge clk) begin

if (rst_n == 1'b0)

 beep <= 1'b0;

else

 if (num_r == 32'd0)

   beep <= 1'b0;

 else

   if (ocnt == num_r)

     beep <= ~beep;

   else

     beep <= beep;

end

以上即为所有的设计说明。

仿真时,需要将消抖模块中的20ms进行调小,否则仿真的时长将会格外的长。

下板后,经过按下不同的按键,蜂鸣器就可以产生对应的声音。

下板后,演示视频(链接)如下:

https://www.bilibili.com/video/BV1Gk4y1X7XT/?spm_id_from=333.999.0.0&vd_source=b5405faeab8632f02533bcbfc5e52e55

 本设计所有内容(设计代码、设计工程)链接为:

链接:https://pan.baidu.com/s/1VGbPqU9O_k2UBtOGkMJjIQ

提取码:dzye

本篇内容中有部分资源来源于网络,如有侵权,请联系作者。

更多的内容可以关注作者的其他博客,也可以关注微信公众账号:郝旭帅电子设计团队

基于FPGA的电子琴设计(按键和蜂鸣器)---第一版---郝旭帅电子设计团队的更多相关文章

  1. 基于FPGA的DDR3多端口读写存储管理系统设计

    基于FPGA的DDR3多端口读写存储管理系统设计 文章出处:电子技术设计 发布时间: 2015/03/12 | 1747 次阅读 每天新产品 时刻新体验专业薄膜开关打样工厂,12小时加急出货   机载 ...

  2. 基于FPGA的按键扫描程序

    最近在学习FPGA,就试着写了个按键扫描的程序.虽说有过基于单片机的按键扫描处理经验,对于按键的处理还是有一些概念.但是单片机程序的编写通常都采用C写,也有用汇编,而FPGA却是采用VHDL或者Ver ...

  3. 基于FPGA的HDMI显示设计(三)

    上一篇:基于FPGA的VGA显示设计(二) 10月10日 ~ 20日期间实习,令我万万没想到的是实习题目是 “便携式高清电视显示屏测试系统原型设计” 也就是 “基于FPGA的视频显示”. 实习要求用 ...

  4. 优化基于FPGA的深度卷积神经网络的加速器设计

    英文论文链接:http://cadlab.cs.ucla.edu/~cong/slides/fpga2015_chen.pdf 翻译:卜居 转载请注明出处:http://blog.csdn.net/k ...

  5. 基于FPGA的DDS设计(一)

    最近在学习基于FPGA的DDS设计,借此机会把学习过程记录下来,当作自己的学习笔记也希望能够帮助到学习DDS的小伙伴. DDS(Direct Digital Synthesizer)直接数字合成器,这 ...

  6. 基于FPGA的XPT2046触摸控制器设计

    基于FPGA的XPT2046触摸控制器设计 小梅哥编写,未经许可,文章内容和所涉及代码不得用于其他商业销售的板卡 本实例所涉及代码均可通过向 xiaomeige_fpga@foxmail.com  发 ...

  7. 基于FPGA的VGA显示设计(二)

    上一篇:基于FPGA的VGA显示设计(一)     参照 CrazyBingo 的 基于FPGA的VGA可移植模块终极设计代码  的工程代码风格,模块化处理了上一篇的代码,并增加了一点其它图形. 顶层 ...

  8. 基于FPGA的VGA可移植模块终极设计【转】

    本文转载自:http://www.cnblogs.com/lueguo/p/3373643.html 略过天涯   基于FPGA的VGA可移植模块终极设计 一.VGA的诱惑 首先,VGA的驱动,这事, ...

  9. 基于FPGA的SPI FLASH控制器设计

    1.SPI FLASH的基本特征 本文实现用FPGA来设计SPI FLASH,FLASH型号为W25Q128BV.支持3种通信方式,SPI.Dual SPI和Quad SPI.FLASH的存储单元无法 ...

  10. 012 基于FPGA的网口通信实例设计【转载】

    一.网口通信设计分类 通过上面其他章节的介绍,网口千兆通信,可以使用TCP或者UDP协议,可以外挂PHY片或者不挂PHY片,总结下来就有下面几种方式完成通信: 图8‑17基于FPGA的网口通信实例设计 ...

随机推荐

  1. 使用SpringBoot开发一个POST接口

    SpringBoot项目的分层 SpringBoot框架项目一般分为五层: View层:向用户展示页面 Controller层:前后端交互层,接收前端请求,调用Service层中的方法,接收Servi ...

  2. Django框架项目——redis操作、Celery

    1-redis操作 redis介绍 redis安装 """ 1.官网下载:安装包或是绿色面安装 2.安装并配置环境变量 """ redis ...

  3. .NET Core使用SkiaSharp快速生成二维码( 真正跨平台方案)

    前言 在.NET 6之前我们一直是使用QRCoder来生成二维码(QRCoder是一个非常强大的生成二维码的组件,用到了System.Drawing.Common 包),然后从.NET 6开始,当为非 ...

  4. 中华人民共和国企业所得税月(季)度预缴纳税申报表(A类,2018年版)

    企业按照<中华人民共和国公司法>有关规定整体改制,包括非公司制企业改制为有限责任公司或股份有限公司,有限责任公司变更为股份有限公司,股份有限公司变更为有限责任公司,原企业投资主体存续并在改 ...

  5. P6346 [CCO2017] 专业网络 & CF1251E1 Voting(Easy Version)

    analysis 这个题目我们可以考虑用贪心来做. 我们不难看出来,这个题目是要让我们推出这么个结论:花小钱,办大人. 整体贪心的思路就出来了,然后就是实现部分. 因为我们认识的人随便是谁都可以.所以 ...

  6. 04-华为HyperReplication中的多时间片技术

    简介 多时间片技术,是应用于HyperReplication的异步远程复制:提高效率, 在同步远程复制中,没有这个概念: 时间片:在Cache中管理一段时间内写入数据的逻辑空间(数据大小没有限定): ...

  7. 我们又组织了一次欧洲最大开源社区活动,Hugging Face 博客欢迎社区成员发帖、Hugging Chat 功能更新!

    每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...

  8. mysqli操作

    1.使用mysqli_connect()函数,语法如下: mysqli 对象名=mysqli_connect(数据库服务名,用户名,密码,数据库名) 例:$conn=mysqli_connect('l ...

  9. P8815 [CSP-J 2022] 逻辑表达式

    Problem 考察算法:后缀表达式计算.建表达式树.\(DFS\). 题目简述 给你一个中缀表达式,其中只有 \(\&\) 和 \(\mid\) 两种运算. 求:\(\&\) 和 \ ...

  10. 字符串小记 I:基本结构与简单匹配(更新中)

    0.一些定义 在开始之前,我们先给出一些关于字符串的定义: 记 \(|S|\) 表示字符串 \(S\) 的长度,\(S_i\) 表示该字符串中第 \(i\) 位的字符,\(S_{l,r}\) 表示该字 ...