2017-01-29 56 views
1

我正在Visual Studio 2013中编写一个C程序,通过串行(COM)端口将MIDI数据发送到MIDI设备。我的代码迄今如下:无法通过串行/ COM端口发送MIDI数据C

打开串行/ COM端口:

unsigned int SERIALCOMMS_OpenPort(HANDLE *hSerialPort, 
            unsigned int comPortNum, 
            unsigned int baudRate) 
{ 
    DCB dcbSerialParams = {0}; 
    COMMTIMEOUTS timeouts = {0}; 
    unsigned char portStr[COM_PORT_LEN_MAX]; 

    /* Initialisations */ 
    memset(portStr, 0x00, sizeof(portStr)); 

    /* Construct the COM port string */ 
    sprintf(portStr, "%sCOM%d", COM_PORT_PREFIX, comPortNum); 

    printf("Opening serial port..."); 
    *hSerialPort = CreateFile((LPCSTR)portStr, 
           (GENERIC_READ | GENERIC_WRITE), 
           0, 
           NULL, 
           OPEN_EXISTING, 
           FILE_ATTRIBUTE_NORMAL, 
           NULL); 
    if (*hSerialPort == INVALID_HANDLE_VALUE) 
    { 
     if (GetLastError() == ERROR_FILE_NOT_FOUND) 
     { 
      printf("\nError: \nThe system cannot find the file specified (%s)\n", portStr); 
      return 1; 
     } 
     else if (GetLastError() == ERROR_INVALID_NAME) 
     { 
      printf("\nError: \n%s port name syntax is incorrect'\n", portStr); 
      return 1; 
     } 
     else 
     { 
      printf("\nHandle creation error code: %x\n", GetLastError()); 
      return 1; 
     } 
     puts("\t...CreateFile returned an invalid handle value"); 
    } 
    printf("OK\n"); 

    /* Set device parameters */ 
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams); 
    if (GetCommState(*hSerialPort, &dcbSerialParams) == 0) 
    { 
     printf("Error getting device state\n"); 
     CloseHandle(*hSerialPort); 
     return 1; 
    } 


    dcbSerialParams.BaudRate = baudRate; 
    dcbSerialParams.ByteSize = 8; 
    dcbSerialParams.StopBits = ONESTOPBIT; 
    dcbSerialParams.Parity = NOPARITY; 
    if (SetCommState(*hSerialPort, &dcbSerialParams) == 0) 
    { 
     printf("Error setting device parameters\n"); 
     return 1; 
    } 

    /* Set COM port timeout settings */ 
    timeouts.ReadIntervalTimeout = 50; 
    timeouts.ReadTotalTimeoutConstant = 50; 
    timeouts.ReadTotalTimeoutMultiplier = 10; 
    timeouts.WriteTotalTimeoutConstant = 50; 
    timeouts.WriteTotalTimeoutMultiplier = 10; 
    if (SetCommTimeouts(*hSerialPort, &timeouts) == 0) 
    { 
     printf("Error setting timeouts\n"); 
     return 1; 
    } 

    return 0; 
} 

恒定COM_PORT_PREFIX定义如下:

#define COM_PORT_PREFIX  "\\\\\.\\" 

端口打开细。但是,当我向它发送数据时,收到的数据似乎与应该发送的数据大不相同。我正在用一个Arduino来测试它,该程序被编程为将接收到的数据作为整数/十六进制值进行处理,以便测试PC实际发送的内容。

下面是用于发送数据的功能的代码:

unsigned int SERIALCOMMS_Send(HANDLE hSerialPort, 
           unsigned char *txData, 
           unsigned int *byteCount) 
{  
    unsigned int bytesWritten = 0u; 

    /* Transmit data */ 
    if (!WriteFile(hSerialPort, txData, *byteCount, &bytesWritten, NULL)) 
    { 
     printf("Error transmitting data\n"); 
     return 1; 
    } 
    printf("\n%d bytes written\n", bytesWritten); 

    return 0; 
} 

使用下面的方法与上述的“发送”功能:

unsigned int byteCount = 1u; 
unsigned char dataByte[1]; 

SERIALCOMMS_Send(hSerialPort, dataByte, &byteCount); 

当我发送以下MIDI数据(十六进制值),它会收到如下:

  • 0x91接收为0xC9
  • 0x92被接收为0xC8
  • 0x93被接收为0xC9
  • 0x94的被接收为0xCA
  • 位0x95被接收为0xCB
  • 0X24被接收为0xD2

显然,没有这说得通。我无法弄清楚是什么原因造成的。一些在Visual Studio项目属性的配置如下:

Project settings

一个可能的方面可能被指定的字符集(当前设置为“使用多字节字符集”)。如果我将其更改为“使用Unicode字符集”,则程序无法与COM端口连接。

从逻辑上思考问题,它必须与我发送数据的方式有关。我很可能以错误的方式传递MIDI数据,但我真的无法弄清楚是什么原因导致了问题以及我做错了什么。

任何帮助将不胜感激。

更新: PC和Arduino上的波特率设置为31250 bps(按照MIDI标准)。

+0

什么是'baudRate'?什么是Arduino使用的标称波特率?从该波特率生成的时钟开始? –

+0

@CL:PC和Arduino上的波特率设置为31250 bps(按照MIDI标准)。在Arduino上,使用Serial.begin(31250)初始化串口时设置了波特率。 问题用这些信息更新。 – user3699569

+0

MIDI供应商的组织确保每个人都必须购买他们的产品的一种方法是选择商品硬件无法生成的波特率。在两端选择9600并重试。 –

回答

0

看来,根据this answer on another thread on stackoverflow,在Windows平台上使用非标准波特率并不是那么简单,因为PC中用于计算UART波特率的晶体振荡频率以及波特率的推导方式由此。因此,似乎最好坚持标准的波特率。

使用标准波特率解决了我的问题。然而,它因此强制改变了我所使用的硬件规格,这并不理想。

这当然会引发下面的问题 - 为了能够使用非标准的波特率,人们需要做些什么?是否必须为此编写额外的/定制的驱动程序?