|
发表于 2023-3-17 19:56:40
|
显示全部楼层
小苹果
#include <reg52.h>
// 待播放的音乐数据
const unsigned char music_data[] = {
// YM2163内部寄存器设置,将内部寄存器设置为播放《小苹果》
0x28, 0x00, // FNUM LOW
0x29, 0x02, // FNUM HIGH
0x2B, 0x80, // CH1 ON, BLOCK=0, LFO OFF
0x2C, 0x08, // CH1 DETUNE, MULTIPLE=1
0x2D, 0x30, // CH1 TL
0x2E, 0x00, // CH1 KS=0, ATTACK RATES=0
0x2F, 0x4F, // CH1 DECAY RATES=4, SUSTAIN LEVELS=15
0x30, 0x0F, // CH1 RELEASE RATES=15, SSG-EG OFF
// 利用不同的等待时间来调整音符的节奏
// 前4个音符
0x28, 0x00,
0x29, 0x02,
0x00, 0xA0,
0x28, 0x00,
0x29, 0x02,
0x00, 0xA0,
0x28, 0x00,
0x29, 0x02,
0x00, 0x50,
0x28, 0x00,
0x29, 0x02,
0x00, 0x50,
// 中间部分
0x2C, 0x08,
0x2D, 0x20,
0x00, 0x10,
0x00, 0x10,
0x2C, 0x08,
0x2D, 0x20,
0x00, 0x80,
0x28, 0x00,
0x29, 0x01,
0x00, 0x40,
0x28, 0x00,
0x29, 0x01,
0x00, 0x20,
0x28, 0x00,
0x29, 0x01,
0x00, 0x20,
0x28, 0x00,
0x29, 0x02,
0x00, 0xA0,
// 后半部分
0x2C, 0x08,
0x2D, 0x30,
0x28, 0x00,
0x29, 0x02,
0x00, 0xA0,
0x2C, 0x08,
0x2D, 0x30,
0x28, 0x00,
0x29, 0x02,
0x00, 0xA0,
0x2C, 0x08,
0x2D, 0x30,
0x28, 0x00,
0x29, 0x02,
0x00, 0xA0,
0xFF, 0xFF, // 结束标志
};
// 延时函数,控制音符的节拍
void delay(unsigned int ms) {
while (ms-- > 0) {
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
// 向YM2163芯片写入一条命令
void write_command(unsigned char command) {
P0 = command;
delay(1);
}
// 向YM2163芯片写入一条数据
void write_data(unsigned char data) {
P0 = data;
delay(1);
}
// 播放一首音乐
void play_music(const unsigned char* music_data) {
unsigned char i = 0;
unsigned char reg_data;
// 循环读取音乐数据,直到遇到结束标志
while (1) {
unsigned char reg_addr = music_data[i++];
reg_data = music_data[i++];
if ((reg_addr == 0xFF && reg_data == 0xFF) || i >= sizeof(music_data)) {
// 遇到结束标志或者超出数组范围,退出循环
break;
}
write_command(reg_addr);
write_data(reg_data);
}
// 播放结束,停止输出音乐信号
write_command(0x2B);
}
// 主函数,控制YM2163芯片播放音乐
void main() {
// 连接芯片的IO口需要根据实际情况进行修改
// 这里假设P0口作为地址总线和数据总线连接到YM2163的接口
P0 = 0x00;
// 播放小苹果
play_music(music_data);
// 停止输出音乐信号
write_command(0x2B);
// 程序结束,停止运行
while (1); |
|