多次写串口导致程序无故退出,自己找不出原因!!!(附代码)请教高手,已经搞了一个星期了,在线等。。。

时间:2022-09-27 18:22:59
代码比较长,希望高手可以耐心点看,多谢了!

串口类头文件:
// CESeries.h: interface for the CCESeries class.
//
//////////////////////////////////////////////////////////////////////

typedef void (CALLBACK* ONSERIESREAD)(CWnd*,BYTE* buf,int bufLen);

class CCESeries
{

public:
CCESeries();
virtual ~CCESeries();
public:
BOOL OpenPort(CWnd* pPortOwner,
  UINT portNo = 1,
  UINT baud = 9600,
  UINT parity = NOPARITY,
  UINT databits = 8,
  UINT stopbits = 0     
  );

void ClosePort();

BOOL SetSeriesTimeouts(COMMTIMEOUTS CommTimeOuts);

BOOL WritePort(const BYTE *buf,DWORD bufLen);
private:
    
    static  DWORD WINAPI ReadThreadFunc(LPVOID lparam);

    static DWORD WINAPI WriteThreadFunc(LPVOID lparam);

static BOOL WritePort(HANDLE hComm,const BYTE *buf,DWORD bufLen);

void CloseReadThread();

void CloseWriteThread();
private:

HANDLE m_hComm;
CWnd* m_pPortOwner;

HANDLE m_hReadThread;
HANDLE m_hWriteThread;

DWORD m_dwReadThreadID;
DWORD m_dwWriteThreadID;

HANDLE m_hReadCloseEvent;
HANDLE m_hWriteCloseEvent;
public:
ONSERIESREAD m_OnSeriesRead; 
ONSERIESREAD m_OnSeriesRead2;
};


串口类源文件,相关实现部分:
// CESeries.cpp: implementation of the CCESeries class.
//
//////////////////////////////////////////////////////////////////////
const int CM_THREADCOMMWRITE = WM_USER+110;//写串口消息

//打开串口并初始化;
BOOL CCESeries::OpenPort(CWnd* pPortOwner,
 UINT portNo ,
 UINT baud ,
 UINT parity ,
 UINT databits ,
 UINT stopbits
 )
{
................设置串口部分省略..........
m_hReadCloseEvent = CreateEvent(NULL,FALSE,FALSE,NULL);//TRUE
m_hWriteCloseEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
m_hReadThread = CreateThread(NULL,0,ReadThreadFunc,this,0,&m_dwReadThreadID);//Run thread immediately after creating.
m_hWriteThread = CreateThread(NULL,0,WriteThreadFunc,this,0,&m_dwWriteThreadID);
return TRUE;
}

xxxDlg.cpp中通过调用此函数来发送“写串口”消息
BOOL CCESeries::WritePort(const BYTE *buf,DWORD bufLen)  //-------------------------------------(1)
{
if (PostThreadMessage(m_dwWriteThreadID,CM_THREADCOMMWRITE,
WPARAM(bufLen), LPARAM(buf)))
{
return TRUE;
}
return FALSE;
}

监控并接收写串口消息CM_THREADCOMMWRITE,并调用(3)函数
DWORD CCESeries::WriteThreadFunc(LPVOID lparam)   //--------------------------------------------(2)
{
CCESeries *ceSeries = (CCESeries*)lparam;
MSG msg;
DWORD dwWriteLen = 0;
BYTE * buf = NULL;

while (TRUE)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (msg.hwnd != 0 )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
if (msg.message == CM_THREADCOMMWRITE)
{
buf = (BYTE*)msg.lParam;
dwWriteLen = msg.wParam;
WritePort(ceSeries->m_hComm,buf,dwWriteLen); //-----------调用(3)
delete[] buf;
}
}

if (WaitForSingleObject(ceSeries->m_hWriteCloseEvent,500) == WAIT_OBJECT_0)// WAIT_TIMEOUT WAIT_OBJECT_0
{
break;
}
ceSeries->m_hWriteThread = NULL;
}
return 0;
}

