子项目四:电子琴
目标:
通过完成音频的输出和电子琴的综合设计, 使学生进一步掌握keilC编译器的使用和proteus仿真软件进行仿真的基本过程。进一步了解单片机C51程序设计基础,了解单片机内部结构、存储器地址分配、并行I/O口的结构与工作原理、循环程序的设计。
任务:
由易到难设计滴、滴报警声的输出,叮咚门铃和电子琴掌握音符的输出控制。 一、原理 1、滴、滴报警声
用 AT89S51 单片机产生“嘀、嘀、…”报警声从 P1.0 端口输出,产生频率为 1KHz, 根据上面图可知:1KHZ方波从 P1.0 输出 0.2 秒,接着 0.2 秒从 P1.0输出电平信号,如此循环下去,就形成我们所需的报警声了。
2、叮咚门铃
当按下开关 SP1,AT89S51 单片机产生“叮咚”声从 P1.0 端口输出,经过放大之后送入喇叭。
3、电子琴
由 4X4 组成 16 个按钮矩阵,设计成 16 个音,可随意弹奏想要表达的音乐。
二、原理图绘制 1、滴、滴报警声
西安思源学院 精品课程 单片机原理与应用
2、叮咚门铃
3、电子琴
西安思源学院 精品课程 单片机原理与应用
三、程序设计
(1)滴、滴报警声
1、生活中我们常常到各种各样的报警声,例如“嘀、嘀、…”就是常见的一种声音报警声,但对于这种报警声,嘀 0.2 秒钟,然后断 0.2 秒钟,如此循环下去,假设嘀声的频率为 1KHz,则报警声时序图如下图所示:
上述波形信号如何用单片机来产生呢?
由于要产生上面的信号,我们把上面的信号分成两部分,一部分为 1KHZ 方波,占用时间为 0.2 秒;另一部分为电平,也是占用0.2秒;因此,我们利用单片机的定时/计数器 T0 作为定时,可以定时 0.2 秒;同时,也要用单片机产生 1KHZ的方波,对于 1KHZ 的方波信号周期为 1ms,高电平占用 0.5ms,低电平占用 0.5ms,因此也采用定时器 T0 来完成 0.5ms 的定时;最后,可以选定定时/计数器 T0 的定时时间为 0.5ms, 而要定时 0.2 秒则是 0.5ms 的 400 倍, 也就是说以 0.5ms 定时 400次就达到 0.2秒的定时时间了。 2、程序框图 主程序框图
中断服务程序框图
西安思源学院 精品课程 单片机原理与应用
3、汇编源程序
T02SA EQU 30H T02SB EQU 31H FLAG BIT 00H ORG 00H LJMP START ORG 0BH LJMP INT_T0
START: MOV T02SA,#00H MOV T02SB,#00H CLR FLAG
MOV TMOD,#01H
MOV TH0,#(65536-500) / 256 MOV TL0,#(65536-500) MOD 256 SETB TR0 SETB ET0 SETB EA SJMP ¥ INT_T0:
MOV TH0,#(65536-500) / 256 MOV TL0,#(65536-500) MOD 256 INC T02SA MOV A,T02SA
CJNE A,#100,NEXT INC T02SB MOV A,T02SB
CJNE A,#04H,NEXT MOV T02SA,#00H MOV T02SB,#00H CPL FLAG
NEXT: JB FLAG,DONE CPL P1.0 DONE: RETI END
4、 C 语言源程序
#include <AT89X51.H> unsigned int t02s; unsigned char t05ms; bit flag;
void main(void) {
TMOD=0x01;
TH0=(65536-500)/256; TL0=(65536-500)%256;
西安思源学院 精品课程 单片机原理与应用
TR0=1; ET0=1; EA=1; while(1); }
void t0(void) interrupt 1 using 0 {
TH0=(65536-500)/256; TL0=(65536-500)%256; t02s++;
if(t02s==400) {
t02s=0; flag= ̄flag; }
if(flag==0) {
P1_0= ̄P1_0; } }
(2)叮咚门铃
1、我们用单片机实定时/计数器 T0 来产生 700HZ和 500HZ的频率, 根据定时/计数器T0,我们取定时 250us,因此,700HZ的频率要经过3 次 250us 的定时,而 500HZ的频率要经过 4 次 250us 的定时。在设计过程,只有当按下 SP1 之后,才启动 T0 开始工作,当 T0 工作完毕,回到最初状态。“叮”和“咚”声音各占用 0.5 秒,因此定时/计数器 T0 要完成 0.5 秒的定时,对于以 250us 为基准定时2000 次才可以。 2、程序框图 主程序框图
西安思源学院 精品课程 单片机原理与应用
T0中断服务程序框图
3、汇编源程序 T5HZ EQU 30H T7HZ EQU 31H T05SA EQU 32H T05SB EQU 33H FLAG BIT 00H STOP BIT 01H SP1 BIT P3.7 ORG 00H LJMP START ORG 0BH LJMP INT_T0
START: MOV TMOD,#02H MOV TH0,#06H MOV TL0,#06H SETB ET0 SETB EA
NSP: JB SP1,NSP LCALL DELY10MS JB SP1,NSP
西安思源学院 精品课程 单片机原理与应用
SETB TR0
MOV T5HZ,#00H MOV T7HZ,#00H MOV T05SA,#00H MOV T05SB,#00H CLR FLAG CLR STOP JNB STOP,¥ LJMP NSP
DELY10MS: MOV R6,#20 D1: MOV R7,#248 DJNZ R7,¥ DJNZ R6,D1 RET
INT_T0: INC T05SA MOV A,T05SA
CJNE A,#100,NEXT MOV T05SA,#00H INC T05SB MOV A,T05SB CJNE A,#20,NEXT MOV T05SB,#00H JB FLAG,STP CPL FLAG LJMP NEXT
STP: SETB STOP CLR TR0 LJMP DONE
NEXT: JB FLAG,S5HZ INC T7HZ MOV A,T7HZ
CJNE A,#03H,DONE MOV T7HZ,#00H CPL P1.0 LJMP DONE
S5HZ: INC T5HZ MOV A,T5HZ
CJNE A,#04H,DONE MOV T5HZ,#00H CPL P1.0 LJMP DONE DONE: RETI END
4、 C 语言源程序
西安思源学院 精品课程 单片机原理与应用
#include void main(void) { unsigned char i,j; TMOD=0x02; TH0=0x06; TL0=0x06; ET0=1; EA=1; while(1) { if(P3_7==0) { for(i=10;i>0;i--) for(j=248;j>0;j--); if(P3_7==0) { t5hz=0; t7hz=0; tcnt=0; flag=0; stop=0; TR0=1; while(stop==0); } } } } void t0(void) interrupt 1 using 0 { tcnt++; if(tcnt==2000) { tcnt=0; if(flag==0) { flag=~flag; } else 西安思源学院 精品课程 单片机原理与应用 { stop=1; TR0=0; } } if(flag==0) { t7hz++; if(t7hz==3) { t7hz=0; P1_0=~P1_0; } } else { t5hz++; if(t5hz==4) { t5hz=0; P1_0=~P1_0; } } } (1)电子琴 1、4×4 矩阵键盘识别处理 每个按键有它的行值和列值 ,行值和列值的组合就是识别这个按键的编码。矩阵的行线和列线分别通过两并行接口和 CPU 通信。每个按键的状态同样需变成数字量“0”和“1” ,开关的一端(列线)通过电阻接 VCC,而接地是通过程序输出数字“0”实现的。键盘处理程序的任务是:确定有无键按下,判断哪一个键按下,键的功能是什么;还要消除按键在闭合或断开时的抖动。两个并行口中,一个输出扫描码,使按键逐行动态接地,另一个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该键的功能。 2、音乐产生的方法; 一首音乐是许多不同的音阶组成的,而每个音阶对应着不同的频率,这样我们就可以利用不同的频率的组合,即可构成我们所想要的音乐了,当然对于单片机来产生不同的频率非常方便,我们可以利用单片机的定时/计数器 T0来产生这样方波频率信号,因此,我们只要把一首歌曲的音阶对应频率关系弄正确即可。现在以单片机 12MHZ 晶振为例,列出高中低音符与单片机计数 T0 相关的计数值如下表所示 音 符 低1 DO #1 DO# 频 率(Hz) 262 277 音 符 #4 FA# 中5 SO 频 率(Hz) 740 784 西安思源学院 精品课程 单片机原理与应用 低2 RE #2 RE# 低3 MI 低4 FA #4 FA# 低5 SO #5 SO# 低6 LA #6 低7 SI 中1 DO #1 DO# 中2 RE #2 RE# 中3 MI 中4 FA 294 311 330 349 370 392 415 440 466 494 523 554 587 622 659 698 #5 SO# 中6 LA #6 中7 SI 高1 DO #1 DO# 高2 RE #2 RE# 高3 MI 高4 FA #4 FA# 高5 SO #5 SO# 高6 LA #6 高7 SI 831 880 932 988 1046 1109 1175 1245 1318 1397 1480 1568 1661 1760 1865 1967 2、程序框图 主程序框图 西安思源学院 精品课程 单片机原理与应用 按键程序设计框图 中断服务程序框图 3、汇编源程序 KEYBUF EQU 30H 西安思源学院 精品课程 单片机原理与应用 STH0 EQU 31H STL0 EQU 32H TEMP EQU 33H ORG 00H LJMP START ORG 0BH LJMP INT_T0 START: MOV TMOD,#01H SETB ET0 SETB EA WAIT: MOV P3,#0FFH CLR P3.4 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY1 LCALL DELY10MS MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY1 MOV A,P3 ANL A,#0FH CJNE A,#0EH,NK1 MOV KEYBUF,#0 LJMP DK1 NK1: CJNE A,#0DH,NK2 MOV KEYBUF,#1 LJMP DK1 NK2: CJNE A,#0BH,NK3 MOV KEYBUF,#2 LJMP DK1 NK3: CJNE A,#07H,NK4 MOV KEYBUF,#3 LJMP DK1 NK4: NOP DK1: MOV A,KEYBUF MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,KEYBUF MOV B,#2 西安思源学院 精品课程 单片机原理与应用 MUL AB MOV TEMP,A MOV DPTR,#TABLE1 MOVC A,@A+DPTR MOV STH0,A MOV TH0,A INC TEMP MOV A,TEMP MOVC A,@A+DPTR MOV STL0,A MOV TL0,A SETB TR0 DK1A: MOV A,P3 ANL A,#0FH XRL A,#0FH JNZ DK1A CLR TR0 NOKEY1: MOV P3,#0FFH CLR P3.5 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY2 LCALL DELY10MS MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY2 MOV A,P3 ANL A,#0FH CJNE A,#0EH,NK5 MOV KEYBUF,#4 LJMP DK2 NK5: CJNE A,#0DH,NK6 MOV KEYBUF,#5 LJMP DK2 NK6: CJNE A,#0BH,NK7 MOV KEYBUF,#6 LJMP DK2 NK7: CJNE A,#07H,NK8 MOV KEYBUF,#7 LJMP DK2 NK8: NOP 西安思源学院 精品课程 单片机原理与应用 DK2: MOV A,KEYBUF MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,KEYBUF MOV B,#2 MUL AB MOV TEMP,A MOV DPTR,#TABLE1 MOVC A,@A+DPTR MOV STH0,A MOV TH0,A INC TEMP MOV A,TEMP MOVC A,@A+DPTR MOV STL0,A MOV TL0,A SETB TR0 DK2A: MOV A,P3 ANL A,#0FH XRL A,#0FH JNZ DK2A CLR TR0 NOKEY2: MOV P3,#0FFH CLR P3.6 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY3 LCALL DELY10MS MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY3 MOV A,P3 ANL A,#0FH CJNE A,#0EH,NK9 MOV KEYBUF,#8 LJMP DK3 NK9: CJNE A,#0DH,NK10 MOV KEYBUF,#9 LJMP DK3 西安思源学院 精品课程 单片机原理与应用 NK10: CJNE A,#0BH,NK11 MOV KEYBUF,#10 LJMP DK3 NK11: CJNE A,#07H,NK12 MOV KEYBUF,#11 LJMP DK3 NK12: NOP DK3: MOV A,KEYBUF MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,KEYBUF MOV B,#2 MUL AB MOV TEMP,A MOV DPTR,#TABLE1 MOVC A,@A+DPTR MOV STH0,A MOV TH0,A INC TEMP MOV A,TEMP MOVC A,@A+DPTR MOV STL0,A MOV TL0,A SETBTR0 DK3A: MOV A,P3 ANL A,#0FH XRL A,#0FH JNZ DK3A CLR TR0 NOKEY3: MOV P3,#0FFH CLR P3.7 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY4 LCALL DELY10MS MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY4 MOV A,P3 西安思源学院 精品课程 单片机原理与应用 ANL A,#0FH CJNE A,#0EH,NK13 MOV KEYBUF,#12 LJMP DK4 NK13: CJNE A,#0DH,NK14 MOV KEYBUF,#13 LJMP DK4 NK14: CJNE A,#0BH,NK15 MOV KEYBUF,#14 LJMP DK4 NK15: CJNE A,#07H,NK16 MOV KEYBUF,#15 LJMP DK4 NK16: NOP DK4: MOV A,KEYBUF MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,KEYBUF MOV B,#2 MUL AB MOV TEMP,A MOV DPTR,#TABLE1 MOVC A,@A+DPTR MOV STH0,A MOV TH0,A INC TEMP MOV A,TEMP MOVC A,@A+DPTR MOV STL0,A MOV TL0,A SETB TR0 DK4A: MOV A,P3 ANL A,#0FH XRL A,#0FH JNZ DK4A CLR TR0 NOKEY4: LJMP WAIT DELY10MS: MOV R6,#10 D1: MOV R7,#248 DJNZ R7,¥ 西安思源学院 精品课程 单片机原理与应用 DJNZ R6,D1 RET INT_T0: MOV TH0,STH0 MOV TL0,STL0 CPL P1.0 RETI TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H TABLE1: DW 64021,64103,64260,64400 DW 64524,64580,64684,64777 DW 64820,64898,64968,65030 DW 65058,65110,65157,65178 END 4、 C 语言源程序 #include unsigned char code table[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; unsigned char temp; unsigned char key; unsigned char i,j; unsigned char STH0; unsigned char STL0; unsigned int code tab[]={64021,64103,64260,64400, 64524,64580,64684,64777, 64820,64898,64968,65030, 65058,65110,65157,65178}; void main(void) { TMOD=0x01; ET0=1; EA=1; while(1) { P3=0xff; P3_4=0; temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--); 西安思源学院 精品课程 单片机原理与应用 temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { temp=P3; temp=temp & 0x0f; switch(temp) { case 0x0e: key=0; break; case 0x0d: key=1; break; case 0x0b: key=2; break; case 0x07: key=3; break; } temp=P3; P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%256; TR0=1; temp=temp & 0x0f; while(temp!=0x0f) { temp=P3; temp=temp & 0x0f; } TR0=0; } } P3=0xff; P3_5=0; temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--); 西安思源学院 精品课程 单片机原理与应用 temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { temp=P3; temp=temp & 0x0f; switch(temp) { case 0x0e: key=4; break; case 0x0d: key=5; break; case 0x0b: key=6; break; case 0x07: key=7; break; } temp=P3; P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%256; TR0=1; temp=temp & 0x0f; while(temp!=0x0f) { temp=P3; temp=temp & 0x0f; } TR0=0; } } P3=0xff; P3_6=0; temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--); 西安思源学院 精品课程 单片机原理与应用 temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { temp=P3; temp=temp & 0x0f; switch(temp) { case 0x0e: key=8; break; case 0x0d: key=9; break; case 0x0b: key=10; break; case 0x07: key=11; break; } temp=P3; P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%256; TR0=1; temp=temp & 0x0f; while(temp!=0x0f) { temp=P3; temp=temp & 0x0f; } TR0=0; } } P3=0xff; P3_7=0; temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--); 西安思源学院 精品课程 单片机原理与应用 temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { temp=P3; temp=temp & 0x0f; switch(temp) { case 0x0e: key=12; break; case 0x0d: key=13; break; case 0x0b: key=14; break; case 0x07: key=15; break; } temp=P3; P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%256; TR0=1; temp=temp & 0x0f; while(temp!=0x0f) { temp=P3; temp=temp & 0x0f; } TR0=0; } } } } void t0(void) interrupt 1 using 0 { TH0=STH0; TL0=STL0; P1_0=~P1_0; } 西安思源学院 精品课程 单片机原理与应用 四、仿真 利用KeilC进行编译程序,生成hex文件 添加仿真文件 单击 开始仿真。 因篇幅问题不能全部显示,请点此查看更多更全内容