如何在c ++中读取程序的输出?

时间:2018-05-22 04:02:15

标签: c++ arduino cout

正在构建一个魔方求解器机器,我需要一种方法来读取程序的输出,以便它可以将它送到机器的步进电机

代码输出这样的东西 (代码用C ++编写)

________________________| RUBIK'S CUBE SOLVER |________________________

Input :

enter code here

White Side : Red Side : Orange Side : Blue Side : Green Side : Yellow Side : 
-------------------------------------------------

Turn these sides of the Cube in Clockwise Direction by 90 degrees in this exact order...

Yellow
Yellow
White
Orange

...

以下是代码片段,我在想是否可以添加某种功能来读取“cout”并将其直接发送到arduino

  if (choice=='w')

{
cout<<"White"<<endl;
swap(white[7],white[3]);
swap(white[6],white[4]);
swap(white[0],white[2]);
swap(white[7],white[5]);
swap(white[0],white[4]);
...

所以我基本上只想将包含颜色的字符串发送到Arduino中,以便它可以执行动作

1 个答案:

答案 0 :(得分:0)

请不要发布重复的问题。

  1. 求解器的输出(颜色命令)没有多大意义

    会让你头疼 MCU 。更好的方法是使用旋转命令的标准符号L,R,U,D,F,B,如此处

    rotations

    您可以使用小写/大写字符区分 CW / CCW 方向。这样您就可以准确地知道哪个切片以及旋转方向。

    直接在 MCU 上运行解算器代码可能会很慢(特别是如果它是基于测试+回溯的基础)。如果是简单的人类求解器(就像我在上面的链接中所使用的那样) MCU 处理能力应该足够。

  2. 现在如何将数据从求解器(假设是Windows PC)提供给MCU?

    最简单的方法是使用 RS232 ,但为此您需要电压转换器,如 MAX232 (您的 MCU 电路板可能有它或它使用一些 USB 芯片 USB2RS232 转换器 TTL 电压,如 FTDI 或其他小型 MCU

    所以你应该做的是编写一个解析器,它接收你的文件(或流或者什么)在PC端(可以是你解决的同一个可执行文件)将命令转换为单个char U,D,L,R,F,B样式并将其发送到 RS232

    使用 USB 也可以做到这一点,但由于需要驱动程序,而且 PC MCU 对于一个新手而言,这不是一个好主意。

    在Windows中,你只需打开像COM1这样的文件设置其属性,然后从/向它读取/写入你的东西(就像文件一样)。这是一个小的 Win32 C ++ / VCL lib port.h我在很久以前写过这样的东西:

    //---------------------------------------------------------------------------
    //--- port class ver: 2.0 ------------------------------------------------
    //---------------------------------------------------------------------------
    #ifndef _port_h
    #define _port_h
    //---------------------------------------------------------------------------
    class port
            {
    public: HANDLE       hnd;
            DWORD        error;
            DWORD        rlen,wlen;
            DCB          rs232_state;
            COMMPROP     properties;
            COMMTIMEOUTS timeouts;
            COMSTAT      stat;
            port();
            ~port();
            int  open(AnsiString name);
            void close();
            int  get_stat();        // err,stat
            int  get_timeouts();    // timeouts
            int  set_timeouts();
            int  get_properties();  // properties
            int  get_rs232_state(); // rs232_state
            int  set_rs232_state();
            void rst_rs232_state();
            void out(BYTE data)  { WriteFile(hnd,&data,1,&wlen,NULL); }
            void in (BYTE *data) { ReadFile (hnd, data,1,&rlen,NULL); }
            void in (char *data) { ReadFile (hnd, data,1,&rlen,NULL); }
            void out(BYTE *data,DWORD len) { WriteFile(hnd,data,len,&wlen,NULL); }
            void in (BYTE *data,DWORD len) { ReadFile (hnd,data,len,&rlen,NULL); }
            };
    //---------------------------------------------------------------------------
    port::port()
            {
            rlen=0;
            wlen=0;
            error=0;
            hnd=(void*)0xFFFFFFFF;
            rst_rs232_state();
            }
    //---------------------------------------------------------------------------
    port::~port()
            {
            close();
            }
    //---------------------------------------------------------------------------
    int port::open(AnsiString name)
            {
            close();
            error=0;
            rlen=0;
            wlen=0;
            hnd=CreateFile( name.c_str(),GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_ALWAYS,0,NULL);
            error=GetLastError();
            if ((DWORD)hnd==0xFFFFFFFF) return 0;
            get_timeouts();
            get_properties();
            get_rs232_state();
    
            timeouts.ReadIntervalTimeout;
            timeouts.ReadTotalTimeoutMultiplier;
            timeouts.ReadTotalTimeoutConstant;
            timeouts.WriteTotalTimeoutMultiplier;
            timeouts.WriteTotalTimeoutConstant;
    
            properties.wPacketLength;
            properties.wPacketVersion;
            properties.dwServiceMask;
            properties.dwReserved1;
            properties.dwMaxTxQueue;
            properties.dwMaxRxQueue;
            properties.dwMaxBaud;
            properties.dwProvSubType;
            properties.dwProvCapabilities;
            properties.dwSettableParams;
            properties.dwSettableBaud;
            properties.wSettableData;
            properties.wSettableStopParity;
            properties.dwCurrentTxQueue;
            properties.dwCurrentRxQueue;
            properties.dwProvSpec1;
            properties.dwProvSpec2;
            properties.wcProvChar[1];
    
            return 1;
            }
    //---------------------------------------------------------------------------
    void port::close()
            {
            if ((DWORD)hnd==0xFFFFFFFF) return;
            CloseHandle(hnd);
            error=GetLastError();
            hnd=(void*)0xFFFFFFFF;
            }
    //---------------------------------------------------------------------------
    int port::get_stat()
            {
            if ((DWORD)hnd==0xFFFFFFFF) return 0;
            DWORD err;
            if (ClearCommError(hnd,&err,&stat)) return 1;
            error=GetLastError();
            return 0;
            }
    //---------------------------------------------------------------------------
    int port::get_timeouts()
            {
            if ((DWORD)hnd==0xFFFFFFFF) return 0;
            if (GetCommTimeouts(hnd,&timeouts)) return 1;
            error=GetLastError();
            get_stat();
            return 0;
            }
    //---------------------------------------------------------------------------
    int port::set_timeouts()
            {
            if ((DWORD)hnd==0xFFFFFFFF) return 0;
            if (SetCommTimeouts(hnd,&timeouts)) return 1;
            error=GetLastError();
            get_stat();
            return 0;
            }
    //---------------------------------------------------------------------------
    int port::get_properties()
            {
            if ((DWORD)hnd==0xFFFFFFFF) return 0;
            if (GetCommProperties(hnd,&properties)) return 1;
            error=GetLastError();
            get_stat();
            return 0;
            }
    //---------------------------------------------------------------------------
    int port::get_rs232_state()
            {
            if ((DWORD)hnd==0xFFFFFFFF) return 0;
            if (GetCommState(hnd,&rs232_state)) return 1;
            error=GetLastError();
            get_stat();
            return 0;
            }
    //---------------------------------------------------------------------------
    int port::set_rs232_state()
            {
            if ((DWORD)hnd==0xFFFFFFFF) return 0;
            if (SetCommState(hnd,&rs232_state)) return 1;
            error=GetLastError();
            get_stat();
            return 0;
            }
    //---------------------------------------------------------------------------
    void port::rst_rs232_state()
            {
            rs232_state.BaudRate    = CBR_9600;
            rs232_state.ByteSize    = 8;
            rs232_state.Parity      = NOPARITY;
            rs232_state.StopBits    = ONESTOPBIT;
            rs232_state.fOutxCtsFlow= FALSE;
            rs232_state.fOutxDsrFlow= FALSE;
            rs232_state.fOutX       = FALSE;
            rs232_state.fInX        = FALSE;
            rs232_state.fBinary     = FALSE;
            rs232_state.fRtsControl = RTS_CONTROL_DISABLE;
            }
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    #endif
    //---------------------------------------------------------------------------
    

    它在 VCL 中使用的唯一内容是AnsiString,它是字符串数据类型,其字符访问权限来自1,而不是0AnsiString s; s.c_str();只返回char*指针,因此您可以直接将所有这些指针移植到char*或您可以使用的字符串类型。

    在处理 RS232 时,您应该记住您需要某种同步,因为另一方从不知道它是从头开始接收数据还是在初始化之前已经发送了一些数据。因此,您应该向求解器流添加一些开始/结束命令。

    您还可以同时读取和写入 RS232 ,但您需要使用线程来正确实现此功能。这就是我通常这样做的方式:

    #include <windows.h>
    //typedef uint32_t DWORD;           // uncomment this if no DWORD type is present
    //typedef uint16_t WORD;            // uncomment this if no WORD type is present
    //typedef uint8_t BYTE;             // uncomment this if no BYTE type is present
    #include "port.h"
    
    port com;
    const int _timeout=1;
    const BYTE _id_timeout=0;
    unsigned char q;
    
    // init or reconnect
    com.open("COM1"); // use number of your COM port to use can be different than 1 especially for USB converters see device manager)
    com.timeouts.ReadIntervalTimeout        =_timeout;
    com.timeouts.ReadTotalTimeoutMultiplier =_timeout;
    com.timeouts.ReadTotalTimeoutConstant   =_timeout;
    com.timeouts.WriteTotalTimeoutMultiplier=_timeout;
    com.timeouts.WriteTotalTimeoutConstant  =_timeout;
    com.set_timeouts();
    com.rs232_state.BaudRate=CBR_9600;
    com.set_rs232_state();
    
    // write
    q='L';
    com.out(q);
    
    // read (this can freeze if no data in RS232 and timeout set too big)
    q=_id_timeout;
    com.in (&q);
    if (q==_id_timeout) /* do something if timeout*/ ;
    else /* handle valid data*/ ;
    
    // exit
    com.close();
    

    如果您的环境不知道BYTE, WORD, DWORD,请使用uint8_t, uint16_t, uint32_t或使用typedef进行更改。 WinAPI 功能需要包含windows.h

    正如我之前提到的那样,请注意在没有从其他方面发送实际数据的情况下读取 COM 端口可能会冻结您的代码,因此最好将读取和写入分离到线程或更短的时间并考虑到丢失由于冻结造成的数据。

    在转到 MCU 之前,您应该检查 PC 端代码是否正常工作(因为您可以轻松调试 PC 一侧而不是 MCU 方面)。您的 MCU 的代码模拟器将从您的求解器读取 RS232 源并将其打印到控制台等任何地方,以便您可以查看数据是否正确。然后通过环路连接 RS232 (通过电线短接RxD和Txd引脚)......

  3. MCU端的代码

    应该或多或少地做同样的事情,但你没有winapi,所以你需要使用你拥有的框架。大多数 MCU 已将iostream重载为 RS232 ,因此您只需使用cin/cout代替所有这些。我没有在Arduino框架中编码(我使用C ++( GCC )代表 MCU )并且 RS232 / UART 访问取决于 MCU 芯片架构和版本因此无法帮助您。

    要记住的重要一点是,您需要以与PC端相同的方式设置RS232协议。所以相同数量的启动/停止/奇偶校验位,相同的BaudRate等......