在 Visual Studio 中将串口应用程序从 C# 转换为 C (ERROR_INVALID_PARAMETER) 87

Posted

技术标签:

【中文标题】在 Visual Studio 中将串口应用程序从 C# 转换为 C (ERROR_INVALID_PARAMETER) 87【英文标题】:Convert serial port application from C# to C in visual studio (ERROR_INVALID_PARAMETER) 87 【发布时间】:2011-06-03 19:25:01 【问题描述】:

我正在尝试用 C 编写一个应用程序以通过 COM 端口与设备通信。

我可以使用具有以下设置的 Docklight(类似程序的超级终端)发送数据,并且可以验证我是否通过 Itronix LogicPort 逻辑分析仪接收数据。 波特率:9600 奇偶校验:无 字节大小:8 停止位:1

我的 C 程序有 2 个问题: 1) 有时 CreateFile 返回 INVALID_HANDLE_VALUE 我似乎无法解决的另一个问题是 GetCommState() 设置通信状态() SetCommTimeouts() 总是返回 ERROR_INVALID_PARAMETER 87 (0x57)

由于我无法解决这个问题,我尝试了一个 C# 程序,它工作得很好,但是我的程序必须是 C 语言才能与我的其余代码进行通信。该程序还通过套接字与 C 中的其他程序进行通信。

在设备管理器中,我想与之通话的设备在端口(COM 和 LPT)下列为 COM6

任何帮助将不胜感激!

以下是两个程序的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace WindowsFormsApplication1

  public partial class Form1 : Form
  

    byte[] TxBuffer = new byte[20];

    SerialPort CommPort = new SerialPort("COM6", 9600, Parity.None, 8, StopBits.One);

    public Form1()
    
        InitializeComponent();
    

    private void Form1_Load(object sender, EventArgs e)
    
        CommPort.Open();
        TxBuffer[0] = (byte)'|';
        TxBuffer[1] = 0;
        TxBuffer[2] = 0;
        TxBuffer[3] = 0;
        TxBuffer[4] = 1;
        TxBuffer[5] = 100;
        TxBuffer[6] = 1;
        TxBuffer[7] = 6;
        TxBuffer[8] = (byte)'|';
        TxBuffer[9] = 1;

    

    private void button1_Click(object sender, EventArgs e)
    
        CommPort.Write(TxBuffer, 0, 10);
    
  

而C代码是:

某处

 struct serial_dev 
         HANDLE hSerial;
 ;        

  struct serial_dev sdev;  //global

       //somewhere in main
   if (init_serial(&sdev, com_file) == -1)
       return -1;
   write_ser(&sdev, buffer, buf_size);
   close_serial(&sdev);

       // in serial.c

    int init_serial(struct serial_dev *sdev, char *port_name)
    
        DCB dcbSerialParams;
        COMMTIMEOUTS timeouts;
        int error = 0;

        memset(&dcbSerialParams, 0, sizeof(dcbSerialParams));
        memset(&timeouts, 0, sizeof(timeouts));

        sdev->hSerial = CreateFile("COM6", GENERIC_READ | GENERIC_WRITE, 0, NULL,  OPEN_EXISTING, 0, NULL);

        if (sdev->hSerial == INVALID_HANDLE_VALUE) 
        
            error = GetLastError();
            close_serial(sdev);
            fprintf(stderr, "error: could not open serial port (error:%d)\n", error);
            return -1;
        


        memset(&dcbSerialParams, 0, sizeof(dcbSerialParams));
        dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

        if (!GetCommState(sdev->hSerial, &dcbSerialParams)) 
        
            close_serial(sdev);
            error = GetLastError();
            fprintf(stderr, "error: could not get serial port state (%d)\n", error);
            return -1;
        

        dcbSerialParams.BaudRate = CBR_9600;
        dcbSerialParams.ByteSize = 8;
        dcbSerialParams.StopBits = ONESTOPBIT;
        dcbSerialParams.Parity = NOPARITY;

        if (!SetCommState(sdev->hSerial, &dcbSerialParams)) 
        
            close_serial(sdev);
            error = GetLastError();
            fprintf(stderr, "error: could not set serial port state (%d)\n", error);
            return -1;
        


        timeouts.ReadIntervalTimeout = 50;
        timeouts.ReadTotalTimeoutConstant = 200;
        timeouts.ReadTotalTimeoutMultiplier = 10;
        timeouts.WriteTotalTimeoutConstant = 50;
        timeouts.WriteTotalTimeoutMultiplier = 10;

        if (!SetCommTimeouts(sdev->hSerial, &timeouts)) 
        
            close_serial(sdev);
            error = GetLastError();
            fprintf(stderr, "error: could not set serial port timeouts (%d)\n", error);
            return -1;
        



        return 0;
    

    void close_serial(struct serial_dev *sdev)
    
            CloseHandle(sdev->hSerial);
    

    int write_ser(struct serial_dev *sdev, void *buf, size_t len)
    
        DWORD written;
        BOOL success;


        success = WriteFile(sdev->hSerial, buf, len, &written, NULL);
        if(!success || written == 0)
        
            printf("error writing to serial\n");
            return -1;
        
        printf("writing to serial OK!\n");
        return written;
    

【问题讨论】:

当 CreateFile 返回 INVALID_HANDLE_VALUE 时,您应该报告 GetLastError 值。这可能是端口之前没有关闭的问题。 注意:你应该使用 "\\.\COM6" 作为 CreateFile (不确定它会改变什么)。 @harper - 我已经在发布的代码中这样做了 @Simon Mourier - 现在我的 CreateFile 调用正在使用“COM6”并且我得到了一个有效的 HANDLE,但是 GetCommState()、SetCommState() 和 SetCommTimeouts() 仍然失败并出现错误 87。当我用“\\.\COM6”尝试它时,它失败并出现错误 2 (ERROR_FILE_NOT_FOUND)。 @emge:您没有发布您为 CreateFile 获得的错误代码,是吗? 【参考方案1】:

伙计们,我想通了...我从项目设置中删除了“UNICODE”和“_UNICODE”预处理器宏,并将其设置为“未设置”,在这里找到答案:http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/1a77c595-10a5-4f14-8512-c67535c53a08/

【讨论】:

以上是关于在 Visual Studio 中将串口应用程序从 C# 转换为 C (ERROR_INVALID_PARAMETER) 87的主要内容,如果未能解决你的问题,请参考以下文章

visual studio 2010 或者2013 串口通信 使用serialport的具体操作

在 Visual Studio 2008 中将目录添加到 CAB 项目

在 Visual Studio 2017 中将 .NET Core 2.2 应用程序发布为依赖于框架的可执行文件 (FDE)

在 Visual Studio 2010 中将 Excel 数据导入 DataGridView

在 Visual Studio 2010 中将输出消息写入“输出窗口”的最简单方法?

如何在 Visual Studio 中将用 C 编写的源代码从另一个项目包含到我自己的 C++ 项目中