MIDI输出用PIC微处理器上的C二进制输出

Binary output using C on PIC microprocessor for MIDI output

所以我正在创建一个需要二进制输出才能运行的项目。我有一系列 IF 语句来确定输出是什么,这里一切都很好。问题是我正在使用 PIC 微控制器 16F877 并用 C 语言编程。 我正在使用 RS232 将信息直接发送到具有大约 8 个音符值和 8 个音量值(8x8 选项集)的 midi 控制器。

我也在用proteus和CCS编程

我的问题是:如何以二进制形式创建 MIDI 输出? 我知道所有二进制值,但不确定如何创建 "midi friendly" 输出。

编辑:根据要求添加示例代码:

#include <16F877.h>
TRISB=1; //sets all tris in portB to 1, to allow as inputs

TRISD=1; //sets all tris in portD to 1, to allow as inputs

TRISC.RC6=0; //sets trisC port 6 to 0, to allow as an output

#use rs232(baud=9600,parity=N,xmit=STDOUT,rcv=None,bits=8,stream=PORT1,float_high)
// initialises RS232 and configures for transmision
#use delay(crystal=4MHz)
// crystal at 4MHz is used (XT MODE)

#define X1  PIN_B0 //names pin B0 as X1
#define X2  PIN_B1 //names pin B1 as X2
#define X3  PIN_B2 //names pin B2 as X3
#define X4  PIN_B3 //names pin B3 as X4
#define X5  PIN_B4 //names pin B4 as X5
#define X6  PIN_B5 //names pin B5 as X6
#define X7  PIN_B6 //names pin B6 as X7
#define X8  PIN_B7 //names pin B7 as X8

#define STDOUT  PIN_C6 // Names pin C6 as STDOUT

#define Y1  PIN_D0 //names pin D0 as Y1
#define Y2  PIN_D1 //names pin D1 as Y2
#define Y3  PIN_D2 //names pin D2 as Y3
#define Y4  PIN_D3 //names pin D3 as Y4
#define Y5  PIN_D4 //names pin D4 as Y5
#define Y6  PIN_D5 //names pin D5 as Y6
#define Y7  PIN_D6 //names pin D6 as Y7
#define Y8  PIN_D7 //names pin D7 as Y8

char xout;
char yout;

int main (void)
 { 
   if(B0==1) //if B0 is 1, sets xout to "A"
   {
      xout='A';
   }
   if(B1==1) //if B1 is 1, sets xout to "B"
   {
      xout='B';
   }
   if(B2==1) //if B2 is 1, sets xout to "C"
   {
      xout='C';
   }
   if(B3==1) //if B3 is 1, sets xout to "D"
   {
      xout="D";
   }
   if(B4==1) //if B4 is 1, sets xout to "E"
   {
      xout='E';
   }
   if(B5==1) //if B5 is 1, sets xout to "F"
   {
      xout='F';
   }
   if(B6==1) //if B6 is 1, sets xout to "G"
   {
      xout='G';
   }
   if(B7==1) //if B7 is 1, sets xout to "H"
   {
      xout='H';
   }
   if(D0==1) //if D0 is 1, sets yout to "A"
   {
      yout='A';
   }
   if(D1==1) //if D1 is 1, sets yout to "B"
   {
      yout='B';
   }
   if(D2==1) //if D2 is 1, sets yout to "C"
   {
      yout='C';
   }
   if(D3=1) //if D3 is 1, sets yout to "D"
   {
      yout='D';
   }
   if(D4==1) //if D4 is 1, sets yout to "E"
   {
      yout='E';
   }
   if(D5==1) //if D5 is 1, sets yout to "F"
   {
      yout='F';
   }
   if(D6==1) //if D6 is 1, sets yout to "G"
   {
      yout='G';
   }
   if(D7==1) //if D7 is 1, sets yout to "H"
   {
      yout='H';
   }


   printf("%c,%c", xout yout); //outputs xout and yout for display on a screen

代替字母(它们只是为了演示实际输出,以便我可以进入 midi)将是二进制代码,printf 将输出 IF 语句中确定的 midi 值

编辑 2:进一步了解

我将主要使用 "switches" 的 8x8 网格(使用可见光作为接口方式)x 轴控制音符,Y 轴控制音量。我只需要一个输出,它将通过 5 针 DIN

直接进入 midi 控制器

我可能只使用 2 个命令(NoteOn、NoteOff)开始,然后根据需要继续。

下面是一个示例 "architecture",我可能会用它弄湿我的脚。 由于您需要跟踪 "note on" 和 "note off" 操作,我添加了全局 "state" 数组。第一个索引以交替方式在当前状态和旧状态之间变化。对于初学者来说,这可能就足够了。

8 个插槽用于 8 个键。如果按下键,该值可以是 "volume" 代码。如果没有按下该音调的键,则为 KEY_OFF。

#define KEY_OFF 0x80  // command parameters only use lower 7 bits...
static uint8_t state[2][8];

static void Configure()
{   // Do what you need to do in terms of initializing pins, serial port, etc...

}

static void UpdateState(uint8_t index)
{
    // read pins into the global state variable at first index "index"
    // Not pressed "tones" get value "OFF".
    // TIP: later, you could consider to use PIC 
    // "interrupt on change" features 
    // to save power. 
    // Tip: Depending on the types of your keys and your circuitry,
    // you might run into "bouncing keys" problems.
    // But the fact, that you send your serial messages synchronously
    // gives your keys some time to "settle", which might be enough.
}

// ROM based lookup table
// TODO: fill in correct values for your note-key to note-to-play mapping.
static const uint8_t notes[8] =
{ 0x01
, 0x01
, 0x01
, 0x01
, 0x01
, 0x01
, 0x01
, 0x01
};

static const uint8_t velocities[8] =
{
    // TODO: 8 entries mapping your "volume key" code to a MIDI "velocity" code.
};

#define DEFAULT_CHANNEL 0x00 // 16 channels available in midi... 0x00..0x0F

static void SerialSend(uint8_t count, const uint8_t * message)
{  // TODO: Implement sending the message on Rs232...
   // TIP: Use the flag "tx buffer EMPTY" before you write next byte.
   for( uint8_t i = 0; i < count; ++i )
   {
       while( !TXEMPTY ); // TODO: look up correct name ...
       TX = message[i]; // TODO: look up correct name...
   }
}

// Assuming to use only channel 0 here...
static void SendNoteOff(uint8_t note)
{
    // TODO: find out if NoteOff needs a "real" velocity value...
    uint8_t midiCmd[3] = { 0x80|DEFAULT_CHANNEL, notes[note], 0x00  };
    SerialSend(3, midiCmd);
}

static void SendNoteOn(uint8_t note, uint8_t velocity)
{
    uint8_t midiCmd[3] = { 0x90 | DEFAULT_CHANNEL, notes[note], velocities[velocity] };
    SerialSend(3, midiCmd);
}

// Named it emain() as it is in some random file of mine which already has a main ;)
void emain()
{
    Configure();
    uint8_t current = 0;
    uint8_t old = 1;
    while (1)
    {
        UpdateState(current);
        for (uint8_t i = 0; i < 8; ++i)
        {
            uint8_t os = state[old][i];
            uint8_t cs = state[current][i];
            if (os != cs )
            {
                if (0x00 != (cs & KEY_OFF))
                {
                    SendNoteOff(i);
                }
                else
                {
                    SendNoteOn(i, cs);
                }
            }
        }
        old = current;
        current = (current + 1) % 2;
    }
}