■ ひさしぶりに使用したら色々悩んだので、このクラスを使う上での注意事項
▼ 読み取りはブロッキングされますので止まりたくなければマルチスレッドにする必要があります。
RS232c*rs=NULL;
_beginthread((void(*)(void*))Thread,0,hDlg);//スレッドのスタート
void Thread(HWND hDlg){ //適当な関数をスレッドにて回します
while(1){
if(rs){
rs->Read_CRLF(buf,1024);
SetWindowText(GetDlgItem(hDlg,IDC_EDIT2),buf);
}
Sleep(1);
}
}
▼ 接続では切断する方法が無いため、deleteする事によりポートをクローズします。
RS232c*rs=NULL;
if(rs != NULL) delete rs;
rs=new RS232c();
rs->Connect(portNo);
■ 接続可能なポートをスキャンする方法
#include <stdio.h>
#include <windows.h>
#include "RS232c.h"
RS232c*rs;
char portNo[32];
int main(){
while(1){
for(int i=0;i<100;i++){
sprintf(portNo,"%d",i);
rs=new RS232c();
if(rs->Connect(portNo)){
printf("Connect :%s\n",portNo);
}
delete rs;
}
printf("------------------\n");
Sleep(1000);
}
return 0;
}
ポートに対して順番に接続を試みる事により接続可能か不可能か判定しています。
■ 使用しているRS232c.h
・修正履歴
2023/08 COM9以降のポートにも接続できるように修正
"COM"を先頭に付けなくても番号(文字)のみでも接続できるように修正
▼ ココから下をRS232c.hとして保存してください。
/////////////////////////////////////////////////////////////////////////
// C++でのRS232c通信クラス
/////////////////////////////////////////////////////////////////////////
//
//このクラスの使い方サンプル
//
//#include "RS232c.h" //このヘッダーを取り込みます。
//
//int _tmain(int argc, _TCHAR* argv[])
//{
// RS232c rs;
// rs.Connect(); //接続します。ここで各種パラメータを設定します。詳しくはインターフェイス参照
// rs.Send("test data"); //文字列を送信 Send(送信文字列)
// char w[100];
// rs.Read(w,100); //文字列の受信 Read(char配列,読み込む文字数)
// //もしくは、
// //rs.Read_CRLF(w,99); //最後にCRLFが付くまで受信 Read_CRLF(char配列,配列サイズ)
// printf(w);
// //クローズする必要はありません、オブジェクトが破棄された時、クローズされます
// getchar();
// return 0;
//}
//////////////////////////////////////////////////////////////////////////
#ifndef _RS_232C_H_
#define _RS_232C_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include <windows.h>
class RS232c{
private:
HANDLE m_hComm;
DWORD size;
DCB m_Dcb;
public:
//各種パラメーターの設定後に接続します。 返り値 TRUE = 成功 FALSE = 失敗
bool Connect(char* PortName, //ポート名を指定します COM1 COM2など、初期値はCOM1 数字部分だけでも可
int BaudRate,//ボーレートを指定します。初期値は 9600
int ByteSize,//1バイトのビット数を指定します。初期値は 8
int Parity,//パリティを指定します。パリティなし: NOPARITY
//偶数パリティ: EVENPARITY
//奇数パリティ: ODDPARITY
//初期値は、パリティなし: NOPARITY
int StopBits,//ストップビット数を指定します。
//1ビット: ONESTOPBIT
//1.5ビット: ONE5STOPBITS
//2ビット: TWOSTOPBITS
//初期値は 1ビット: ONESTOPBIT
int RTS, //RTSをON=RTS_CONTROL_ENABLE 初期値は無効です
int DTR, //DTRをON=DTR_CONTROL_ENABLE 初期値は無効です
int ReadTimeOut,//受信時のタイムアウト msで指定 初期値は 5000ms
int WriteTimeOut//送信時のタイムアウト msで指定 初期値は 20000ms
);
//文字列の受信 Read(char配列,読み込む文字数) 返り値 TRUE = 成功 FALSE = 失敗
bool Read(char* Buff,int NumberOfCharactersToRead);
//文字列の受信 Read_CRLF(char配列,バッファーサイズ) 返り値 TRUE = 成功 FALSE = 失敗
//CRLFをキャッチしたときに受信完了します、読み込み文字列がバッファーサイズをあふれた場合は
//その時点までの文字列しか受信できません
bool Read_CRLF(char* Buff,int NumberOfCharactersToRead);
//文字列を送信 Send(送信文字列) 返り値 TRUE = 成功 FALSE = 失敗
bool Send(char* word);
//接続の状態を取得します
bool RS232c::isLink();
//デストラクタ ポートを閉じます
~RS232c();
};
bool RS232c::Connect(char* PortName="COM1",
int BaudRate = 9600,
int ByteSize = 8,
int Parity = NOPARITY,
int StopBits = ONESTOPBIT,
int RTS = RTS_CONTROL_DISABLE,
int DTR = DTR_CONTROL_DISABLE,
int ReadTimeOut =5000,
int WriteTimeOut = 20000
)
{
//COM10 以上のシリアル ポートにも接続できるように修正 2023/08/22
//番号のみの場合には前に"COM"を付ける
char str[32];
if(PortName[0]=='C'){
strcpy(str,"\\\\.\\");
}else{
strcpy(str,"\\\\.\\COM");
}
strcat(str,PortName);
PortName=str;
//修正終了
m_hComm = CreateFile(
PortName,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0
);
if( m_hComm == INVALID_HANDLE_VALUE ) return FALSE;
// イベントを使用しないようにセットする
SetCommMask( m_hComm, 0 );
// 入出力バッファの許容量設定
SetupComm( m_hComm, 2000L, 2000L );
// タイムアウト情報のセット
COMMTIMEOUTS m_CommTime;
m_CommTime.ReadIntervalTimeout = 0xFFFFFFFF;
m_CommTime.ReadTotalTimeoutMultiplier = 0;
m_CommTime.ReadTotalTimeoutConstant = ReadTimeOut;
m_CommTime.WriteTotalTimeoutMultiplier = 0;
m_CommTime.WriteTotalTimeoutConstant = WriteTimeOut;
// タイムアウトの設定
SetCommTimeouts( m_hComm, &m_CommTime);
// 通信デバイス情報の取得
GetCommState( m_hComm, &m_Dcb );
// 通信デバイス情報の修正
m_Dcb.DCBlength = sizeof( DCB );
m_Dcb.fBinary = FALSE;
m_Dcb.BaudRate = BaudRate;
m_Dcb.ByteSize = ByteSize;
m_Dcb.Parity = Parity;
m_Dcb.StopBits = StopBits;
m_Dcb.fRtsControl = RTS;
m_Dcb.fDtrControl = DTR;
m_Dcb.fDsrSensitivity = FALSE;
m_Dcb.fAbortOnError = FALSE;
m_Dcb.fNull = TRUE;
m_Dcb.fParity =TRUE;
m_Dcb.ErrorChar =0x00;
m_Dcb.fErrorChar = TRUE;
SetCommState( m_hComm, &m_Dcb ) ;
if( !SetCommState( m_hComm, &m_Dcb ) ) return FALSE;
return TRUE;
}
bool RS232c::Read(char* Buff,int NumberOfCharactersToRead){
for(int i=0;i<NumberOfCharactersToRead;i++){
Buff[i]='\0';
}
if(0==ReadFile(m_hComm,Buff,NumberOfCharactersToRead, &size,NULL)){
return FALSE;
}else{
return TRUE;
}
}
bool RS232c::Read_CRLF(char* Buff,int NumberOfCharactersToRead){
for(int i=0;i<NumberOfCharactersToRead;i++){
Buff[i]='\0';
}
char buf[10]="";
char beChar=0x00;
bool flag=TRUE;
int c=0;
while((!(buf[0]==0x0A && beChar==0x0D)) && c<NumberOfCharactersToRead && isLink()){
buf[0]=0x00;
if(0==ReadFile(m_hComm,buf,1, &size,NULL)){
flag=FALSE;
}else{
flag=TRUE;
}
if(buf[0]!=0x00 && flag){
if(c>1) beChar=Buff[c-1];
Buff[c++]=buf[0];
}else{
return FALSE;
}
}
return TRUE;
}
bool RS232c::Send(char* word){
if(0==WriteFile(m_hComm,word,strlen(word),&size, NULL)){
return FALSE;
}else{
return TRUE;
}
}
bool RS232c::isLink(){
if(m_Dcb.fDtrControl == DTR_CONTROL_ENABLE){ //DTRが有効の場合のみ有効
DWORD dwSts;
BOOL fSuccess = GetCommModemStatus( m_hComm, &dwSts ); // 信号ステータスの取得
if( !fSuccess ){
} else {
if(!(dwSts & MS_DSR_ON)) return FALSE; //DSR信号ON
//if(dwSts & MS_CTS_ON) //CTSON
//if(dwSts & MS_RING_ON) //RINGON
if(!(dwSts & MS_RLSD_ON)) return FALSE; //RLSDON
}
}
return TRUE;
}
RS232c::~RS232c(){
//ポートを閉じます
CloseHandle(m_hComm);
}
#endif // _RS_232C_H_
▲トップページ
>
Windows と C++