⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 111.cpp

📁 综合微机通用总线、定时计数器、并行接口、中断控制器等芯片等控制原理
💻 CPP
字号:


#include <dos.h>       //getvect(); setvect();
#include <conio.h>     //kbhit();
#include <stdlib.h>    //exit(0);
#include <stdio.h>     //printf();

#ifdef __cplusplus
  #define __CPPARGS 
#else
  #define __CPPARGS
#endif


#define S1   1  //从PA口选择播放的歌曲
#define S2   2
#define S3   4
#define S4   8
#define S5   16
#define S6   32
#define S7   64
#define S8   128


#define CTRL_8255 0x303       //8255控制口地址
#define PORTA     0x300       //8255芯片PA口地址
#define PORTB     0x301       //8255芯片PB口地址
#define CTRL_8253 0x307       //8253控制口地址


short int Music1[ ]={
    //声明音阶的音乐频率
  131,
  147,
  165,
  175,
  196,
  220,
  247,
  262,
  0
};
short int Music1_Delay[ ]={
	 //声明音阶的音乐延时
   8,8,8,8,8,8,8,8
};


short int Music2[ ]= {
    //声明歌曲“两个老虎”的音乐频率 
    262,294,330,262,
    262,294,330,262,
    330,349,392,
    330,349,392,
    392,440,392,349,330,262,
    392,440,392,349,330,262,
    294,196,262,
    294,196,262,
    0
};
short int Music2_Delay[] = {
    //声明歌曲“两个老虎”的音乐延时 
    8,8,8,8,
    8,8,8,8,
    8,8,16,
    8,8,16,
    4,4,4,4,8,8,
    4,4,4,4,8,8,
    8,8,16,
    8,8,16
};

short int Music3[ ]={
     //声明歌曲“小蜜蜂”的音乐频率 
	392,330,330,
	349,294,294,
	262,294,330,349,
	392,392,392,
    392,330,330,
	349,294,294,
	262,330,392,392,
	262,
	0
};
short int Music3_Delay[ ]={
    //声明歌曲“小蜜蜂”的音乐延时 
	4,4,8,
	4,4,8,
	4,4,4,4,
	4,4,8,
	4,4,8,
	4,4,8,
	4,4,4,4,
	16
};

short int Music4[ ]={
    //声明歌曲“小星星”的音乐频率 
	262,262,392,392,
	440,440,392,
	349,349,330,330,
	294,294,262,
	0
};
short int Music4_Delay[ ]={
     //声明歌曲“小星星”的音乐延时 
	8,8,8,8,
	8,8,16,
	8,8,8,8,
	8,8,16
};

short int Music5[ ]={
     //声明歌曲“洋娃娃和小熊跳舞”的音乐频率 
     262,294,330,349,
	 392,392,392,349,330,
	 349,349,349,330,294,
	 262,330,392,
     262,294,330,349,
	 392,392,392,349,330,
	 349,349,349,330,294,
	 262,330,262,
     0
};
short int Music5_Delay[ ]={
     //声明歌曲“洋娃娃和小熊跳舞”的音乐延时
	4,4,4,4,
	4,4,4,2,2,
	4,4,4,2,2,
	8,8,8,
    4,4,4,4,
	4,4,4,2,2,
	4,4,4,2,2,
	8,8,8
};

short int Music6[ ]={
     //声明歌曲“友谊地久天长”的音乐频率
	196,262,262,262,
	330,294,262,294,
	330,262,262,330,392,440,
	440,392,330,330,
	262,294,262,294,
    330,262,220,220,196,262
};
short int Music6_Delay[ ]={
    //声明歌曲“友谊地久天长”的音乐延时
    8,16,4,8,
    8,16,4,8,
    8,16,4,8,8,16,
    8,16,4,8,
    8,16,4,8,
    8,16,4,8,8,16
};

struct Music{
	short int *Freq;
	short int *TimeDelay;
}Music[5];

short int  *ptrFreq;      // 声明音频指针
short int  *ptrTimeDelay; // 声明延时指针

void interrupt (*oldhandler)(__CPPARGS);
void interrupt chengyiping(__CPPARGS)
{
   disable();
   (*ptrTimedelay)--;       // 延时点数减一
   outportb(OCW2FROM,0x62); //发中断结束命令(OCW2),向从片8259发EOI命令即指定从片8259的ISR2复位
   outportb(OCW2MAIN,0x20); //向主片8259发EOI命令,结束当前最高级中断服务
	 enable();
}

