1

我一直在尝试通过 RS232 串行端口(在我的情况下是 COM6)与我的设备通信。我的代码应该向设备写入一串 ascii 值,然后读取响应,但是我似乎无法得到任何响应。当我让它在我的计算机中写入和读取文件时,该程序似乎工作得相对较好,但当我指定 COM6 时则不然。这是我的代码的最新版本:

using namespace std;

const char ASCII[ ]= "0123456789ABCDEF";
char *Checksum (char *buffer)
{
static char Hex[10];
static int a1, a2;
register unsigned int i;
int sum;
printf("%s \n", buffer);
sum = 256;
for ( i=0 ; i<strlen(buffer) ; i++ )
{
sum-=buffer[i];
if ( sum<0 )
sum+= 256;
}
a1 = (sum & 0xF0) >> 4;
a2 = sum & 0x0F;
Hex[0] = ASCII[a1];
Hex[1] = ASCII[a2];
Hex[2] = 0;
printf("the checksum is %s \n",Hex);
return(Hex);
}


int main()
{
char data[80], input[80], *data2;
char *response;
DCB dcb;
bool retVal;
DWORD dwBytesTransferred;
DWORD byteswritten;
printf("the variable response is initially: %d\n", response);

dcb.BaudRate = CBR_19200; //19200 Baud
dcb.ByteSize = 8; //8 data bits
dcb.Parity = NOPARITY; //no parity
dcb.StopBits = ONESTOPBIT; //1 stop

//New open port area
HANDLE        hPort;
  if ((hPort = CreateFile ( "\\\\.\\COM6",
      GENERIC_READ | GENERIC_WRITE,
      0,              // exclusive access
      NULL,           // no security attrs
      OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL,
      NULL)) != INVALID_HANDLE_VALUE)
  {
      printf("SUCCESS opening the port\n");// success
  } 
//GetCommState
DCB Dcb;
  GetCommState (hPort, &Dcb);
  Dcb.BaudRate        = CBR_19200;
  Dcb.StopBits        = ONESTOPBIT;
  Dcb.ByteSize        = 8;
  Dcb.Parity          = NOPARITY;
  Dcb.fParity         = 0;
  Dcb.fOutxCtsFlow    = 0;
  Dcb.fOutxDsrFlow    = 0;
  Dcb.fDsrSensitivity = 0;
  Dcb.fTXContinueOnXoff = TRUE;
  Dcb.fOutX           = 0;
  Dcb.fInX            = 0;
  Dcb.fNull           = 0;
  Dcb.fErrorChar      = 0;
  Dcb.fAbortOnError   = 0;
  Dcb.fRtsControl     = RTS_CONTROL_DISABLE;
  Dcb.fDtrControl     = DTR_CONTROL_DISABLE;

//Flushing

FlushFileBuffers( hPort );
  PurgeComm (hPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
  COMSTAT     comStat;
  DWORD       dwErrorFlags;
  ClearCommError ( hPort, &dwErrorFlags, &comStat );

//NEW commtimeouts area
COMMTIMEOUTS CommTimeOuts;
 DWORD dwTimeout = 3000;  // <- set timeout in milliseconds
     if(!dwTimeout)
     {   // Don't use timeout -> Read the bytes already in input buffer and return immediately
         CommTimeOuts.ReadIntervalTimeout      = MAXDWORD;
         CommTimeOuts.ReadTotalTimeoutConstant = 0;
     } else
     {   // Use given timeout, wait until the requested number of bytes are read - or timeout
         CommTimeOuts.ReadIntervalTimeout         = 0;
         CommTimeOuts.ReadTotalTimeoutConstant    = dwTimeout;
     }
     CommTimeOuts.ReadTotalTimeoutMultiplier  = 0;
     CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
     CommTimeOuts.WriteTotalTimeoutConstant   = 0;
     SetCommTimeouts (hPort, &CommTimeOuts);
printf("insert ASCII code string you wish to send:");
scanf("%s", input);
strcpy(data, "{0x02}");
strcat(data, input);
printf("%s \n", data);
data2=Checksum(data);
strcat(data, data2);
strcat(data, "{0x03}");
printf("the final sent message will be: %s \n",data);
retVal = WriteFile(hPort,data, strlen(data), &byteswritten, NULL);
printf("Number of bytes written: %d\n",  byteswritten);
printf("Write Success? %d\n", retVal);
retVal=ReadFile (hPort, &response, 20, &dwBytesTransferred, NULL);
printf("Read Success? %d\n", retVal);
printf("Port Response: %d\n", response);
free(response);
return 0;
}

最新发现总结:使用 Habi 建议的 Free Serial Port Monitor 我现在可以确定 WriteFile 工作正常,并且 COM6 正在接收消息。我仍在寻找交叉电缆来仔细检查消息是否正在通过线路传输。我想,当我试图弄清楚是否有人可以查看这个新版本并告诉我是否有任何问题时,特别是与 ReadFile 函数有关的问题,我将不胜感激。困扰我的是,免费串行端口软件只显示从我的计算机传递的数据,而根本没有来自设备的响应。=\

4

3 回答 3

5

代替

"COM6"

尝试

"\\\\.\\COM6"

我建议使用CreateFile(), ReadFile(), WriteFile().

要打开 COM 端口,请尝试以下操作:

HANDLE        hComDev;

if ((hComDev = CreateFile ( "\\\\.\\COM6",
    GENERIC_READ | GENERIC_WRITE,
    0,              // exclusive access
    NULL,           // no security attrs
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL)) != INVALID_HANDLE_VALUE)
{
      // success
}

您的代码中似乎GetCommState()缺少调用。试试这个来配置 COM 端口:

DCB Dcb;

GetCommState (hComDev, &Dcb); 

Dcb.BaudRate        = CBR_19200;
Dcb.StopBits        = ONESTOPBIT;
Dcb.ByteSize        = 8;
Dcb.Parity          = NOPARITY;
Dcb.fParity         = 0;
Dcb.fOutxCtsFlow    = 0;
Dcb.fOutxDsrFlow    = 0;
Dcb.fDsrSensitivity = 0;
Dcb.fTXContinueOnXoff = TRUE;
Dcb.fOutX           = 0;
Dcb.fInX            = 0;
Dcb.fNull           = 0;
Dcb.fErrorChar      = 0;
Dcb.fAbortOnError   = 0;
Dcb.fRtsControl     = RTS_CONTROL_DISABLE;
Dcb.fDtrControl     = DTR_CONTROL_DISABLE;

为了最初清除 COM 端口,我会在开始发送和接收字节之前进行这样的重置:

FlushFileBuffers( hComDev );

PurgeComm (hComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

COMSTAT     comStat;
DWORD       dwErrorFlags;
ClearCommError ( hComDev, &dwErrorFlags, &comStat );

你要求超时?要配置超时,请尝试以下操作:

COMMTIMEOUTS CommTimeOuts;
DWORD dwTimeout = ....  // <- set timeout in milliseconds

if(!dwTimeout)
{   // Don't use timeout -> Read the bytes already in input buffer and return immediately
    CommTimeOuts.ReadIntervalTimeout      = MAXDWORD;
    CommTimeOuts.ReadTotalTimeoutConstant = 0;
}
else
{   // Use given timeout, wait until the requested number of bytes are read - or timeout
    CommTimeOuts.ReadIntervalTimeout         = 0;
    CommTimeOuts.ReadTotalTimeoutConstant    = dwTimeout;
}
CommTimeOuts.ReadTotalTimeoutMultiplier  = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant   = 0;

SetCommTimeouts (hComDev, &CommTimeOuts);

我的代码应该向设备写入一串 ascii 值,然后读取响应,但是我似乎无法得到任何响应。

你确定字节真的被发送到设备吗?如果您有选择,请使用示波器并监控 PC 的 Tx 线路。发送一些字节并检查波特率和开始/停止位。如果您没有硬件来监视此信号,请使用基于软件的串行监视器,例如Free Serial Port Monitor。我没有使用这种软件工具的经验,但它们至少应该向您展示 Windows 驱动程序试图通过您选择的 COM 端口发送一些东西。

问候哈比

于 2012-08-01T19:05:23.907 回答
0

如果您已经尝试了一个月,那么我建议您查看 windows 函数CreateFile。我已经将它用于串行端口通信,它工作正常。您可能还想查看 DCB 结构GetCommStateSetCommState函数来配置串行端口。WriteFile可用于向串口写入数据。我无法发布我公司拥有的所有代码,但这应该可以帮助您入门。

当您等待读取时,查询串行端口缓冲区中是否有任何数据也ClearCommError可能对您有所帮助。

于 2012-08-01T18:39:39.283 回答
0

我遇到了类似的问题,发现其他答案很有帮助,但我没有收到字符。

最终我发现问题出在 RTS_CONTROL_DISABLE 或 DTR_CONTROL_DISABLE 上。

通过使 RTS 和 DTR 保持低电平,程序向调制解调器/设备指示程序尚未准备好接收数据,并且调制解调器尊重此信号并且尽职尽责地不发送。

通过将这些更改为 RTS_CONTROL_ENABLE 和 DTR_CONTROL_ENABLE,程序向调制解调器指示可以发送数据,并且我开始接收字符。并非所有设备都尊重这些信号,因此它可能在禁用 DTR 和 RTS 的某些配置中工作——调制解调器无论如何都可能发送数据。

于 2016-05-31T15:42:38.920 回答