
楼主我这里有电子琴的单片机程序,做毕业设计那个我觉得还是自己做得好,因为你没懂的话论文答辩是过不了的。简易电子琴#include<> //包含51单片机寄存器定义的头文件sbit P14=P1^4; //将P14位定义为引脚sbit P15=P1^5; //将P15位定义为引脚sbit P16=P1^6; //将P16位定义为引脚sbit P17=P1^7; //将P17位定义为引脚unsigned char keyval; //定义变量储存按键值sbit sound=P3^7; //将sound位定义为 int C; //全局变量,储存定时器的定时常数unsigned int f; //全局变量,储存音阶的频率//以下是C调低音的音频宏定义#define l_dao 262 //将“l_dao”宏定义为低音“1”的频率262Hz#define l_re 286 //将“l_re”宏定义为低音“2”的频率286Hz#define l_mi 311 //将“l_mi”宏定义为低音“3”的频率311Hz#define l_fa 349 //将“l_fa”宏定义为低音“4”的频率349Hz#define l_sao 392 //将“l_sao”宏定义为低音“5”的频率392Hz#define l_la 440 //将“l_a”宏定义为低音“6”的频率440Hz#define l_xi 494 //将“l_xi”宏定义为低音“7”的频率494Hz//以下是C调中音的音频宏定义#define dao 523 //将“dao”宏定义为中音“1”的频率523Hz#define re 587 //将“re”宏定义为中音“2”的频率587Hz#define mi 659 //将“mi”宏定义为中音“3”的频率659Hz#define fa 698 //将“fa”宏定义为中音“4”的频率698Hz#define sao 784 //将“sao”宏定义为中音“5”的频率784Hz#define la 880 //将“la”宏定义为中音“6”的频率880Hz#define xi 987 //将“xi”宏定义为中音“7”的频率53//以下是C调高音的音频宏定义#define h_dao 1046 //将“h_dao”宏定义为高音“1”的频率1046Hz#define h_re 1174 //将“h_re”宏定义为高音“2”的频率1174Hz#define h_mi 1318 //将“h_mi”宏定义为高音“3”的频率1318Hz#define h_fa 1396 //将“h_fa”宏定义为高音“4”的频率1396Hz#define h_sao 1567 //将“h_sao”宏定义为高音“5”的频率1567Hz#define h_la 1760 //将“h_la”宏定义为高音“6”的频率1760Hz#define h_xi 1975 //将“h_xi”宏定义为高音“7”的频率1975Hz/**************************************************************函数功能:软件延时子程序**************************************************************/void delay20ms(void) {unsigned char i,j;for(i=0;i<100;i++)for(j=0;j<60;j++);}/*******************************************函数功能:节拍的延时的基本单位,延时200ms******************************************/void delay() {unsigned char i,j;for(i=0;i<250;i++)for(j=0;j<250;j++);}/*******************************************函数功能:输出音频入口参数:F******************************************/void Output_Sound(void){C=(46083/f)*10; //计算定时常数TH0=(8192-C)/32; //可证明这是13位计数器TH0高8位的赋初值方法TL0=(8192-C)%32; //可证明这是13位计数器TL0低5位的赋初值方法TR0=1; //开定时T0delay(); //延时200ms,播放音频TR0=0; //关闭定时器sound=1; //关闭蜂鸣器keyval=0xff; //播放按键音频后,将按键值更改,停止播放}/*******************************************函数功能:主函数******************************************/ void main(void){ EA=1; //开总中断ET0=1; //定时器T0中断允许ET1=1; //定时器T1中断允许TR1=1; //定时器T1启动,开始键盘扫描TMOD=0x10; //分别使用定时器T1的模式1,T0的模式0TH1=(65536-500)/256; //定时器T1的高8位赋初值TL1=(65536-500)%256; //定时器T1的高8位赋初值 while(1) //无限循环{switch(keyval){case 1:f=dao; //如果第1个键按下,将中音1的频率赋给fOutput_Sound(); //转去计算定时常数 break;case 2:f=l_xi; //如果第2个键按下,将低音7的频率赋给fOutput_Sound(); //转去计算定时常数 break;case 3:f=l_la; //如果第3个键按下,将低音6的频率赋给fOutput_Sound(); //转去计算定时常数 break;case 4:f=l_sao; //如果第4个键按下,将低音5的频率赋给fOutput_Sound(); //转去计算定时常数 break;case 5:f=sao; //如果第5个键按下,将中音5的频率赋给fOutput_Sound(); //转去计算定时常数 break;case 6:f=fa; //如果第6个键按下,将中音4的频率赋给fOutput_Sound(); //转去计算定时常数 break;case 7:f=mi; //如果第7个键按下,将中音3的频率赋给fOutput_Sound(); //转去计算定时常数 break; case 8:f=re; //如果第8个键按下,将中音2的频率赋给fOutput_Sound(); //转去计算定时常数 break;case 9:f=h_re; //如果第9个键按下,将高音2的频率赋给fOutput_Sound(); //转去计算定时常数 break;case 10:f=h_dao; //如果第10个键按下,将高音1的频率赋给fOutput_Sound(); //转去计算定时常数 break;case 11:f=xi; //如果第11个键按下,将中音7的频率赋给fOutput_Sound(); //转去计算定时常数 break;case 12:f=la; //如果第12个键按下,将中音6的频率赋给fOutput_Sound(); //转去计算定时常数 break; case 13:f=h_la; //如果第13个键按下,将高音6的频率赋给fOutput_Sound(); //转去计算定时常数 break;case 14:f=h_sao; //如果第14个键按下,将高音5的频率赋给fOutput_Sound(); //转去计算定时常数 break;case 15:f=h_fa; //如果第15个键按下,将高音4的频率赋给fOutput_Sound(); //转去计算定时常数 break;case 16:f=h_mi; //如果第16个键按下,将高音3的频率赋给fOutput_Sound(); //转去计算定时常数 break; } } } /**************************************************************函数功能:定时器T0的中断服务子程序,使引脚输出音频方波**************************************************************/ void Time0_serve(void ) interrupt 1 using 1 {TH0=(8192-C)/32; //可证明这是13位计数器TH0高8位的赋初值方法TL0=(8192-C)%32; //可证明这是13位计数器TL0低5位的赋初值方法 sound=!sound; //将引脚取反,输出音频方波}/**************************************************************函数功能:定时器T1的中断服务子程序,进行键盘扫描,判断键位**************************************************************/ void time1_serve(void) interrupt 3 using 2 //定时器T1的中断编号为3,使用第2组寄存器{TR1=0; //关闭定时器T0P1=0xf0; //所有行线置为低电平“0”,所有列线置为高电平“1”if((P1&0xf0)!=0xf0) //列线中有一位为低电平“0”,说明有键按下{delay20ms(); //延时一段时间、软件消抖if((P1&0xf0)!=0xf0) //确实有键按下{P1=0xfe; //第一行置为低电平“0”(输出低电平“0”)if(P14==0) //如果检测到接引脚的列线为低电平“0”keyval=1; //可判断是S1键被按下if(P15==0) //如果检测到接引脚的列线为低电平“0”keyval=2; //可判断是S2键被按下if(P16==0) //如果检测到接引脚的列线为低电平“0”keyval=3; //可判断是S3键被按下if(P17==0) //如果检测到接引脚的列线为低电平“0”keyval=4; //可判断是S4键被按下P1=0xfd; //第二行置为低电平“0”(输出低电平“0”)if(P14==0) //如果检测到接引脚的列线为低电平“0”keyval=5; //可判断是S5键被按下if(P15==0) //如果检测到接引脚的列线为低电平“0”keyval=6; //可判断是S6键被按下if(P16==0) //如果检测到接引脚的列线为低电平“0”keyval=7; //可判断是S7键被按下if(P17==0) //如果检测到接引脚的列线为低电平“0”keyval=8; //可判断是S8键被按下P1=0xfb; //第三行置为低电平“0”(输出低电平“0”)if(P14==0) //如果检测到接引脚的列线为低电平“0”keyval=9; //可判断是S9键被按下if(P15==0) //如果检测到接引脚的列线为低电平“0”keyval=10; //可判断是S10键被按下if(P16==0) //如果检测到接引脚的列线为低电平“0”keyval=11; //可判断是S11键被按下if(P17==0) //如果检测到接引脚的列线为低电平“0”keyval=12; //可判断是S12键被按下P1=0xf7; //第四行置为低电平“0”(输出低电平“0”)if(P14==0) //如果检测到接引脚的列线为低电平“0”keyval=13; //可判断是S13键被按下if(P15==0) //如果检测到接引脚的列线为低电平“0”keyval=14; //可判断是S14键被按下if(P16==0) //如果检测到接引脚的列线为低电平“0”keyval=15; //可判断是S15键被按下if(P17==0) //如果检测到接引脚的列线为低电平“0”keyval=16; //可判断是S16键被按下}}TR1=1; //开启定时器T1TH1=(65536-500)/256; //定时器T1的高8位赋初值TL1=(65536-500)%256; //定时器T1的高8位赋初值 }
简易电子琴的设计摘 要 随着基于CPLD的EDA技术的发展和应用领域的扩大与深入,EDA技术在电子信息、通信、自动控制用计算机等领域的重要性日益突出。作为一个学电子信息专业的学生,我们必须不断地了解更多的新产品信息,这就更加要求我们对EDA有个全面的认识。本程序设计的是简易电子琴的设计。采用EDA作为开发工具,VHDL语言为硬件描述语言,MAX + PLUS II作为程序运行平台,所开发的程序通过调试运行、波形仿真验证,初步实现了设计目标。本程序使用的硬件描述语言VHDL,可以大大降低了硬件数字系统设计的入门级别,让人感觉就是C语言的近亲。通过老师的指导和自己的学习完成了预想的功能。关键词 电子琴;课程设计;EDA;VHDL1 引言 课程设计的目的巩固和运用所学课程,理论联系实际,提高分析、解决计算机技术实际问题的独立工作能力,通过对一个简易的八音符电子琴的设计,进一步加深对计算机原理以及数字电路应用技术方面的了解与认识,进一步熟悉数字电路系统设计、制作与调试的方法和步骤。巩固所学课堂知识,理论联系实际,提高分析、解决计算机技术实际问题的独立工作能力。为了进一步了解计算机组成原理与系统结构,深入学习EDA技术,用VHDL语言去控制将会使我们对本专业知识可以更好地掌握。 课程设计的内容(1)设计一个简易的八音符电子琴,它可通过按键输入来控制音响。(2)演奏时可以选择是手动演奏(由键盘输入)还是自动演奏已存入的乐曲。(3)能够自动演奏多首乐曲,且每首乐曲可重复演奏。2 开发工具简介 EDA技术EDA是电子设计自动化(Electronic Design Automation)缩写,是90年代初从CAD(计算机辅助设计)、CAM(计算机辅助制造)、CAT(计算机辅助测试)和CAE(计算机辅助工程)的概念发展而来的。EDA技术是以计算机为工具,根据硬件描述语言HDL( Hardware Description language)完成的设计文件,自动地完成逻辑编译、化简、分割、综合及优化、布局布线、仿真以及对于特定目标芯片的适配编译和编程下载等工作。典型的EDA工具中必须包含两个特殊的软件包,即综合器和适配器。综合器的功能就是将设计者在EDA平台上完成的针对某个系统项目的HDL、原理图或状态图形描述,针对给定的硬件系统组件,进行编译、优化、转换和综合,最终获得我们欲实现功能的描述文件。综合器在工作前,必须给定所要实现的硬件结构参数,它的功能就是将软件描述与给定的硬件结构用一定的方式联系起来。也就是说,综合器是软件描述与硬件实现的一座桥梁。综合过程就是将电路的高级语言描述转换低级的、可与目标器件FPGA/CPLD相映射的网表文件。适配器的功能是将由综合器产生的王表文件配置与指定的目标器件中,产生最终的下载文件,如JED文件。适配所选定的目标器件(FPGA/CPLD芯片)必须属于在综合器中已指定的目标器件系列。硬件描述语言HDL是相对于一般的计算机软件语言,如:C、PASCAL而言的。HDL语言使用与设计硬件电子系统的计算机语言,它能描述电子系统的逻辑功能、电路结构和连接方式。设计者可利用HDL程序来描述所希望的电路系统,规定器件结构特征和电路的行为方式;然后利用综合器和适配器将此程序编程能控制FPGA和CPLD内部结构,并实现相应逻辑功能的的门级或更底层的结构网表文件或下载文件。目前,就FPGA/CPLD开发来说,比较常用和流行的HDL主要有ABEL-HDL、AHDL和VHDL。硬件描述语言—VHDLVHDL的英文全名是Very-High-Speed Integrated Circuit Hardware Description Language,诞生于1982年。1987年底,VHDL被IEEE和美国国防部确认为标准硬件描述语言 。自IEEE公布了VHDL的标准版本,IEEE-1076(简称87版)之后,各EDA公司相继推出了自己的VHDL设计环境,或宣布自己的设计工具可以和VHDL接口。此后VHDL在电子设计领域得到了广泛的接受,并逐步取代了原有的非标准的硬件描述语言。1993年,IEEE对VHDL进行了修订,从更高的抽象层次和系统描述能力上扩展VHDL的内容,公布了新版本的VHDL,即IEEE标准的1076-1993版本,(简称93版)。现在,VHDL和Verilog作为IEEE的工业标准硬件描述语言,又得到众多EDA公司的支持,在电子工程领域,已成为事实上的通用硬件描述语言。有专家认为,在新的世纪中,VHDL于Verilog语言将承担起大部分的数字系统设计任务。VHDL主要用于描述数字系统的结构,行为,功能和接口。除了含有许多具有硬件特征的语句外,VHDL的语言形式和描述风格与句法是十分类似于一般的计算机高级语言。VHDL的程序结构特点是将一项工程设计,或称设计实体(可以是一个元件,一个电路模块或一个系统)分成外部(或称可是部分,及端口)和内部(或称不可视部分),既涉及实体的内部功能和算法完成部分。在对一个设计实体定义了外部界面后,一旦其内部开发完成后,其他的设计就可以直接调用这个实体。这种将设计实体分成内外部分的概念是VHDL系统设计的基本点。应用VHDL进行工程设计的优点是多方面的。(1) 与其他的硬件描述语言相比,VHDL具有更强的行为描述能力,从而决定了他成为系统设计领域最佳的硬件描述语言。强大的行为描述能力是避开具体的器件结构,从逻辑行为上描述和设计大规模电子系统的重要保证。(2) VHDL丰富的仿真语句和库函数,使得在任何大系统的设计早期就能查验设计系统的功能可行性,随时可对设计进行仿真模拟。(3) VHDL语句的行为描述能力和程序结构决定了他具有支持大规模设计的分解和已有设计的再利用功能。符合市场需求的大规模系统高效,高速的完成必须有多人甚至多个代发组共同并行工作才能实现。(4)对于用VHDL完成的一个确定的设计,可以利用EDA工具进行逻辑综合和优化,并自动的把VHDL描述设计转变成门级网表。(4) VHDL对设计的描述具有相对独立性,设计者可以不懂硬件的结构,也不必管理最终设计实现的目标器件是什么,而进行独立的设计。 VHDL的设计流程:(1) 设计输入根据电路设计所提出的要求,将程序输入到VHDL编辑器中去编辑。(2) 功能级模拟用VHDL,模拟器对编辑后的程序进行模拟,如果达不到设计要求,则可以重新修改程序,直到通过功能模拟。(3) 逻辑综合与优化 将通过功能模拟的程序放到VHDL编译器中,进行逻辑综合与优化。(4) 门级模拟对电路用VHDL。仿真器仿真。可对门级电路的延时、定时状态、驱动能力等进行仿真。如不符合要求,可重复步骤(3),再门级模拟,直到符合要求止。(5) 版图生成 用相应的软件处理后,就可以拿去制版。设计过程设计规划根据系统设计要求,系统设计采用自顶向下的设计方法,系统的整体组装设计原理图如图3-1所示,它由乐曲自动演奏模块、音调发生模块和数控分频模块三部分组成。图3-1 系统的整体组装设计原理图 各模块的原理及其程序(1)乐曲自动演奏模块乐曲自动演奏模块()的作用是产生8位发声控制输入信号/当进行自动演奏时,由存储在此模块中的8位二进制数作为发声控制输入,从而自动演奏乐曲。VHDL源程序()LIBRARY IEEE;USE ;USE ;USE ;ENTITY AUTO ISPORT ( CLK : IN STD_LOGIC;AUTO : IN STD_LOGIC;CLK2 : BUFFER STD_LOGIC;INDEX2 : IN STD_LOGIC_VECTOR(7 DOWNTO 0);INDEX0 : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));END AUTO;ARCHITECTURE BEHAVIORAL OF AUTO ISSIGNAL COUNT0: INTEGER RANGE 0 TO 31;BEGINPULSE0 :PROCESS(CLK,AUTO)VARIABLE COUNT :INTEGER RANGE 0 TO 8;BEGINIF AUTO ='1' THENCOUNT := 0;CLK2<='0';ELSIF(CLK'EVENT AND CLK ='1')THENCOUNT :=COUNT +1;IF COUNT =4 THENCLK2 <='1';ELSIF COUNT =8 THENCLK2<='0'; COUNT:=0;END IF ;END IF ;END PROCESS;MUSIC:PROCESS(CLK2)BEGINIF (CLK2'EVENT AND CLK2='1')THENIF (COUNT0=31)THENCOUNT0<=0;ELSECOUNT0<=COUNT0+1;END IF ;END IF ;END PROCESS;COM1:PROCESS(COUNT0,AUTO,INDEX2)BEGINIF AUTO ='0' THENCASE COUNT0 ISWHEN 0=>INDEX0<="00000100"; --3WHEN 1=>INDEX0<="00000100"; --3WHEN 2=>INDEX0<="00000100"; --3WHEN 3=>INDEX0<="00000100"; --3WHEN 4=>INDEX0<="00010000"; --5WHEN 5=>INDEX0<="00010000"; --5WHEN 6=>INDEX0<="00010000"; --5WHEN 7=>INDEX0<="00100000"; --6WHEN 8=>INDEX0<="10000000"; --8WHEN 9=>INDEX0<="10000000"; --8WHEN 10=>INDEX0<="10000000"; --8WHEN 11=>INDEX0<="00000100"; --3WHEN 12=>INDEX0<="00000010"; --2WHEN 13=>INDEX0<="00000010"; --2WHEN 14=>INDEX0<="00000001"; --1WHEN 15=>INDEX0<="00000001"; --1WHEN 16=>INDEX0<="00010000"; --5WHEN 17=>INDEX0<="00010000"; --5WHEN 18=>INDEX0<="00001000"; --4WHEN 19=>INDEX0<="00001000"; --4WHEN 20=>INDEX0<="00001000"; --4WHEN 21=>INDEX0<="00000100"; --3WHEN 22=>INDEX0<="00000010"; --2WHEN 23=>INDEX0<="00000010"; --2WHEN 24=>INDEX0<="00010000"; --5WHEN 25=>INDEX0<="00010000"; --5WHEN 26=>INDEX0<="00001000"; --4WHEN 27=>INDEX0<="00001000"; --4WHEN 28=>INDEX0<="00000100"; --3WHEN 29=>INDEX0<="00000100"; --3WHEN 30=>INDEX0<="00000010"; --2WHEN 31=>INDEX0<="00000010"; --2WHEN OTHERS =>NULL;END CASE;ELSE INDEX0<=INDEX2;END IF;END PROCESS;END BEHAVIORAL;(2) 音调发生模块音调发生模块的作用是产生音阶的分频预置值。当8位发声控制输入信号中的某一位为高电平时,则对应某一音节的数值将输出,该数值即为该音阶的分频预置值,分频预置值控制数控分频模块进行分频,由此可得到每个音阶对应的频率。VHDL源程序()LIBRARY IEEE;USE ;USE ;USE ;ENTITY TONE ISPORT (INDEX: IN STD_LOGIC_VECTOR(7 DOWNTO 0);CODE: OUT STD_LOGIC_VECTOR(6 DOWNTO 0);HIGH: OUT STD_LOGIC;TONE0: OUT INTEGER RANGE 0 TO 2047);END TONE;ARCHITECTURE ART OF TONE ISBEGINSEARCH : PROCESS(INDEX)BEGINCASE INDEX ISWHEN "00000001"=>TONE0 <=773;CODE<="1001111";HIGH<='1';WHEN "00000010"=>TONE0 <=912;CODE<="0010010";HIGH<='1';WHEN "00000100"=>TONE0 <=1036;CODE<="0000110";HIGH<='1';WHEN "00001000"=>TONE0 <=1116;CODE<="1001100";HIGH<='1';WHEN "00010000"=>TONE0 <=1197;CODE<="0100100";HIGH<='1';WHEN "00100000"=>TONE0 <=1290;CODE<="0100000";HIGH<='0';WHEN "01000000"=>TONE0 <=1372;CODE<="0001111";HIGH<='0';WHEN "10000000"=>TONE0 <=1410;CODE<="0000000";HIGH<='0';WHEN OTHERS =>TONE0<=2047;CODE<="0000001";HIGH<='0';END CASE;END PROCESS;END ART;(3) 数控分频模块数控分频模块是对时基脉冲进行分频,得到与1、2、3、4、5、6、7七个音符相对应的频率。VHDL源程序()LIBRARY IEEE;USE ;USE ;USE ;ENTITY FENPIN ISPORT(CLK1: IN STD_LOGIC;TONE1: IN INTEGER RANGE 0 TO 2047;SPKS: OUT STD_LOGIC);END ENTITY FENPIN;ARCHITECTURE ART OF FENPIN ISSIGNAL PRECLK:STD_LOGIC;SIGNAL FULLSPKS:STD_LOGIC;BEGINPROCESS(CLK1)VARIABLE COUNT:INTEGER RANGE 0 TO 8;BEGINIF (CLK1'EVENT AND CLK1='1')THENCOUNT:=COUNT +1;IF COUNT=2 THENPRECLK<='1';ELSIF COUNT =4 THENPRECLK<='0';COUNT:=0;END IF ;END IF ;END PROCESS;PROCESS(PRECLK,TONE1)VARIABLE COUNT11:INTEGER RANGE 0 TO 2047;BEGINIF (PRECLK'EVENT AND PRECLK='1')THENIF COUNT11
98 浏览 4 回答
173 浏览 3 回答
183 浏览 7 回答
333 浏览 4 回答
179 浏览 4 回答
92 浏览 6 回答
100 浏览 4 回答
129 浏览 3 回答
288 浏览 9 回答
146 浏览 2 回答
333 浏览 5 回答
236 浏览 4 回答
115 浏览 2 回答
158 浏览 6 回答
119 浏览 3 回答