int  Playing(void)
{
	oldhandler = getvect(INTR); // 保存原中断向量
	setvect(INTR, handler);     // 装载新中断向量
	
	outportb( CTRL_8255, 0x90 ); // 初始化8255
	outportb( CTRL_8255, 0x0c ); // 置pc6=0 禁止8253通道2的gate引脚
	outportb( CTRL_8255, 0x00 ); // 置pc0=0 禁止7408
	outportb( CTRL_8253, 0xb6 ); // 初始化8253


	int       n = 0;               //保存歌曲编号
	short     out = 0;               
	short int order  = inportb( PORTA ); //接收从PA口得到的命令
    short int norder = order; 
	switch (order)
	{
	    case S1:  n = 0; 
			break;
	    case S2:  n = 1;
			break;
	    case S3:  n = 2; 
			break;
	    case S4:  n = 3;
			break;
	    case S5:  n = 4;
			break;
	    case S6:  n = 5; 
			break;
	}	
	ptrFreq      = Music[n].Freq;      
	ptrTimeDelay = Music[n].TimeDelay;
    int status;
	//开始播放歌曲
    while ( *ptrFreq && !kbhit())
	{
	void interrupt (*oldhandler)(__CPPARGS);
	oldhandler=getvect(0x72);               //获取原中断向量
	setvect(0x72,handler);                  //设置新中断向量
    enable();
	status=inportb(0xa1);
	outportb(0xa1,status&0xfb);             //打开IRQ10(OCW1)
	status=inportb(0x21);
	outportb(0x21,status&0xfb);             //打开IRQ2(OCW1)
		outportb( 0x306, (unsigned char)(CLK / *ptrFreq % 256) );
		// 先送低字节
		outportb( 0x306, (unsigned char)(CLK / *ptrFreq / 256) );
		// 再送高字节
		// 以上置8253通道2 的计数初值
		short int  note= *ptrFreq;  //从PB口显示当前音阶
		switch (note)
		{
		case 262: out = 0xfe;
			break;
		case 294: out = 0xfd; 
			break; 
		case 330: out = 0xfb; 
			break; 
		case 349: out = 0xf7; 
			break; 
		case 392: out = 0xef; 
			break; 
		case 440: out = 0xdf;
			break; 
		case 494: out = 0xbf;
			break; 
		case 131: out = 0xfe; 
			break; 
		case 147: out = 0xfd; 
			break; 
		case 165: out = 0xfb; 
			break; 
		case 175: out = 0xf7; 
			break; 
		case 196: out = 0xef; 
			break; 
		case 220: out = 0xdf; 
			break;
		case 247: out = 0xbf; 
			break; 
		}
		outportb( PORTB, out); //置8255芯片PB口的当前值
		
		outportb( CTRL_8255, 0x01 );
		outportb( CTRL_8255, 0x0d ); // 开扬声器
		
		while ( *pTimeDelay){};      //等待延时到
		
		outportb( CTRL_8255, 0x0c );
		outportb( CTRL_8255, 0x00 ); // 关闭扬声器
		setvect(0x72,oldhandler);//恢复原中断向量
     	status=inportb(0xa1);
	    outportb(0xa1,status|0x04);//屏蔽IRQ10(OCW1)
    	status=inportb(0x21);
	    outportb(0x21,status|0x04);//屏蔽IRQ2
 
		ptrFreq++;      // 获取下一个音频
		ptrTimeDelay++; // 获取下一个延时 
	} // 歌曲结束或按了任意键

    outportb( PORTB,0xff );       //熄灭所有指示灯
    outportb( CTRL_8255,0x0c );
    outportb( CTRL_8255,0x00 );   // 再次关闭扬声器
    setvect(INTR,oldhandler);     // 恢复原中断向量
    
    return 0;
}

void main(void)
{
	printf("Now Playing Music!\n");
	printf("Hit ESC key to exit:\n");//初始化歌曲相关信息数组
	Music[0].Freq      = Music1;
	Music[0].TimeDelay = Music1_Delay;
	Music[1].Freq      = Music2;
	Music[1].TimeDelay = Music2_Delay;
	Music[2].Freq      = Music3;
	Music[2].TimeDelay = Music3_Delay;
	Music[3].Freq      = Music4;
	Music[3].TimeDelay = Music4_Delay;
    Music[4].Freq      = Music5;
	Music[4].TimeDelay = Music5_Delay;
	Music[5].Freq      = Music6;
	Music[5].TimeDelay = Music6_Delay;
	Playing();//调用播放歌曲子程序
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -