视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
实验09硬件电子琴
2025-09-30 19:47:51 责编:小OO
文档
实验九  硬件电子琴

一. 实验目的

1. 了解交流蜂鸣器的发音原理;

2. 利用蜂鸣器呵呵按键设计硬件电子琴;

3. 学会在编写HDL顶层文件。

二. 准备知识

与利用微处理器(CPU或MCU)来实现乐曲演奏相比,以纯硬件完成乐曲演奏电路的逻辑要复杂的多,仅凭传统的数字逻辑技术,很难完成简单的演奏电路,但是借助于功能强大的EDA工具与VHDL语言,就相对简单,很容易实现。

实验箱上有1个交流蜂鸣器BUZZER,通过跳线JP6的BEEP与可编程逻辑器件相连接。其硬件原理图如图!!!!!!!!所示。可以看出,为了增加I/O口的驱动能力,在此采用了PNP型三极管,这样只要在BEEP上输入一定频率的脉冲,蜂鸣器就会发出音乐。从能量的角度来说,这个脉冲信号占空比最好为1:1,此时蜂鸣器的发声强度最大。

乐曲演奏的原理:由于组成乐曲的每个音符的频率值(音调)及其持续时间(音长)是乐曲演奏的2个基本数据,因此需要控制输出到蜂鸣器的激励信号的频率和该频率信号持续的时间。

频率的高低决定了音调的高低,而乐曲的简谱与个音名的频率对应关系如表9.1所示。所以不同的频率的信号都从同一基准频率分频而来的。由于音节频率为非整数,而把分频系数作为小数处理又太麻烦,故需将计算得到的分频数进行四舍五入取整处理,并且其基准频率和分频系数应综合考虑加以选择,从而保证音乐不会走调。如在48MHz的时钟下,中音1(对应的频率值为523..25Hz)的分频系数应该为48000000/(2*523.25)=0xb327,这样只需对系统的时钟进行45863次分频,然后再进行占空比为1:1的二分频即可得到所要的中音1.至于其它音符,同样可以求出其对应的分频系数。如表9.2所示。

表9.1  简谱中的音名与频率的关系

                                         单位:Hz

低音部1234567
频 率

261.63293.67329.63349.23391.99440.00493.88
中音部1234567
频 率

523.25587.33659.25698.46783.99880987.76
高音部1234567
频 率

1046.501174.661381.511396.921567.9817601975.52
注:中音频率为低音的2倍,高音频率为中音的2倍

表9.2  简谱中音名与分频次数的关系

                                         单位:次数

低音部1234567
频 率

91734817267281068723612255454548595
中音部1234567
频 率

45867408633474534361306132727324297
高音部1234567
频 率

22934 20431 17372 17181 15306 13636 12149 
从表9.2可知,分频器即计数器的位宽为17位即可。分频计数器的计数方式是0~N还是N~满量程,在程序中需要加以区别,实验中最好采用N~满量程的就是方式,那么计数器计满时的加载数就是计满最大值+1-48000000/(2*f)。如表9.3所示。分频器即计数器的位宽设为17位。

表9.3  简谱中音名与加载数的关系

                                         单位:次数

低音部1234567
频 率

39338 49346 58262 62349 69847 76527 82477 
中音部1234567
频 率

85205 90209 96327 96711 100459 103799 106775 
高音部1234567
频 率

108138 1101 113700 1131 115766 117436 1123 
说明:表9.3的加载数和设计的分频器的位宽有关系。

因为只有8个按键,所以这里为了简单起见,进行如下处理:按键key1~key7按下(低电平)时分别对应中音部的1~7,此时数码管8显示音符,数码7全灭不显示,;而按键key8按下时,按键key1~key7分别对应高音部的1~7,此时数码管8显示音符,数码7显示“H”,即标志为高音。为了简单起见,按键不进行消抖处理。

三. 实验步骤

1、新建工程beep1

新建文件夹,并在该文件夹下新建工程beep1。

2、新建顶层文件

新建HDL文件tone,并设为顶层实体文件。

本实验训练的工程文件只包含1个HDL顶层文件,即在一个HDL文件中实现硬件电子琴的设计。

该文件的输入管脚包括:按键key[7..0]、系统时钟clk48M;输出包括:蜂鸣器buzzer、扫描显示的位码dig[7..0]、扫描显示的段码seg[7..0]。

按键key8,按下时(低电平),数码7(段码定义为seg7)显示“H”(seg7= "10001001"),反之不显示(seg7="11111111")。

按键key7~key1,有且只有1个按键按下时(低电平),数码8(段码定义为seg8)分别显示“7”~“1”,并得出不同的加载数count_start;无key7~key1操作时,数码8不显示即全灭(seg8="11111111")。

按下key8时,再分别按键key7~key1,按下时(低电平),数码8分别显示“7”~“1”,译码出不同的加载数。无key7~key1操作时,数码8不显示即全灭。

计数范围为加载数N~满量程的带进位beep_r的进程。

beep_r经T触发器,结果为送蜂鸣器buzzer。

48MHz的系统时钟分频,得到占空比为1:1的clk100Hz时钟信号。该时钟信号为高电平时,点亮数码7(位码dig=“11111101”,段码reg=seg7);该时钟信号为低电平时,点亮数码8(位码dig=“11111110”,段码reg=seg8);

