电子陶笛的设计与实现_第1页
电子陶笛的设计与实现_第2页
电子陶笛的设计与实现_第3页
电子陶笛的设计与实现_第4页
电子陶笛的设计与实现_第5页
已阅读5页,还剩72页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、实 验 报 告 实验名称: 电子陶笛的设计与实现 题目编号: 题目6 学 院: 电子工程学院 姓 名: 班内序号: 学 号: 班 级: 2014211212 实 验 报 告- 1 -一 设计课题的任务要求- 1 -基本要求- 1 -提高要求- 1 -二 系统设计- 1 -设计思路- 1 -总体框图- 2 -Ø 逻辑流程图- 2 -Ø 逻辑划分方框图- 2 -Ø 总体框图- 3 -分块设计- 4 -(一) 键盘模块- 4 -(二) 数码管模块- 4 -(三) 点阵模块- 4 -(四) 音乐模块- 4 -三 仿真波形及波形分析- 4 -1. 键盘模块- 4 -2. 数

2、码管模块- 6 -3. 点阵模块- 7 -4. 音乐模块- 8 -四 源程序- 9 -1. 键盘模块源程序- 9 -(一) 键盘分频器- 9 -(二) 键盘扫描- 9 -(三) 键盘编码- 10 -(四) 键盘防抖- 12 -(五) 键盘顶层- 13 -2. 数码管模块源程序- 14 -3. 点阵模块源程序- 15 -(一) 点阵分频器- 15 -(二) 点阵译码- 16 -4. 音乐播放模块源程序- 30 -(一) 产生音符模块- 30 -(二) 预置分频系数- 36 -(三) 数控分频发声- 37 -(四) 音乐播放模块顶层- 38 -5. 顶层设计- 40 -五 功能说明及资源利用情况-

3、 42 -六 故障及问题分析- 43 -七 总结和结论- 44 -1 设计课题的任务要求 基本要求 1.用4×4键盘的第一行和第二行各两个按键模拟四孔陶笛的指孔,当按键按下代表“按孔”,按键弹开代表“放孔”,本题目的电子陶笛要求能够演奏中音1至中音7共7个音符; 2.根据四孔陶笛的演奏指法,每演奏一个音符,数码管显示相应的音符,同时蜂鸣器演奏相应的声音; 3.用8×8双色点阵显示电子陶笛四个指控的演奏界面,红色表示“按孔”,绿色表示“放孔”,音符“2”对应下图所示。 4.设置开关键。开机时有不小于5s的开机音乐,并在点阵上显示开机界面。关机状态为点阵全灭,关闭蜂鸣器。 提高

4、要求 1.可通过一个拨码开关进行手动/自动演奏的切换,并与点阵显示配合增加自动演奏乐曲的功能。 2.增加手动演奏音符的存储、播放功能。 3.自拟其他功能。2 系统设计 设计思路根据系统设计要求,电子陶笛设计采用自顶向下的设计方法。整体的功能通过不同的底层模块配合来完成电子陶笛的功能。设计主要分为四个主要的模块:键盘模块、数码管模块、点阵模块以及音乐播放模块。其中键盘模块包含键盘扫描与键盘编码,键盘扫描频率为1kHz左右较为合适,键盘编码是通过给键盘列扫描信号,读取键盘行值来判断是哪个键按下,进而编码输出控制其他模块的音符信号;数码管模块是通过读取音符信号静态显示7个对应的音符;点阵模块是通过读

5、取音符信号来显示相应的四孔指法,扫描时钟为10kHz左右;音乐播放模块包含预置频率值、产生音符信号、数控分频发声三个主要部分,预置频率是给每个音符分配对应的频率,产生音符信号是通过一个手动自动开关信号来控制输出的音符,数控分频发声是通过读取音符信号的预置频率作为分频系数来分频输出给蜂鸣器的,该模块是在系统总时钟50MHz下工作的。最后通过顶层设计将各模块整合连接起来。 总体框图Ø 逻辑流程图 Ø 逻辑划分方框图 Ø 总体框图 分块设计(1) 键盘模块 本次陶笛实验所要求使用的是4×4键盘,并且每个指法对应的键数不一,有一键,两键,三键,四键,这比一次只判

6、别一个键的情况要略微复杂一点,我使用的是四行错开的四个键key2,key5,key12,key15,并设置了四个信号count1-count4,当代表陶笛左列第一孔的key2被按下时,此时keydrv&keyin为11010111,然后将count2编码为1,当key5被按下时count1为1,其它键同理,最后输出count2&count1&count4&count3,能表示四个键排列组合的所有情况,取我们需要的7种代表音符指法信号,输出给其它模块。(2) 数码管模块 数码管模块为静态显示,不需要扫描时钟,开机信号为1时令cat为00000000,八个数码管同时

7、静态显示音符,开机信号为0时令cat为11111111,所有数码管熄灭;输入的音符指孔信号译码为1-7的数字显示,代表七个音符。(3) 点阵模块 点阵模块需要显示开机动画以及陶笛按孔放孔的情况,将50MHz时钟分频为10kHz作为点阵模块的行扫描时钟,然后将10kHz分频为2Hz的时钟,作为开机动画的时钟,及OCARINA几个字母每隔0.5s显示一次,每次显示是快速行扫描每列亮不同的led利用视觉暂留效应来显示完整的图案的;输入的note作为音符指法信号译码为需要显示的指孔图案,红点代表按孔,绿点代表放孔,最后通过快速的行扫描显示出来。(4) 音乐模块 音乐模块包括三个主要部分:手动自动整合产

8、生总音符信号、预置分频系数、分频驱动蜂鸣器发声。其中产生音符信号模块是通过auto信号来控制是否为自动播放,如果是则按照已储存的音乐信息输出音符信号,如果否则输出键盘键入的音符信号,该模块还包括通过pswich来控制开机音乐的音符信号输出;预置分频系数是将音符指控信号译码为每个音符对应的频率值(题目中的表格已给出),分频驱动蜂鸣器发声是通过读取输入的特定音符的频率值tune计算出分频系数,然后将总时钟clk_in分频为该音符频率的时钟clk_out,然后输出给蜂鸣器驱动其发声的。3 仿真波形及波形分析1. 键盘模块仿真波形:(此图接上图尾)clk:时钟输入;keyin:键盘行信号;keydrv

9、:键盘列信号;keyvalue:编码输出指法信号波形分析: 图中的clk为时钟信号,keydrv为输出的列扫描信号,实际扫描速度为1kHz;keyin为键盘的行信号,不按键时为1,按下键之后为0,根据键盘的列扫描信号以及读取对应的行信号来判断是哪个键被按下;图中的keyvalue为编码输出的陶笛指孔信号;为便于分析我设置keyin的值为1011和1111来模拟一次按孔和放孔,当快速扫描键盘每一列时,只有keydrv&keyin为11101011时是我们有用的编码信号,即第一列第二行的按键key5被按下,代表陶笛四孔左列第二孔被按下,编码为0100,对应的音符为6,而1111代表放孔,编

10、码为0000。(我所使用的四个按键为key2,key5,key12,key15,分别代表陶笛左列一二孔和右列一二孔)2. 数码管模块仿真波形:(此图接上图尾)digi_swich:数码管开关;fingnote:输入指法信号;seg:数码管的每一段;cat:数码管的控制信号波形分析: 图中第一个为数码管开关digi_swich,第二个为指孔信号,由图可知,当开关信号为1时,输入指孔信号1111,1101,1110时输出分别为0110000,1101101,1111001,代表数字1、2、3,即数码管显示指孔信号对应的音符;当开关信号为0时,输出的seg为0110011,cat为11111111,

11、数码管全灭。3. 点阵模块仿真波形:(此图接上图尾)Clk_in:时钟输入;led_swich:点阵开关;note:对应音符的指孔信号;row:点阵行信号;col_g:点阵列信号绿灯;col_r点阵列信号红灯波形分析: 上图所示波形为显示开机动画OCARINA中的字母O的波形,由图可见,当时钟信号到来时,点阵开始逐行扫描,同时点阵的列亮不同的红灯,通过视觉暂留效应显示一副完整的图形,即字母O,从而构成动画的第一帧。由于仿真的局限性,此处不列举出动画的完整显示以及音符指控的显示。4. 音乐模块仿真波形:(此图接上图尾)Clk:时钟输入;mswich:音乐播放开关;mclear:自动播放复位;ma

12、uto:曲目1自动播放;mauto1:曲目2自动播放;hang:指孔信号输入;clkout:对应音符频率;yinfu:音符指孔信号输出波形分析: 为了方便分析,将复位信号以及自动播放曲目2信号设为0,而开机信号以及自动播放曲目1设为1,即该仿真为曲目1播放时的仿真;因为总时钟为50MHz,分频后的时钟频率均为几百赫兹,故分频系数很大难以显示完全,我将end time设置为50ms,所显示的是分频后的其中一个周期,该分频后的时钟输出给蜂鸣器驱动其发声。4 源程序1. 键盘模块源程序(1) 键盘分频器 library ieee;use ieee.std_logic_1164.all;use iee

