《单片机原理及应用》课程设计 一、 电子琴电路功能介绍及组成框图1、设计要求 由16个按键组成4×4键盘矩阵,设置成16个音,可随意弹奏想要表现的音乐。按下键的同时,显示键号;另外在没有键按下时能播放一首熟悉的音乐。
二、硬件电路设计1、总电路 2、各部分工作原理(1) 音频电路原理音频电路原理为整个电子琴设计的核心原理,电路设计方法和编程方法都围绕着电子琴的音频产生、变化的原理来进行。 音频电路中包含一个发音装置。利用电子琴的音频脉冲和节拍的产生原理,通过P3.3口来控制发音装置,产生音符和音乐信号。 (1.1)音频脉冲音乐的产生主要是通过单片机的I/O口输出高低不同的脉冲信号来控制蜂鸣器发音,要想产生音频脉冲信号,需要算出某一音频的周期(1/频率),然后将此周期除以2,即为半周期的时间。利用单片机定时器计时这个半个周期时间,每当计时到后就将输出脉冲的I/O口反相,然后重复计时此半周期时间再对I/O口反相,这样就能在此I/O口上得到此频率的脉冲。通常,利用单片机的内部定时器0,工作在方式1下,改变计数初始值THO和TLO来实现。 例如,若单片机采用12MHz晶振,要产生频率为587Hz的音频脉冲时,其音频信号的脉冲周期 T=1/587=1703.5775μs,半周期的时间为852μs,因此只要令计数器计数=852μs/1μs=852,在每计数852时将I/O口反相,就可得到C调中音Re。 计数脉冲值与频率的关系如下: (1.2) 节拍每个音符使用一个字节,字节的高四位代表音符的高低,低四位代表音符的节拍,表5-2为节拍与节拍码的对照表。如果1拍为0.4s,1/4拍是0.1s只要设定延迟时间就可求得节拍的时间。假设1/4拍为1个延迟单位时间,那么1拍对应的就是4个延迟单位时间,以此类推。所以只要求得1/4拍的延迟单位时间,其余的节拍就是它的倍数,表5-3为1/4拍和1/8拍的时间设定。
不管采用哪种方法,当歌曲结束时,在发音计数值表(TABLE)中均需加上音乐结束符00H。 (2)音符显示采用的共阴极7段数码管作为音符显示器。当AT89C51执行完按键扫描程序后,所得到的键号送至P0口,通过P0口进而控制数码管的音符字模的显示。另外,P0口作为通用I/O口时,需要外界上拉电阻。 (3)矩阵式音符键盘 采用矩阵式键盘,节省I/O口资源。矩阵式键盘的行线与列线的交叉处不相通,设置为按键,n条行线与m条列线,可构成n*m个按键的键盘。 (4)弹奏按键 音符按键采用外部中断1的方式来实现。当按键按下时,调用中断函数切断音乐播放模式,进入音符按键弹奏模式。 三、软件设计1、程序组成 (1.1)歌曲播放程序 首先,建立音乐代码库:找出乐曲最低音和最高音范围,然后确定音符表T的顺序,把T值建立在数组 T[ ] 中,构成发音符的计数值放在数组tab[ ]中,以音符节拍码00H为音乐结束标记。通过调用音乐代码库来实现演奏歌曲。
[音乐代码库]
[音乐播放程序] (1.2)键盘音符获取程序 键盘是人与单片机通信的重要接口。合适的键盘扫描程序能使单片机准确的运行。另外,按键按下时,由于弹簧抖动的原因,会对按键有无按下的判断产生干扰,故需要采用适当的消抖方法。本案例采用软件延时的方法去抖动。
[延时去抖动]
[按键扫描] (1.3)音符显示程序 采用的共阴极7段数码管作为音符显示器,当执行完按键扫描程序后,所得到的键号送至P0口,通过P0口进而控制数码管的音符字模的显示。
[音符获取] (1.4)弹奏模式程序 通过弹奏按键的按下来产生外部中断,利用中断来实现由歌曲播放模式转到弹奏模式。
[外部中断0函数]
[音符弹奏] 2、流程图 四、设计总结(包括调试软、硬件过程和体会、收获) 附录: 1. 仿真状态图 2. 程序清单
- #include <reg51.h>
- #include <absacc.h>
- #include <stdio.h>
- #include <math.h>
- #define uchar unsigned char
- #define uint unsigned int
- uchar S=0,T=0;
- uchar SH;
- uchar SL;
- uchar k, key;
- bit flag=1;
- sbit SPK=P3^0;
- uchar code DSY_CODE[]= {0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71};
- uchar code music[]= {8,9,10,8,8,9,10,8,10,11,12,10,11,12,-1};
- uchar code Len[]= {1,1,1,1,1,1,1,1,1,1,2,1,1,2,-1};
- uint code tab[]= { 64580,64684,64777,64820,64898,64968,65030,
- 65058,65110,65157,65178,65217,65252,65283};
- //延时
- void delay1(uint ms)
- { uchar t;
- while(ms--)
- for (t=0;t<120;t++); }
- /* 键消抖延时*/
- void delay(void)
- { uchar i;
- for (i=300;i>0;i--); }
- /* 键扫描函数 */
- uchar getkey()
- {
- uchar scode,tcode;
- if ((P2&0xf0)==0xf0)
- return(0);
- scode = 0xfe;
- while((scode&0x10)!=0)
- { P2 = scode;
- if ((P2&0xf0)!=0xf0)
- {
- tcode = (P2&0xf0)|0x0f; return((~scode)+(~tcode)); }
- else scode = (scode<<=1)|0x01; }
- }
- void EX0_INT() interrupt 0
- { flag=0; }
- void time0_int(void) interrupt 1 using 0
- {
- TH0 = SH;
- TL0 = SL;
- SPK=!SPK;
- P0=DSY_CODE[k] ; }
- void main(void) {
- P0=0x3f;
- IE=0x87;
- TMOD=0x01;
- IT0=1;
- IT1=1;
- while(1)
- {
- P2 = 0xf0;
- if ((P2&0xf0)!=0xf0)
- delay();
- if ((P2&0xf0)!=0xf0)
- { key = getkey();
- switch(key)
- {
- case 0x11:k = 0;break; // 按键1
- case 0x21:k = 1;break; // 按键2
- case 0x41:k = 2;break; // 按键3
- case 0x81:k = 3;break; // 按键4
- case 0x12:k = 4; break; // 按键5
- case 0x22:k = 5;break; // 按键6
- case 0x42:k = 6;break; // 按键7
- case 0x82:k = 7;break; // 按键8
- case 0x14:k = 8;break; // 按键9
- case 0x24:k = 9;break; // 按键10
- case 0x44:k = 10;break; // 按键11
- case 0x84:k = 11;break; // 按键12
- case 0x18:k = 12;break; // 按键13
- case 0x28:k = 13;break; // 按键14
- case 0x48:k = 14;break; // 按键15
- case 0x88:k = 15;break; // 按键16
- default:break;
- }
- if(flag==0) { SH = tab[k]/256;
- SL = tab[k]%256;
- TR0 = 1;
- while ((P2&0xf0)!=0xf0);
- SPK=1;
- TR0 = 0; }
- else
- { while(flag==1)
- {
- if (music[T]==-1)T=0;
- SH=(tab[music[T]])/256;
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
完整课设论文下载(word格式 可编辑):http://www.51hei.com/bbs/dpj-86870-1.html
|