直接向串口写命令的函数
BOOL CCESeries::WritePort(HANDLE hComm,const BYTE *buf,DWORD bufLen) //----------------------------(3)
{
DWORD dwNumBytesWritten;
DWORD dwHaveNumWritten =0 ; 

ASSERT(hComm != INVALID_HANDLE_VALUE);
do
{
if (WriteFile (hComm,
buf+dwHaveNumWritten,
bufLen - dwHaveNumWritten,          
&dwNumBytesWritten,
NULL))
{
dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;

if (dwHaveNumWritten == bufLen)
{
break;
}
Sleep(10);
}
else
{
return FALSE;
}
}while (TRUE);

return TRUE;
}

下面部分是调用(1)的xxxDlg.cpp文件的“写串口”按钮事件内容:
void CMFCWinCEDlg::OnBnClickedMfg()
{
BYTE buf1[]={0x44,0x69,0x72,0x65,0x63,0x74,0x42,0x61,0x6E,0x64,0x20,0x4F,0x4B}; //DirectBand OK
BYTE buf2[]={0x10,0x01,0xDF,0xED,0x84,0xC5,0x01,0x00,0x0B,0x00,0x00,0x05,0x00,0x00,0x10,0x03};
BYTE buf3[]={0x10,0x01,0xB0,0xA7,0xA6,0x77,0x01,0x00,0x0B,0x00,0x01,0x0B,0x00,0x00,0x10,0x03};
BYTE buf4[]={0x0D};
BYTE bufTemp[]={0x00};
HWND hRecvEdit = ::GetDlgItem(this->GetSafeHwnd(), IDC_EDIT_RECV);
WriteFlag = nEnterMFG;//set write flag as EnterMFG.
if (!m_ceSeries.WritePort(buf1,13))
{
OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command failed.");
return;
}
OutputString(hRecvEdit,L"\r\nCommand 1 OK.");  //---------(4)

Sleep(1000);
if (!m_ceSeries.WritePort(buf2,16))
{
OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command failed.\r\n");
return;
}
OutputString(hRecvEdit,L"\r\nCommand 2 OK.");  //--------(5)

Sleep(1000);             
if (!m_ceSeries.WritePort(buf3,16))
{
OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command failed.\r\n");
return;
}
OutputString(hRecvEdit,L"\r\nCommand 3 OK.");//----------(6)


Sleep(1000);
OutputString(hRecvEdit,L"\r\nCommand 4 OK.");//----------(7)
if (!m_ceSeries.WritePort(buf4,1))
{
OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command failed.\r\n");
return;

OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command ok.\r\n");
OutputString(hRecvEdit,L"\r\nWaiting for receiver to reboot ...\r\n"); 
}
调用这里是,可以显示出(4),(5),(6)的信息,
(7)的信息显示不出系统就自动退出了很是郁闷。

代码比较长,希望高手可以耐心点看,多谢了!

19 个解决方案

#1


CSDN有点很不好,写了半天,不注意按了一个什么按钮,全没了,
Ctrl+Z又不能撤销操作,

害得俺又重写一遍。

#2


你在每个OutputString后面都加一个Sleep看看执行结果是否相同。

#3


代码比较长,用C++效果重发一遍,希望高手可以耐心点看,多谢了!

串口类头文件:

// CESeries.h: interface for the CCESeries class.
//
//////////////////////////////////////////////////////////////////////

typedef void (CALLBACK* ONSERIESREAD)(CWnd*,BYTE* buf,int bufLen);

class CCESeries
{

public:
CCESeries();
virtual ~CCESeries();
public:
BOOL OpenPort(CWnd* pPortOwner,
  UINT portNo = 1,
  UINT baud = 9600,
  UINT parity = NOPARITY,
  UINT databits = 8,
  UINT stopbits = 0     
  );

void ClosePort();

BOOL SetSeriesTimeouts(COMMTIMEOUTS CommTimeOuts);

BOOL WritePort(const BYTE *buf,DWORD bufLen);
private:
    
    static  DWORD WINAPI ReadThreadFunc(LPVOID lparam);

    static DWORD WINAPI WriteThreadFunc(LPVOID lparam);

static BOOL WritePort(HANDLE hComm,const BYTE *buf,DWORD bufLen);

void CloseReadThread();

void CloseWriteThread();
private:

HANDLE m_hComm;
CWnd* m_pPortOwner;

HANDLE m_hReadThread;
HANDLE m_hWriteThread;

DWORD m_dwReadThreadID;
DWORD m_dwWriteThreadID;

HANDLE m_hReadCloseEvent;
HANDLE m_hWriteCloseEvent;
public:
ONSERIESREAD m_OnSeriesRead; 
ONSERIESREAD m_OnSeriesRead2;
};




串口类源文件,相关实现部分:

// CESeries.cpp: implementation of the CCESeries class.
//
//////////////////////////////////////////////////////////////////////
const int CM_THREADCOMMWRITE = WM_USER+110;//写串口消息


//打开串口并初始化;

BOOL CCESeries::OpenPort(CWnd* pPortOwner,
 UINT portNo ,
 UINT baud ,
 UINT parity ,
 UINT databits ,
 UINT stopbits
 )
{
................设置串口部分省略..........
m_hReadCloseEvent = CreateEvent(NULL,FALSE,FALSE,NULL);//TRUE
m_hWriteCloseEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
m_hReadThread = CreateThread(NULL,0,ReadThreadFunc,this,0,&m_dwReadThreadID);//Run thread immediately after creating.
m_hWriteThread = CreateThread(NULL,0,WriteThreadFunc,this,0,&m_dwWriteThreadID);
return TRUE;
}





xxxDlg.cpp中通过调用此函数来发送“写串口”消息

BOOL CCESeries::WritePort(const BYTE *buf,DWORD bufLen)  //-------------------------------------(1)
{
if (PostThreadMessage(m_dwWriteThreadID,CM_THREADCOMMWRITE,
WPARAM(bufLen), LPARAM(buf)))
{
return TRUE;
}
return FALSE;
}




监控并接收写串口消息CM_THREADCOMMWRITE,并调用(3)函数

DWORD CCESeries::WriteThreadFunc(LPVOID lparam)   //--------------------------------------------(2)
{
CCESeries *ceSeries = (CCESeries*)lparam;
MSG msg;
DWORD dwWriteLen = 0;
BYTE * buf = NULL;

while (TRUE)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (msg.hwnd != 0 )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
if (msg.message == CM_THREADCOMMWRITE)
{
buf = (BYTE*)msg.lParam;
dwWriteLen = msg.wParam;
WritePort(ceSeries->m_hComm,buf,dwWriteLen); //-----------调用(3)
delete[] buf;
}
}

if (WaitForSingleObject(ceSeries->m_hWriteCloseEvent,500) == WAIT_OBJECT_0)// WAIT_TIMEOUT WAIT_OBJECT_0
{
break;
}
ceSeries->m_hWriteThread = NULL;
}
return 0;
}




直接向串口写命令的函数


BOOL CCESeries::WritePort(HANDLE hComm,const BYTE *buf,DWORD bufLen) //----------------------------(3)
{
DWORD dwNumBytesWritten;
DWORD dwHaveNumWritten =0 ; 

ASSERT(hComm != INVALID_HANDLE_VALUE);
do
{
if (WriteFile (hComm,
buf+dwHaveNumWritten,
bufLen - dwHaveNumWritten,          
&dwNumBytesWritten,
NULL))
{
dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;

if (dwHaveNumWritten == bufLen)
{
break;
}
Sleep(10);
}
else
{
return FALSE;
}
}while (TRUE);

return TRUE;
}





下面部分是调用(1)的xxxDlg.cpp文件的“写串口”按钮事件内容:


void CMFCWinCEDlg::OnBnClickedMfg()
{
BYTE buf1[]={0x44,0x69,0x72,0x65,0x63,0x74,0x42,0x61,0x6E,0x64,0x20,0x4F,0x4B}; //DirectBand OK
BYTE buf2[]={0x10,0x01,0xDF,0xED,0x84,0xC5,0x01,0x00,0x0B,0x00,0x00,0x05,0x00,0x00,0x10,0x03};
BYTE buf3[]={0x10,0x01,0xB0,0xA7,0xA6,0x77,0x01,0x00,0x0B,0x00,0x01,0x0B,0x00,0x00,0x10,0x03};
BYTE buf4[]={0x0D};
BYTE bufTemp[]={0x00};
HWND hRecvEdit = ::GetDlgItem(this->GetSafeHwnd(), IDC_EDIT_RECV);
WriteFlag = nEnterMFG;//set write flag as EnterMFG.
if (!m_ceSeries.WritePort(buf1,13))
{
OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command failed.");
return;
}
OutputString(hRecvEdit,L"\r\nCommand 1 OK.");  //---------(4)

Sleep(1000);
if (!m_ceSeries.WritePort(buf2,16))
{
OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command failed.\r\n");
return;
}
OutputString(hRecvEdit,L"\r\nCommand 2 OK.");  //--------(5)

Sleep(1000);             
if (!m_ceSeries.WritePort(buf3,16))
{
OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command failed.\r\n");
return;
}
OutputString(hRecvEdit,L"\r\nCommand 3 OK.");//----------(6)


Sleep(1000);
OutputString(hRecvEdit,L"\r\nCommand 4 OK.");//----------(7)
if (!m_ceSeries.WritePort(buf4,1))
{
OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command failed.\r\n");
return;

OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command ok.\r\n");
OutputString(hRecvEdit,L"\r\nWaiting for receiver to reboot ...\r\n"); 
}


调用这里是,可以显示出(4),(5),(6)的信息,
(7)的信息显示不出系统就自动退出了很是郁闷。


代码比较长,希望高手可以耐心点看,多谢了!

#4


已经加了啊,效果一样,

#5


多谢cnzdgs 的回复,
OutputString函数的内容如下,
主要是往CEdit里写一些提示信息。



#define nTempBuf 20000    //The maximum number of characters allowed is STRSAFE_MAX_CCH.
#define nExitMFG  5
#define nListen   0
//......

TCHAR TempBuf[nTempBuf];
bool FirstOutput;
unsigned int WriteFlag=0; //

void OutputString(HWND hRecvEdit, TCHAR *Str)
{  
if (FirstOutput)
{
StringCchPrintf(TempBuf, nTempBuf, Str);
FirstOutput = false;
}
else
{
int CurLen = wcslen(TempBuf);
int StrLen = wcslen(Str);

// Append or overwrite?
if (CurLen + StrLen > nTempBuf - 1)
{
memcpy(TempBuf, TempBuf + (StrLen+1)*2, (CurLen-(StrLen+1)+1)*2);
}

StringCchCat(TempBuf, nTempBuf, Str);
}
// Set the new text
SendMessage(hRecvEdit, WM_SETTEXT, 0, (LPARAM )TempBuf);
::SendMessage(hRecvEdit,EM_LINESCROLL,nTempBuf,(int)::SendMessage(hRecvEdit,EM_GETLINECOUNT,0,0));

#6


在(7)之前GetLastError()试试,看看是不是已经出错了

#7


把CCESeries::WriteThreadFunc中的delete去掉,最好把BYTE buf1[](2、3、4)都定义为全局量并在前面加上const。

#8


写串口为啥还要开个线程?麻烦又不方便调试。

#9


为什么每次都delete啊?写程序写大方点,用数组不是挺好的吗?

#10


delete[] buf;
后加上buf = NULL;

看看

实在看不出哪错了,自动退出应该是内存错误

#11


感觉你的程序吧,...........,问题之一就是delete局部数组变量了。

#12


多谢各位的回复!

如果在xxxDlg.cpp中写一函数直接对串口写数据,该如何写?

#13


因为HANDLE    m_hComm;
是private成员,
不知道如何在外部调用,希望大家提点一下,

#14


写个函数如GetHandle将m_hComm开放出去不就行了

#15


多谢Jennyvenus,试试,

#16


非常感谢Jennyvenus,youyingbo,

你们说的对,写串口没必要用线程,
感谢各位!

揭帖了。

#17


虽然揭帖了,
但是还想请问一下这个写串口的函数有没有问题?
现在发现一奇怪现象:如果先点击A按钮去的发A命令,
然后再点击B按钮去发B命令,
但是,点击完B之后,本来应该是发B命令的,但是却发了A命令,
排除代码写错的原因了,
这是为什么?

BOOL CCESeries::WriteCommData(HANDLE hComm,const BYTE *buf,DWORD bufLen)//Add 20080219
{
DWORD dwNumBytesWritten;
DWORD dwHaveNumWritten =0 ; 

ASSERT(hComm != INVALID_HANDLE_VALUE);
do
{
if (WriteFile (hComm,
buf+dwHaveNumWritten,
bufLen - dwHaveNumWritten,          
&dwNumBytesWritten,
NULL))
{
dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;

if (dwHaveNumWritten == bufLen)
{
break;
}
Sleep(10);
}
else
{
return FALSE;
}
}while (TRUE);

return TRUE;
}

#18


等我看看,估计是你传的指针错了。

#19


//你这段程序本身没有大的问题,不过你的逻辑可能得不到完全实现
BOOL CCESeries::WriteCommData(HANDLE hComm,const BYTE *buf,DWORD bufLen)//Add 20080219
{
    DWORD dwNumBytesWritten;
    DWORD dwHaveNumWritten =0 ; 
    
    ASSERT(hComm != INVALID_HANDLE_VALUE);
    do //用do循环表明你想将大数据块分批写串口
    {
        if (WriteFile (hComm,                    
            buf+dwHaveNumWritten,               //起始地址没有问题
            bufLen - dwHaveNumWritten,          //长度并没有合理控制,比如第一次执行,bufLen - dwHaveNumWritten就是bufLen,理论上就将全部数据都写进去了
            &dwNumBytesWritten,                 //这并没有错   
            NULL))                                
        {
            dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;
            
            if (dwHaveNumWritten == bufLen)
            {
                break;
            }
            Sleep(10);
        }
        else
        {
            return FALSE;
        }
    }while (TRUE);
    
    return TRUE;        
}

//这段函数本身应该是没问题的

#1


CSDN有点很不好,写了半天,不注意按了一个什么按钮,全没了,
Ctrl+Z又不能撤销操作,

害得俺又重写一遍。

#2


你在每个OutputString后面都加一个Sleep看看执行结果是否相同。

#3


代码比较长,用C++效果重发一遍,希望高手可以耐心点看,多谢了!

串口类头文件:

// CESeries.h: interface for the CCESeries class.
//
//////////////////////////////////////////////////////////////////////

typedef void (CALLBACK* ONSERIESREAD)(CWnd*,BYTE* buf,int bufLen);

class CCESeries
{

public:
CCESeries();
virtual ~CCESeries();
public:
BOOL OpenPort(CWnd* pPortOwner,
  UINT portNo = 1,
  UINT baud = 9600,
  UINT parity = NOPARITY,
  UINT databits = 8,
  UINT stopbits = 0     
  );

void ClosePort();

BOOL SetSeriesTimeouts(COMMTIMEOUTS CommTimeOuts);

BOOL WritePort(const BYTE *buf,DWORD bufLen);
private:
    
    static  DWORD WINAPI ReadThreadFunc(LPVOID lparam);

    static DWORD WINAPI WriteThreadFunc(LPVOID lparam);

static BOOL WritePort(HANDLE hComm,const BYTE *buf,DWORD bufLen);

void CloseReadThread();

void CloseWriteThread();
private:

HANDLE m_hComm;
CWnd* m_pPortOwner;

HANDLE m_hReadThread;
HANDLE m_hWriteThread;

DWORD m_dwReadThreadID;
DWORD m_dwWriteThreadID;

HANDLE m_hReadCloseEvent;
HANDLE m_hWriteCloseEvent;
public:
ONSERIESREAD m_OnSeriesRead; 
ONSERIESREAD m_OnSeriesRead2;
};




串口类源文件,相关实现部分:

// CESeries.cpp: implementation of the CCESeries class.
//
//////////////////////////////////////////////////////////////////////
const int CM_THREADCOMMWRITE = WM_USER+110;//写串口消息


//打开串口并初始化;

BOOL CCESeries::OpenPort(CWnd* pPortOwner,
 UINT portNo ,
 UINT baud ,
 UINT parity ,
 UINT databits ,
 UINT stopbits
 )
{
................设置串口部分省略..........
m_hReadCloseEvent = CreateEvent(NULL,FALSE,FALSE,NULL);//TRUE
m_hWriteCloseEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
m_hReadThread = CreateThread(NULL,0,ReadThreadFunc,this,0,&m_dwReadThreadID);//Run thread immediately after creating.
m_hWriteThread = CreateThread(NULL,0,WriteThreadFunc,this,0,&m_dwWriteThreadID);
return TRUE;
}





xxxDlg.cpp中通过调用此函数来发送“写串口”消息

BOOL CCESeries::WritePort(const BYTE *buf,DWORD bufLen)  //-------------------------------------(1)
{
if (PostThreadMessage(m_dwWriteThreadID,CM_THREADCOMMWRITE,
WPARAM(bufLen), LPARAM(buf)))
{
return TRUE;
}
return FALSE;
}




监控并接收写串口消息CM_THREADCOMMWRITE,并调用(3)函数

DWORD CCESeries::WriteThreadFunc(LPVOID lparam)   //--------------------------------------------(2)
{
CCESeries *ceSeries = (CCESeries*)lparam;
MSG msg;
DWORD dwWriteLen = 0;
BYTE * buf = NULL;

while (TRUE)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (msg.hwnd != 0 )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
if (msg.message == CM_THREADCOMMWRITE)
{
buf = (BYTE*)msg.lParam;
dwWriteLen = msg.wParam;
WritePort(ceSeries->m_hComm,buf,dwWriteLen); //-----------调用(3)
delete[] buf;
}
}

if (WaitForSingleObject(ceSeries->m_hWriteCloseEvent,500) == WAIT_OBJECT_0)// WAIT_TIMEOUT WAIT_OBJECT_0
{
break;
}
ceSeries->m_hWriteThread = NULL;
}
return 0;
}




直接向串口写命令的函数


BOOL CCESeries::WritePort(HANDLE hComm,const BYTE *buf,DWORD bufLen) //----------------------------(3)
{
DWORD dwNumBytesWritten;
DWORD dwHaveNumWritten =0 ; 

ASSERT(hComm != INVALID_HANDLE_VALUE);
do
{
if (WriteFile (hComm,
buf+dwHaveNumWritten,
bufLen - dwHaveNumWritten,          
&dwNumBytesWritten,
NULL))
{
dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;

if (dwHaveNumWritten == bufLen)
{
break;
}
Sleep(10);
}
else
{
return FALSE;
}
}while (TRUE);

return TRUE;
}





下面部分是调用(1)的xxxDlg.cpp文件的“写串口”按钮事件内容:


void CMFCWinCEDlg::OnBnClickedMfg()
{
BYTE buf1[]={0x44,0x69,0x72,0x65,0x63,0x74,0x42,0x61,0x6E,0x64,0x20,0x4F,0x4B}; //DirectBand OK
BYTE buf2[]={0x10,0x01,0xDF,0xED,0x84,0xC5,0x01,0x00,0x0B,0x00,0x00,0x05,0x00,0x00,0x10,0x03};
BYTE buf3[]={0x10,0x01,0xB0,0xA7,0xA6,0x77,0x01,0x00,0x0B,0x00,0x01,0x0B,0x00,0x00,0x10,0x03};
BYTE buf4[]={0x0D};
BYTE bufTemp[]={0x00};
HWND hRecvEdit = ::GetDlgItem(this->GetSafeHwnd(), IDC_EDIT_RECV);
WriteFlag = nEnterMFG;//set write flag as EnterMFG.
if (!m_ceSeries.WritePort(buf1,13))
{
OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command failed.");
return;
}
OutputString(hRecvEdit,L"\r\nCommand 1 OK.");  //---------(4)

Sleep(1000);
if (!m_ceSeries.WritePort(buf2,16))
{
OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command failed.\r\n");
return;
}
OutputString(hRecvEdit,L"\r\nCommand 2 OK.");  //--------(5)

Sleep(1000);             
if (!m_ceSeries.WritePort(buf3,16))
{
OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command failed.\r\n");
return;
}
OutputString(hRecvEdit,L"\r\nCommand 3 OK.");//----------(6)


Sleep(1000);
OutputString(hRecvEdit,L"\r\nCommand 4 OK.");//----------(7)
if (!m_ceSeries.WritePort(buf4,1))
{
OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command failed.\r\n");
return;

OutputString(hRecvEdit,L"\r\nSend Entering Manufacturing Mode command ok.\r\n");
OutputString(hRecvEdit,L"\r\nWaiting for receiver to reboot ...\r\n"); 
}


调用这里是,可以显示出(4),(5),(6)的信息,
(7)的信息显示不出系统就自动退出了很是郁闷。


代码比较长,希望高手可以耐心点看,多谢了!

#4


已经加了啊,效果一样,

#5


多谢cnzdgs 的回复,
OutputString函数的内容如下,
主要是往CEdit里写一些提示信息。



#define nTempBuf 20000    //The maximum number of characters allowed is STRSAFE_MAX_CCH.
#define nExitMFG  5
#define nListen   0
//......

TCHAR TempBuf[nTempBuf];
bool FirstOutput;
unsigned int WriteFlag=0; //

void OutputString(HWND hRecvEdit, TCHAR *Str)
{  
if (FirstOutput)
{
StringCchPrintf(TempBuf, nTempBuf, Str);
FirstOutput = false;
}
else
{
int CurLen = wcslen(TempBuf);
int StrLen = wcslen(Str);

// Append or overwrite?
if (CurLen + StrLen > nTempBuf - 1)
{
memcpy(TempBuf, TempBuf + (StrLen+1)*2, (CurLen-(StrLen+1)+1)*2);
}

StringCchCat(TempBuf, nTempBuf, Str);
}
// Set the new text
SendMessage(hRecvEdit, WM_SETTEXT, 0, (LPARAM )TempBuf);
::SendMessage(hRecvEdit,EM_LINESCROLL,nTempBuf,(int)::SendMessage(hRecvEdit,EM_GETLINECOUNT,0,0));

#6


在(7)之前GetLastError()试试,看看是不是已经出错了

#7


把CCESeries::WriteThreadFunc中的delete去掉,最好把BYTE buf1[](2、3、4)都定义为全局量并在前面加上const。

#8


写串口为啥还要开个线程?麻烦又不方便调试。

#9


为什么每次都delete啊?写程序写大方点,用数组不是挺好的吗?

#10


delete[] buf;
后加上buf = NULL;

看看

实在看不出哪错了,自动退出应该是内存错误

#11


感觉你的程序吧,...........,问题之一就是delete局部数组变量了。

#12


多谢各位的回复!

如果在xxxDlg.cpp中写一函数直接对串口写数据,该如何写?

#13


因为HANDLE    m_hComm;
是private成员,
不知道如何在外部调用,希望大家提点一下,

#14


写个函数如GetHandle将m_hComm开放出去不就行了

#15


多谢Jennyvenus,试试,

#16


非常感谢Jennyvenus,youyingbo,

你们说的对,写串口没必要用线程,
感谢各位!

揭帖了。

#17


虽然揭帖了,
但是还想请问一下这个写串口的函数有没有问题?
现在发现一奇怪现象:如果先点击A按钮去的发A命令,
然后再点击B按钮去发B命令,
但是,点击完B之后,本来应该是发B命令的,但是却发了A命令,
排除代码写错的原因了,
这是为什么?

BOOL CCESeries::WriteCommData(HANDLE hComm,const BYTE *buf,DWORD bufLen)//Add 20080219
{
DWORD dwNumBytesWritten;
DWORD dwHaveNumWritten =0 ; 

ASSERT(hComm != INVALID_HANDLE_VALUE);
do
{
if (WriteFile (hComm,
buf+dwHaveNumWritten,
bufLen - dwHaveNumWritten,          
&dwNumBytesWritten,
NULL))
{
dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;

if (dwHaveNumWritten == bufLen)
{
break;
}
Sleep(10);
}
else
{
return FALSE;
}
}while (TRUE);

return TRUE;
}

#18


等我看看,估计是你传的指针错了。

#19


//你这段程序本身没有大的问题,不过你的逻辑可能得不到完全实现
BOOL CCESeries::WriteCommData(HANDLE hComm,const BYTE *buf,DWORD bufLen)//Add 20080219
{
    DWORD dwNumBytesWritten;
    DWORD dwHaveNumWritten =0 ; 
    
    ASSERT(hComm != INVALID_HANDLE_VALUE);
    do //用do循环表明你想将大数据块分批写串口
    {
        if (WriteFile (hComm,                    
            buf+dwHaveNumWritten,               //起始地址没有问题
            bufLen - dwHaveNumWritten,          //长度并没有合理控制,比如第一次执行,bufLen - dwHaveNumWritten就是bufLen,理论上就将全部数据都写进去了
            &dwNumBytesWritten,                 //这并没有错   
            NULL))                                
        {
            dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;
            
            if (dwHaveNumWritten == bufLen)
            {
                break;
            }
            Sleep(10);
        }
        else
        {
            return FALSE;
        }
    }while (TRUE);
    
    return TRUE;        
}

//这段函数本身应该是没问题的