在C#中读取和写入串行端口的数据

时间:2016-11-11 11:15:32

标签: c# arduino serial-port console-application

我正在构建一个控制台应用程序,该应用程序将在Windows的任务计划程序中安排,以便在设定的每小时每天运行我的代码。总而言之,此应用程序将通过SerialPort进行读写。当我向Arduino发送内容时,我需要从中收到一些内容以完成我发送的内容并执行命令。

换句话说,我会发送一些东西,看看门是否打开,如果是应用程序将运行代码关闭它。如果门已关闭,我将发送一串字符显示在Arduino Led Display中。

所以我开发了一个代码,但我不确定它是否完全正确,如果有可能帮助我改进它。我可以做出任何改变吗?

static void Main(string[] args)
{
    SerialPort comport = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
    comport.Open();

    string start = "?";
    string carriageReturn = "\r";
    string text = string.Empty;

    string mensage = "@" + "r" + "\r";
    string mensage2 = "@" + "{" + texto + "\r";

    try
        {
            while (true)
            {
                //Send to the Arduino
                comport.Write(start+ "*" + carriageReturn);

                //If the serial port have bytes to read
                if (comport.BytesToRead > 0)
                { 
                    //Buffer with data
                    byte[] dados = HexStringToByteArray(mensage);

                    //Handle data
                    comport.Read(dados, 0, dados.Length);

                    //Send again to execute the the command
                    comport.Write(start + "*" + carriageReturn);
                }

                if (comport.BytesToRead > 0)
                { 
                    comport.Write(start + "*" + carriageReturn);

                    byte[] dados2 = HexStringToByteArray(mensage2);

                    comport.Read(dados2, 0, dados2.Length);

                    comport.Write(text);
                }
                comport.Close();
            }
        }

        catch(Exception ex)
        {
        }
}

private static byte[] HexStringToByteArray(string s)
{
    s = s.Replace(" ", "");
    byte[] buffer = new byte[s.Length / 2];

    for (int i = 0; i < s.Length; i += 2)
        buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
        return buffer;
}

修改

我的基本输入输出映射/关系是:

我会将?*\r发送给Arduino,然后我会等待回答。

如果,Arduino的答案为@r\r,我会再次发送?*\r

如果来自Arduino的回答是@{/r我将向他发送一个字符串。

2 个答案:

答案 0 :(得分:0)

这是我修改的第一次尝试。

您应该考虑使用DataReceived事件并使用退出策略。到目前为止,您的程序永远不会退出。

static void Main(string[] args)
{
    SerialPort port = new SerialPort("COM1", 9600, Parity.Odd, 7, StopBits.One);
    // register the event
    port.DataReceived += Port_DataReceived;
    //open the port
    port.Open();

    try
    {
        // start the communication
        port.Write("?*\r");

        Console.WriteLine("Waiting for response");

        // Your manual exit strategy. Hit a kKeyboard-key to end this game
        while (!Console.KeyAvailable)
        {
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine("Writing failed! \nError: " + ex.Message);
    }        
}

一旦Arduino发送给你,DataReceived事件就会被解雇。如果没有,您可以手动退出程序。

在活动中你可以完成整个逻辑。正如您已经发布了输入输出映射,您可以将其破解为固定代码,因为它是在您的帖子中编写的。如果仅有两种情况,您也可以使用开关/案例构造:

private static void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort port = sender as SerialPort;

    // read input
    string incoming = port.ReadExisting();

    switch (incoming)
    {
        case "@r\r":
            // send the message back
            port.Write("?*\r");
            break;
        case @"@{/r":
            port.Write("Display this!");
            break;
        default:
            Console.WriteLine("Unknown command from Arduino!\n Command: " + incoming);
            break;
    }
}

我希望它有所帮助

答案 1 :(得分:0)

如果我理解你的描述(关闭门将由arduino完成,对吧?),这就是任务:

  • 任务预定控制台应用程序通过串口触发arduino以检查状态并执行某些操作(如果状态告知必要)
  • Arduino报告状态(最终执行该任务)

你可以这么做:

"?" --> PC sends a trigger: Check door status and behave accordingly

然后PC等待回复:

"1"  <-- Arduino response ( door was already closed )
"2"  <-- or alternate response ( I closed the door )

Arduino可以发送任何其他内容来表示错误。 (随意发明就足够了)

此外,arduino可能根本没有回应。那么你的预定控制台应用程序会做什么呢?

您不需要发送/接收超过一个字节,以使Arduino和您的小型串行PC代码更简单。

PC代码没有用户界面,所以Arduino不需要立即响应,如果关闭门需要一段时间。