13、e.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity div_100 isport(clkin:in std_logic;-输入总时钟clkout:out std_logic-输出分频后的时钟);end div_100;architecture a of div_100 issignal tmp:integer range 0 to 50000;signal clktmp:std_logic;beginprocess(clkin)beginif (clkin'event and clkin='1')th

14、en if tmp=49999 then tmp<=0; clktmp<=not clktmp; else tmp<=tmp+1; end if;end if;end process;clkout<=clktmp;end a;(2) 键盘扫描library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity keyscan is port(clk_in:in std_logic; -扫描时钟keydrv:out std_l

15、ogic_vector(3 downto 0)-输出扫描信号);end keyscan;architecture a of keyscan issignal count:std_logic_vector(1 downto 0);-计数器信号signal drtmp:std_logic_vector(3 downto 0);beginp0:process(clk_in) begin if rising_edge(clk_in) then if count="11"then count<="00" else count<=count+1; end

16、 if; end if; end process p0;p1:process(count)begin case count iswhen "00"=>drtmp<="1110" -扫第一列when "01"=>drtmp<="1101" -扫第二列when "10"=>drtmp<="1011" -扫第三列when "11"=>drtmp<="0111" -扫第四列when others

17、=>drtmp<="0000"end case;end process p1; keydrv<=drtmp;end a;(3) 键盘编码 library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity key_code isPort( clkin: in std_logic; -时钟输入 keyin : in STD_LOGIC_VECTOR (3 downto 0); -键盘行信号 keydrv : i

18、n STD_LOGIC_VECTOR (3 downto 0);-列扫描信号 finger:out std_logic_vector(3 downto 0) -编码输出对应陶笛的指法 ); end key_code;architecture rtl of key_code issignal count1,count2,count3,count4:std_logic;-输出指法向量的低位到高位signal fingering:std_logic_vector(3 downto 0):="0000"-弹奏指法,按孔为1,放孔为0signal s1,s2,s3,s4,s5,s6,

19、s7,s8:std_logic_vector(3 downto 0);-存储指法编码signal tmp:std_logic_vector(3 downto 0);-最终得到的指法编码begin-temp<=keydrv&keyin;process(keydrv,keyin) begin s1<="1111" s2<="1101" s3<="1110" s4<="1100" s5<="0101" s6<="0100" s7&l

20、t;="0010" s8<="0000"if keydrv="1110" then case keyin is when"1011"=>count1<='1' when others=>count1<='0' end case;elsif keydrv="1101"then case keyin is when"0111"=>count2<='1' when others=>cou

21、nt2<='0' end case; elsif keydrv="1011"then case keyin is when"1110"=>count3<='1' when others=>count3<='0' end case; elsif keydrv="0111"then case keyin is when"1101"=>count4<='1' when others=>count4<=&#

22、39;0' end case; end if; tmp<=count2&count1&count4&count3; case tmp iswhen"0000"=>fingering<=s8;when"1111"=>fingering<=s1;when"1101"=>fingering<=s2;when"1110"=>fingering<=s3;when"1100"=>fingering<=s4;wh

23、en"0101"=>fingering<=s5;when"0100"=>fingering<=s6;when"0010"=>fingering<=s7;when others=>fingering<=s8; end case;end process; finger<=fingering;end rtl; (4) 键盘防抖 library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.st

24、d_logic_unsigned.all;entity Antiwitter is Port ( clkin : in STD_LOGIC; fingerin : in STD_LOGIC_VECTOR (3 downto 0); fingerout : out STD_LOGIC_VECTOR (3 downto 0);end Antiwitter;architecture Behavioral of Antiwitter issignal TempNum:std_logic_vector(3 downto 0);signal Counter:std_logic_vector(4 downt

25、o 0);signal Start:std_logic;beginprocess(clkin)beginif rising_edge(clkin) then if Start='0' thenTempNum<="0000"fingerout<="0000"Start<='1'elseif fingerin/=TempNum thenTempNum<=fingerin;Counter<="00000"elseif Counter="11111" thenf

26、ingerout<=fingerin;Counter<="00000"elseCounter<=Counter+1;end if;end if;end if;end if;end process;end Behavioral;(5) 键盘顶层library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity keyboard isPort ( clk : in STD_LOGIC;-扫描时钟,周期10ms k

27、eyint : in STD_LOGIC_VECTOR (3 downto 0);-键盘行信号 keydrvt : out STD_LOGIC_VECTOR(3 downto 0);-输出扫描信号 keyvalue : out STD_LOGIC_VECTOR(3 downto 0);-编码输出音符信号end keyboard;architecture RTL of keyboard iscomponent keyscanPort ( clk_in : in STD_LOGIC;-扫描时钟 keydrv : out STD_LOGIC_VECTOR(3 downto 0);-输出扫描信号end

28、 component;component key_codePort ( clkin: in std_logic; -时钟输入 keyin : in STD_LOGIC_VECTOR (3 downto 0); -键盘行信号 keydrv : in STD_LOGIC_VECTOR (3 downto 0);-列扫描信号 finger:out std_logic_vector(3 downto 0) -编码输出对应陶笛的指法 );end component;component Antiwitter Port ( clkin : in STD_LOGIC; -时钟输入 fingerin : in

29、STD_LOGIC_VECTOR (3 downto 0);-音符指法信号输入 fingerout : out STD_LOGIC_VECTOR (3 downto 0);-音符指法信号输出end component;signal keydrv1:STD_LOGIC_VECTOR (3 downto 0);-列扫描信号signal key:std_logic_vector(3 downto 0);-音符信号beginU1:keyscanport map(clk_in=>clk,keydrv=>keydrv1);U2:key_codeport map(clkin=>clk,ke

30、yin=>keyint,keydrv=>keydrv1,finger=>key);U3:Antiwitterport map(clkin=>clk,fingerin=>key,fingerout=>keyvalue);keydrvt<=keydrv1;end RTL;2. 数码管模块源程序 library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity digital_tube isport( dig

31、i_swich:in std_logic; -数码管开关 fingnote : in std_logic_vector(3 downto 0); -输入指法表示音符 seg : out std_logic_vector(6 downto 0); -数码管段 cat : out std_logic_vector(7 downto 0) -数码管扫描信号 );end;architecture b of digital_tube isbeginp0: process(fingnote) variable segt : std_logic_vector(6 downto 0); begin if di

32、gi_swich='1'thencase fingnote iswhen "1111" => segt:="0110000"-显示“1”when "1101" => segt:="1101101"-显示“2”when "1110" => segt:="1111001"-显示“3”when "1100" => segt:="0110011"-显示“4”when "0101" =&

33、gt; segt:="1011011"-显示“5”when "0100" => segt:="1011111"-显示“6”when "0010" => segt:="1110000"-显示“7”when others=> segt:="1111110"-显示“0”end case; cat<="00000000" else cat<="11111111"end if;seg<=segt; end pr

34、ocess p0; end b;3. 点阵模块源程序(1) 点阵分频器 library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity div_led isport(clk_in : in std_logic; -输入时钟50MHzclk_out : out std_logic); -输出时钟10kHzend div_led;architecture b of div_led is signal clktmp : std_logic;begi

35、np0:process(clk_in) variable cnt : integer range 0 to 2499;beginif (clk_in'event and clk_in='1') thenif cnt=2499 then -分频系数为2499cnt:=0;clktmp<= not clktmp;elsecnt:=cnt+1; -每个输入时钟上升沿到来时cnt加1end if;end if;end process p0;clk_out<=clktmp;end b;(2) 点阵译码 library ieee;use ieee.std_logic_1

36、164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity led_array isport( clk_in : in std_logic; -时钟输入 note: in std_logic_vector(3 downto 0); -输入音符 led_swich:in std_logic; -开关 row : out std_logic_vector(7 downto 0); -点阵行向量 col_r :out std_logic_vector(7 downto 0); -点阵列向量,放孔显示红色 co

37、l_g :out std_logic_vector(7 downto 0) -点阵列向量,按孔显示绿色 );end led_array;architecture a of led_array issignal cnt:integer range 0 to 7; -慢计数器,控制开机动画的每一帧signal tmp:integer range 0 to 2500;-分频系数signal clk_tmp:std_logic; -动画分频时钟 signal count: integer range 0 to 7;-快计数器,控制点阵行扫描signal rowt: std_logic_vector(7

38、 downto 0);-点阵行向量signal colt_r: std_logic_vector(7 downto 0);-点阵列向量,放孔显示红色signal colt_g: std_logic_vector(7 downto 0); -点阵列向量,按孔显示绿色beginp1:process(clk_in)begin if (clk_in'event and clk_in='1') thenif count=7 then count<=0;elsecount<=count+1;-用count来记数end if;end if;end process p1;p

39、2:process(clk_in)beginif (clk_in'event and clk_in='1') thenif tmp=2499 then -动画分频器tmp<=0;clk_tmp<=not clk_tmp;elsetmp<=tmp+1;end if;end if; end process p2;p3:process(clk_tmp,led_swich) begin if led_swich='0'then -动画计数器 cnt<=0; elsif (clk_tmp'event and clk_tmp='

40、;1') then if cnt=7 thencnt<=cnt; -控制开机动画只显示一次else cnt<=cnt+1;end if;end if; end process p3;p4: process(cnt,count,note,led_swich) begin if led_swich='1'then case cnt is -显示开机动画 when 0=> -显示“O” case count is when 0=> rowt<="11111110" colt_g<="00000000"

41、 colt_r<="00000000" when 1=> rowt<="11111101" colt_g<="00000000" colt_r<="00111100" when 2=> rowt<="11111011" colt_g<="00000000" colt_r<="01000010" when 3=> rowt<="11110111" colt_g<=&q

42、uot;00000000" colt_r<="01000010" when 4=> rowt<="11101111" colt_g<="00000000" colt_r<="01000010" when 5=> rowt<="11011111" colt_g<="00000000" colt_r<="01000010" when 6=> rowt<="10111111&q

43、uot; colt_g<="00000000" colt_r<="01000010" when 7=> rowt<="01111111" colt_g<="00000000" colt_r<="00111100" when others=> rowt<="11111111" colt_r<="00000000" colt_g<="00000000"end case; when

44、1=> -显示“C” case count is when 0=> rowt<="11111110" colt_g<="00000000" colt_r<="00000000" when 1=> rowt<="11111101" colt_g<="00000000" colt_r<="00111100" when 2=> rowt<="11111011" colt_g<="0

45、0000000" colt_r<="01000010" when 3=> rowt<="11110111" colt_g<="00000000" colt_r<="00000010" when 4=> rowt<="11101111" colt_g<="00000000" colt_r<="00000010" when 5=> rowt<="11011111"

46、colt_g<="00000000" colt_r<="00000010" when 6=> rowt<="10111111" colt_g<="00000000" colt_r<="01000010" when 7=> rowt<="01111111" colt_g<="00000000" colt_r<="00111100" when others=> rowt<

47、;="11111111" colt_r<="00000000" colt_g<="00000000"end case; when 2=> -显示“A” case count is when 0=> rowt<="11111110" colt_g<="00000000" colt_r<="00000000" when 1=> rowt<="11111101" colt_g<="000000

48、00" colt_r<="01000010" when 2=> rowt<="11111011" colt_g<="00000000" colt_r<="01000010" when 3=> rowt<="11110111" colt_g<="00000000" colt_r<="01000010" when 4=> rowt<="11101111" colt_

49、g<="00000000" colt_r<="01111110" when 5=> rowt<="11011111" colt_g<="00000000" colt_r<="01000010" when 6=> rowt<="10111111" colt_g<="00000000" colt_r<="00100100" when 7=> rowt<="01

50、111111" colt_g<="00000000" colt_r<="00011000" when others=> rowt<="11111111" colt_r<="00000000" colt_g<="00000000"end case; when 3=> -显示“R” case count is when 0=> rowt<="11111110" colt_g<="00000000&qu

51、ot; colt_r<="00000000" when 1=> rowt<="11111101" colt_g<="00000000" colt_r<="00110010" when 2=> rowt<="11111011" colt_g<="00000000" colt_r<="00001010" when 3=> rowt<="11110111" colt_g<

52、="00000000" colt_r<="00000110" when 4=> rowt<="11101111" colt_g<="00000000" colt_r<="00011110" when 5=> rowt<="11011111" colt_g<="00000000" colt_r<="00100010" when 6=> rowt<="1011111

53、1" colt_g<="00000000" colt_r<="00100010" when 7=> rowt<="01111111" colt_g<="00000000" colt_r<="00011100" when others=> rowt<="11111111" colt_r<="00000000" colt_g<="00000000"end case; when 4=> -显示“I” case count is when 0=> rowt<="11111110" colt_g<="00000000" colt_r<="00000000" when 1=> rowt<="11111101&

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论