Proteus设计简易电子琴
1、proteus版本及使用芯片
proteus版本:8.0
使用芯片:8086、并行接口芯片8255A、可编程定时/计数器8253、锁存器74HC373、译码器74HC138
2、题目分析
1、设计一个简易的电子琴有21个音阶,故采用3*7个按钮来模拟。
2、通过PB输出的数据以及从PC口读入的数据来判断按下的是哪个键,然后通过C语言编程将对应的音频输入到8253A中,使得CLK0开始工作,发声然后通过控制GATE0信号来使计数停止。
3、8255A芯片用法
参考8255A芯片详解
1、使用一片8255A芯片读取按钮的按下情况
2、这里仅仅使用0方式,PA、PB口输出,PC口输入,控方式命令字为89H
3、8253A芯片用法
参考8253A芯片详解
1、这里使用可编程定时/计数芯片8253A来达到控制蜂鸣器发声的效果
4、74HC138芯片进行片选
1、通过74HC138来进行8255A、8253A芯片的选中
2、8255A芯片 /CS引脚与74HC138的Y0引脚相连,故8255A芯片的PA、PB、PC以及命令口地址分别为8000H、8002H、8004H、8006H。
3、8253A芯片 /CS引脚与 74HC138的 Y2引脚相连,故8253A芯片的三个计数器地址以及命令口地址分别为0A000H、0A002H、0A004H、0A006H。
5、原理图
4、c源代码
/* Main.c file generated by New Project wizard
*
* Created: 2019 12 16
* Processor: 8086
* Compiler: Digital Mars C
*
* Before starting simulation set Internal Memory Size
* in the 8086 model properties to 0x10000
*/
#define TCONTRO 0A006H//00000110B
#define TCON0 0A000H
#define TCON1 0A002H
#define TCON2 0A004H
#define IOCON 8006H //控制口
#define IOA 8000H //A数据口
#define IOB 8002H //B数据口
#define IOC 8004H //C数据口
//以下是C调低音的音频宏定义
#define l_dao 382 //将“l_dao”宏定义为低音“1”的频率262Hz
#define l_re 350 //将“l_re”宏定义为低音“2”的频率286Hz
#define l_mi 322 //将“l_mi”宏定义为低音“3”的频率311Hz
#define l_fa 287 //将“l_fa”宏定义为低音“4”的频率349Hz
#define l_sao 254 //将“l_sao”宏定义为低音“5”的频率392Hz
#define l_la 227 //将“l_a”宏定义为低音“6”的频率440Hz
#define l_xi 202 //将“l_xi”宏定义为低音“7”的频率494Hz
//以下是C调中音的音频宏定义
#define dao 191 //将“dao”宏定义为中音“1”的频率523Hz
#define re 170 //将“re”宏定义为中音“2”的频率587Hz
#define mi 152 //将“mi”宏定义为中音“3”的频率659Hz
#define fa 143 //将“fa”宏定义为中音“4”的频率698Hz
#define sao 128 //将“sao”宏定义为中音“5”的频率784Hz
#define la 114 //将“la”宏定义为中音“6”的频率880Hz
#define xi 101 //将“xi”宏定义为中音“7”的频率523H
//以下是C调高音的音频宏定义
#define h_dao 96 //将“h_dao”宏定义为高音“1”的频率1046Hz
#define h_re 85 //将“h_re”宏定义为高音“2”的频率1174Hz
#define h_mi 76 //将“h_mi”宏定义为高音“3”的频率1318Hz
#define h_fa 72 //将“h_fa”宏定义为高音“4”的频率1396Hz
#define h_sao 64 //将“h_sao”宏定义为高音“5”的频率1567Hz
#define h_la 57 //将“h_la”宏定义为高音“6”的频率1760Hz
#define h_xi 51 //将“h_xi”宏定义为高音“7”的频率1975Hz
void outp(unsigned int addr, char data)
// Write a byte to the specified I/O port
{ __asm
{ mov dx, addr
mov al, data
out dx, al
}
}
char inp(unsigned int addr)
// Read a byte from the specified I/O port
{ char result;
__asm
{ mov dx, addr
in al, dx
mov result, al
}
return result;
}
void delay()
{
unsigned char i,j;
for(i=0;i<100;i++)
for(j=0;j<50;j++)
;
}
void main(void)
{
unsigned char i,j,a,b;
unsigned int ch, cl; //储存定时器的定时常数
unsigned char k;
unsigned int cf[]={l_dao, l_re,l_mi,l_fa,l_sao,l_la,l_xi ,//21个音,先用四个
dao,re, mi,fa,sao,la,xi,
h_dao,h_re,h_mi,h_fa,h_sao,h_la,h_xi};
outp(IOCON,0x89);// 0x88=10001000B A组0方式 PA输出 PC4-7输入 B组0方式 PB输出 PC0-3输出
outp(TCONTRO,0x36); //计数器0,只写计算值低8位,方式3,二进制计数 00110110B
while(1)
{
//001 010 100
j=0x0e;
for(k=0;k<3;k++)
{
j-=k; // k=1 j=00001101 00001100 00000011
outp(IOB,j); //PB口输入
b=inp(IOC); //PC口读取
b|=0x80; //由于PC口只连7个引脚,故置PC7=1
outp(IOA,0x01);//控制GATE0,使蜂鸣器每次发完声后停止
switch(b)
{
case 0xfe://11111110
ch=cf[3*k]/256;cl=cf[3*k]%256;
outp(TCON0,cl); //计数器0
outp(TCON0,ch);
delay();
break;
case 0xfd: //11111101
ch=cf[3*k+1]/256;cl=cf[3*k+1]%256;
outp(TCON0,cl); //计数器0
outp(TCON0,ch);
delay();
break;
case 0xfb://11111011
ch=cf[3*k+2]/256;cl=cf[3*k+2]%256;
outp(TCON0,cl); //计数器0
outp(TCON0,ch);
delay();
break;
case 0xf7://11110111
ch=cf[3*k+3]/256;cl=cf[3*k+3]%256;
outp(TCON0,cl); //计数器0
outp(TCON0,ch);
delay();
break;
case 0xef://11101111
ch=cf[3*k+4]/256;cl=cf[3*k+4]%256;
outp(TCON0,cl); //计数器0
outp(TCON0,ch);
delay();
break;
case 0xdf://11011111
ch=cf[3*k+5]/256;cl=cf[3*k+5]%256;
outp(TCON0,cl); //计数器0
outp(TCON0,ch);
delay();
break;
case 0xbf://10111111
ch=cf[3*k+6]/256;cl=cf[3*k+6]%256;
outp(TCON0,cl); //计数器0
outp(TCON0,ch); [添加链接描述](%E9%93%BE%E6%8E%A5%EF%BC%9Ahttps://pan.baidu.com/s/1bVbFmyxzULV-_mTqivKIFA%20%20%E6%8F%90%E5%8F%96%E7%A0%81%EF%BC%9Ae703%20%20%E5%A4%8D%E5%88%B6%E8%BF%99%E6%AE%B5%E5%86%85%E5%AE%B9%E5%90%8E%E6%89%93%E5%BC%80%E7%99%BE%E5%BA%A6%E7%BD%91%E7%9B%98%E6%89%8B%E6%9C%BAApp%EF%BC%8C%E6%93%8D%E4%BD%9C%E6%9B%B4%E6%96%B9%E4%BE%BF%E5%93%A6)
delay();
break;
}
outp(IOA,0x00);
}
}
}