/*****************************************************************************************
硬件连接:
5V : Arduino上的5V连接音效板的VCC
GND : Arduino上的GND连接音效板上的GND
D3 Arduino上的软串口的TX引脚(D3引脚)连接音效板上的MIDI引脚
D4 : Arduino上的D4引脚连接音效板上的RESET引脚
*****************************************************************************************/
//软串口库
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //引脚2是RX(没用到), 引脚3是TX
byte note = 0; //音符变量,表示将要播放的音符,初始值是0,范围是0-127
byte resetMIDI = 4; //数字引脚4,连接到VS1053的复位引脚
byte ledPin = 13; //MIDI通讯指示灯
int instrument = 0; //乐器号变量,初始值为0
void setup()
{
//设置硬串口波特率为57600bps,用于连接PC以显示程序运行状态
Serial.begin(57600);
//设置用于MIDI通讯的软串口,波特率为31250bps
mySerial.begin(31250);
//对VS1053进行复位:低电平持续100ms,后拉高并保持
pinMode(resetMIDI, OUTPUT); //复位引脚设置为输出
digitalWrite(resetMIDI, LOW); //引脚电平拉低
delay(100);
digitalWrite(resetMIDI, HIGH); //引脚电平拉高
delay(100);
talkMIDI(0xB0, 0x07, 120); //0xB0 是通道消息, 设置1通道音量接近最大 (127)
}
void loop() {
//基本的MIDI乐器, GM1,参见VS1053手册33页
//=================================================================
Serial.println("Basic Instruments");
talkMIDI(0xB0, 0, 0x00); //默认bank GM1
//改变不同的乐器,GM1总共有128种乐器,0~127
for(instrument = 0 ; instrument < 127 ; instrument++)
{
Serial.print(" Instrument: ");
Serial.println(instrument, DEC);
talkMIDI(0xC0, instrument, 0); //设置MIDI通道1的乐器为instrument
//播放音符,从 F#-0 (30) 到 F#-5 (90):
for (note = 30 ; note < 40 ; note++)
{
Serial.print("N:");
Serial.println(note, DEC);
//通道1开打开音符Note,力度为60
noteOn(0, note, 60);
delay(50);
//通道1开关闭音符Note,力度为60
noteOff(0, note, 60);
delay(50);
}
delay(100); //乐器切换间隔
}
//=================================================================
//Demo GM2 / Fancy sounds
//=================================================================
Serial.println("Demo Fancy Sounds");
talkMIDI(0xB0, 0, 0x78); //Bank select drums 选择打击乐器
//For this bank 0x78, the instrument does not matter, only the note
for(instrument = 30 ; instrument < 31 ; instrument++) {
Serial.print(" Instrument: ");
Serial.println(instrument, DEC);
talkMIDI(0xC0, instrument, 0); //Set instrument number. 0xC0 is a 1 data byte command
//Play fancy sounds from 'High Q' to 'Open Surdo [EXC 6]'
for (note = 27 ; note < 87 ; note++) {
Serial.print("N:");
Serial.println(note, DEC);
//Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
noteOn(0, note, 60);
delay(100);
//Turn off the note with a given off/release velocity
noteOff(0, note, 60);
delay(100);
}
delay(100); //Delay between instruments
}
//Demo Melodic
//=================================================================
Serial.println("Demo Melodic? Sounds");
talkMIDI(0xB0, 0, 0x79); //Bank select Melodic
//These don't sound different from the main bank to me
//Change to different instrument
for(instrument = 27 ; instrument < 87 ; instrument++) {
Serial.print(" Instrument: ");
Serial.println(instrument, DEC);
talkMIDI(0xC0, instrument, 0); //Set instrument number. 0xC0 is a 1 data byte command
//Play notes from F#-0 (30) to F#-5 (90):
for (note = 30 ; note < 40 ; note++) {
Serial.print("N:");
Serial.println(note, DEC);
//Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
noteOn(0, note, 60);
delay(50);
//Turn off the note with a given off/release velocity
noteOff(0, note, 60);
delay(50);
}
delay(100); //Delay between instruments
}
}
//发送一个MIDI音符开消息
//通道范围0-15
void noteOn(byte channel, byte note, byte attack_velocity) {
talkMIDI( (0x90 | channel), note, attack_velocity);
}
//发送一个MIDI音符关消息
void noteOff(byte channel, byte note, byte release_velocity) {
talkMIDI( (0x80 | channel), note, release_velocity);
}
//播放一个音符
//不要视图去看一看数值大于127或者小于127是什么样的
void talkMIDI(byte cmd, byte data1, byte data2) {
digitalWrite(ledPin, HIGH);
mySerial.write(cmd);
mySerial.write(data1);
//Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes
//有一些命令只有一个字节。所有小于0xBn的命令有两个数据字节
//(sort of: http://253.ccarh.org/handout/midiprotocol/)
if( (cmd & 0xF0) <= 0xB0)
mySerial.write(data2);
digitalWrite(ledPin, LOW);
}
MIDI控制程序 Arduino平台 容易迁移到STM8/STM32
最新推荐文章于 2021-04-15 10:57:43 发布