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が提案した無料のシリアルポートモニターを使用すると、WriteFileが正しく機能しており、COM6がメッセージを受信して​​いることが確実にわかります。メッセージが回線を介して転送されていることを再確認するためのクロスケーブルをまだ探しています。誰かがこの新版を見て、特にReadFile関数に関して何か問題があるかどうかを教えてくれるかどうかを考えながら、私は理解しています。Free Serial Portソフトウェアは、コンピューターから渡されたデータのみを表示し、デバイスからの応答はまったく表示しないのが気になります。= \

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

1か月間試している場合は、Windows関数CreateFileを確認することをお勧めします。私はこれをシリアルポート通信に使用しましたが、正常に動作します。シリアルポートを構成するためのDCB構造体GetCommStateと関数も確認することをお勧めします。シリアルポートにデータを書き込むために使用できます。私の会社が所有しているため、すべてのコードを投稿することはできませんが、これはあなたが始めるのに役立つはずです。SetCommStateWriteFile

また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 に答える