注意:各个进程之间的“连线”就是信号,进程之间依靠信号进行传递“数据”的,故需要定义一些信号(VHDL)或寄存器(Verilog HDL)。

3、编译、锁定管脚、再编译

指定ADDER8原理图文件为顶层文件。

为了方便锁定管脚,我们先进行编译,发现错误进行纠正,直至成功为止。

锁定管脚(管脚表)

再编译,把管脚锁定的信息编译到下载文件中去。

4、下载

连接电源,进行下载

根据设计思路,试验结果。

四. 实验参考程序

程序清单 tone.VHD

LIBRARY IEEE;

USE        IEEE.STD_LOGIC_11.ALL;

USE     IEEE.STD_LOGIC_UNSIGNED.ALL;

USE        IEEE.STD_LOGIC_ARITH.ALL;

ENTITY tone IS

PORT(    clk48M:    IN    STD_LOGIC; --系统时钟48MHz

        key:        IN    STD_LOGIC_VECTOR(7 DOWNTO 0);--按键输入

        buzzer:    OUT STD_LOGIC;--蜂鸣器输出端

        seg:        OUT    STD_LOGIC_VECTOR(7 DOWNTO 0);--数码管段码输出

        dig:        OUT    STD_LOGIC_VECTOR(7 DOWNTO 0) ); --数码管位码输出

END ;

ARCHITECTURE one  OF tone IS

SIGNAL    beep,beep_r,clk100Hz,clk50Hz:    STD_LOGIC;

SIGNAL    count,count_start:    integer range 0 to 131071; --预置数分频器中间计数值信号

SIGNAL    count100Hz:    integer range 0 to 480000;--100Hz计数器中间计数值信号

SIGNAL    seg8,seg7:    STD_LOGIC_VECTOR(7 DOWNTO 0);--数码7、8的译码

BEGIN

    PROCESS(clk48M)

    BEGIN

        IF    RISING_EDGE(clk48M)THEN

            IF count=131071 THEN --计满X”1FFFF”

                count<=    count_start;--加载预置数

                beep_r<='1'; --输出进位,触发T触发器

            ELSE

                count<=count+1;

                beep_r<='0';

            END IF;        

        END IF;

    END PROCESS;

    PROCESS(beep_r)

    BEGIN

        IF    RISING_EDGE(beep_r)THEN

            beep <= not beep; --T触发器,得到1:1方波

        END IF;

    END PROCESS;

    buzzer <= beep;--输出到蜂鸣器

        

    PROCESS(key)

    BEGIN

        CASE    key    IS

            WHEN     "11111110"=>    count_start<=85205;seg8<=X"f9";--中音1预置数及显示译码

            WHEN    "11111101"=>    count_start<=90209;seg8<=X"a4";--中音2

            WHEN    "11111011"=>    count_start<=96327;seg8<=X"b0";--中音3

            WHEN    "11110111"=>    count_start<=96711;seg8<=X"99";--中音4

            WHEN    "11101111"=>    count_start<=100459;seg8<=X"92";--中音5

            WHEN    "11011111"=>    count_start<=103799;seg8<=X"82";--中音6 

            WHEN    "10111111"=>    count_start<=106775;seg8<=X"f8";--中音7 

            

            WHEN    "01111110"=>    count_start<=108138;seg8<=X"f9";--高音1

            WHEN    "01111101"=>    count_start<=1101;seg8<=X"a4";--高音2 

            WHEN    "01111011"=>    count_start<=113700;seg8<=X"b0";--高音3

            WHEN    "01110111"=>    count_start<=1131;seg8<=X"99";--高音4

            WHEN    "01101111"=>    count_start<=115766;seg8<=X"92";--高音5 

            WHEN    "01011111"=>    count_start<=117436;seg8<=X"82";--高音6 

            WHEN    "00111111"=>    count_start<=1123;seg8<=X"f8";--高音7 

            WHEN    OTHERS=>    count_start<=131071;seg8<=X"ff";--无声、无显示

        END CASE;

        

        CASE key(7)    IS        --key8按下时

            WHEN     '0'        =>     seg7<="10001001";--显示"H"

            WHEN    OTHERS    =>    seg7<="11111111";--不显示

        END CASE;

    END PROCESS;

    

    PROCESS(clk48M)

    BEGIN

        IF    RISING_EDGE(clk48M)THEN

            IF count100Hz = 240000 THEN

                count100Hz <= 0;

                clk100Hz <= not clk100Hz;--反转,占空比1:1

                --clk100Hz <= '1';

            ELSE

                count100Hz <= count100Hz+1;

                --clk100Hz <= '0';

            END IF;        

        END IF;

    END PROCESS;

    PROCESS(clk100Hz)

    BEGIN

        IF    clk100Hz='1'THEN

            seg<=seg7;        --显示数码7的内容

            dig<="11111101";     --选通数码7

        ELSE

            seg<=seg8;        --显示数码8的内容

            dig<="11111110";    --选通数码8

        END IF;        

    END PROCESS;

    

END;下载本文

显示全文
专题