MIDI控制程序 Aduino平台 容易迁移到STM8/STM32

/*
硬件连接:
 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

    //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
  }
  //=================================================================


  //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);
}

猜你喜欢

转载自blog.csdn.net/weixin_43572492/article/details/84974407