串口通讯死机现象

wqm_44944 2007-10-10 12:05:19
我的系统出现死机现象:打开应用程序(EVC开发)通过串口与控制器通讯。刚开始没有问题。应用程序发出命令后,控制器收到后解析并响应请求。通讯一段时间后系统出现死机现象。但是,当我把控制器断电重启一下,这时候系统又好了。通讯一段时间又死机了。这是怎么回事??谁遇到过这种情况!救救我!(我确定控制器没问题,我用.net 开发的应用与其通讯一直没问题) 我的板子是2410开发板。硬件应该没问题。平台为wince 4.2
...全文
1567 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiuzhoulh 2011-10-30
  • 打赏
  • 举报
回复
串口是全双工通信的
huanghaihe 2008-08-01
  • 打赏
  • 举报
回复
请教高手,我采用电脑测试DVB-S串口,老是烧坏主板,请问是什么原因并怎么处理才能防止主板烧坏?谢谢!
wqm_44944 2007-10-22
  • 打赏
  • 举报
回复
都能成功!现在问题解决了,应该是因为控制器与我的开发串口配置参数不一致造成了死机!同时我把发送线程去掉了。现在通讯都没问题了。请问应该程序当中最多可以打开几个定时器?
lenux 2007-10-19
  • 打赏
  • 举报
回复
我用2,3 短接的通讯线测试的时候,我的程序没问题!

2,3短接后你的发送和接受数据还都能成功吗?
lenux 2007-10-19
  • 打赏
  • 举报
回复
发现你的两个线程的读和写的两个操作之间没有设同步机制,你能保证两个操作不会同时发生吗?
KevinCEC 2007-10-18
  • 打赏
  • 举报
回复
ce支持的串口通信只能同步通信的
wqm_44944 2007-10-18
  • 打赏
  • 举报
回复
我用就是同步方式啊!
canjiu 2007-10-17
  • 打赏
  • 举报
回复
我以前遇到的串口死机问题是底层驱动问题,本来就是调驱动的.屏蔽掉驱动的一个函数就不死机了,你好像是做应用程序的,不知你的问题.若是底层驱动问题可与我交流.
wqm_44944 2007-10-12
  • 打赏
  • 举报
回复
我用2,3 短接的通讯线测试的时候,我的程序没问题!
lenux 2007-10-12
  • 打赏
  • 举报
回复
兄弟,你读串口和写串口的线程单独分开跑测试情况怎么样了。
我没有你的设备只能靠你的反馈来判断啊。
你的问题可能不是原则上的,需要细心调试。
wqm_44944 2007-10-12
  • 打赏
  • 举报
回复
大家帮忙想想办法,分不够可以再加!
lenux 2007-10-10
  • 打赏
  • 举报
回复
if (WaitForSingleObject(ceSeries- >m_hReadCloseEvent,500) == WAIT_OBJECT_0)

等待退出的时间太长了,有个1个毫秒就够了。

明天再来看吧。代码好像有问题啊
//清空串口
PurgeComm(ceSeries- >m_hComm,PURGE_RXCLEAR ¦ PURGE_TXCLEAR);
每读一次串口都要清一下吗?
happytt 2007-10-10
  • 打赏
  • 举报
回复
我也是前两天解决这个问题的,代码其实都差不多,只是我只有读,没有写.
可能就像楼上说的,你用单个来测试看看
lenux 2007-10-10
  • 打赏
  • 举报
回复
晕啊,lz
你先只读串口,不写。看出问题不。
然后再看只写串口,不读。看出问题不。

要是单个跑可以,同时跑不行,就是同步处理出问题了。单看代码好累得。
wqm_44944 2007-10-10
  • 打赏
  • 举报
回复
这我通讯部分的全部代码?请大家帮我看看是那里的问题!
wqm_44944 2007-10-10
  • 打赏
  • 举报
回复
// CSeries.h: interface for the CCSeries class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_CSERIES_H__2DB1AAE2_F6D9_4320_8421_69FAF7A70B87__INCLUDED_)
#define AFX_CSERIES_H__2DB1AAE2_F6D9_4320_8421_69FAF7A70B87__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

typedef unsigned int UNIT;

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

typedef struct
{
BYTE FunNO; //功能码
BYTE StartNO; //开始变量号
BYTE Length; //长度
int Data[8]; //要传输的数据
//BYTE Coefficient; //系数
//int OffSet; //偏移量
BYTE ReturnLen; //返回长度
}STRBUF;
class CCSeries
{
public:
CCSeries();
virtual ~CCSeries();

private:
//关闭写线程
void CloseWriteThread();
//关闭读线程
void CloseReadThread();
//串口写线程函数
static DWORD WINAPI WriteThreadFunc(LPVOID lparam);
//串口读线程函数
static DWORD WINAPI ReadThreadFunc(LPVOID lparam);
//向串口写入数据
static BOOL WritePort(HANDLE hComm,const BYTE *buf,DWORD bufLen);

//已打开的串口句柄
HANDLE m_hComm;
CWnd* m_pPortOwner;

//读写线程句柄
HANDLE m_hReadThread;
HANDLE m_hWriteThread;

//读写线程ID标识
DWORD m_dwReadThreadID;
DWORD m_dwWriteThreadID;

//读写线程退出事件
HANDLE m_hReadCloseEvent;
HANDLE m_hWriteCloseEvent;

public:
CString m_strRecvData;
BOOL SetSeriesTimeOuts(COMMTIMEOUTS CommTimeOuts);
BOOL WritePort(const BYTE *buf,DWORD bufLen);
void ClosePort();
//以指定的参数打开串口
BOOL OpenPort(CWnd* pProtOwner,UNIT portno = 1,UNIT baud = 19200,UNIT parity = NOPARITY,UNIT databits = 8,UNIT stopbits = 0);
//回调事件
ONSERIESREAD m_OnSeriesRead;
//灭菌参数集合
static BYTE auchByte[256];
static int auiWord[256];
//读写队列
static STRBUF WriteBuf[5];
static STRBUF ReadBuf[50];
//读写缓冲区头尾指针
static BYTE WriteBufFront;
static BYTE WriteBufRear;
static BYTE ReadBufFront;
static BYTE ReadBufRear;
//入队操作
static void EnQueue(BYTE FunNO,BYTE StartNO,BYTE Length,int *Data,BYTE PossessionMark);
static BYTE CalcReturnLen(BYTE FunNO,BYTE Len);

static char NSYL[20];
static char NSWD[20];
static char JCYL[20];
static char JCWD[20];
static char DateTime[30];
};

#endif // !defined(AFX_CSERIES_H__2DB1AAE2_F6D9_4320_8421_69FAF7A70B87__INCLUDED_)
wqm_44944 2007-10-10
  • 打赏
  • 举报
回复

// CSeries.cpp: implementation of the CCSeries class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "SeriesComm.h"
#include "CSeries.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
const CM_THREADCOMMWRITE = WM_USER + 110;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCSeries::CCSeries()
{
m_hComm = INVALID_HANDLE_VALUE;
}

CCSeries::~CCSeries()
{

}
BOOL CCSeries::WritePort(HANDLE hComm, const BYTE *buf, DWORD bufLen)
{
DWORD dwNumBytesWritten = 0;
DWORD dw_HaveNumWritten = 0;

ASSERT(hComm != INVALID_HANDLE_VALUE);
//清空串口
PurgeComm(hComm,PURGE_RXCLEAR | PURGE_TXCLEAR);
do
{
if(WriteFile(hComm,buf + dw_HaveNumWritten,bufLen - dw_HaveNumWritten,&dwNumBytesWritten,NULL))
{
dw_HaveNumWritten = dw_HaveNumWritten + dwNumBytesWritten;
//写入完成
if (dw_HaveNumWritten == bufLen)
{
break;
}
Sleep(10);
}
else
{
AfxMessageBox(_T("write failed."));
return FALSE;
}
}while(TRUE);

return TRUE;
}

//串口读线程函数
DWORD WINAPI CCSeries::ReadThreadFunc(LPVOID lparam)
{
CCSeries *ceSeries = (CCSeries*)lparam;

DWORD evtMask;
BYTE * readBuf = NULL; //读取的字节
DWORD actualReadLen = 0; //实际读取的字节数
DWORD WillReadLen;

DWORD dwReadErrors;
COMSTAT cmState;

//清空缓冲,并检查串口是否打开
ASSERT(ceSeries->m_hComm != INVALID_HANDLE_VALUE);

//清空串口
PurgeComm(ceSeries->m_hComm,PURGE_RXCLEAR | PURGE_TXCLEAR);

SetCommMask(ceSeries->m_hComm,EV_RXCHAR | EV_CTS | EV_DSR);
while(TRUE)
{
if (WaitCommEvent(ceSeries->m_hComm,&evtMask,0))
{
//延时50毫秒再读数据
Sleep(30);
// CCSeries::Count += 1;
SetCommMask(ceSeries->m_hComm,EV_RXCHAR | EV_CTS | EV_DSR);
//表示串口接收到字符
if ((evtMask & EV_RXCHAR) == EV_RXCHAR)
{
ClearCommError(ceSeries->m_hComm,&dwReadErrors,&cmState);
WillReadLen = cmState.cbInQue;

if (WillReadLen <=0)
{
continue;
}

readBuf = new BYTE[WillReadLen];
ReadFile(ceSeries->m_hComm,readBuf,WillReadLen,&actualReadLen,0);
//读取的数据大于0
if (actualReadLen > 0)
{
//触发回调函数
ceSeries->m_OnSeriesRead(ceSeries->m_pPortOwner,readBuf,actualReadLen);
}
//清空串口
PurgeComm(ceSeries->m_hComm,PURGE_RXCLEAR | PURGE_TXCLEAR);
delete [] readBuf;
}
}
//如果收到读线程退出信号,则退出线程
if (WaitForSingleObject(ceSeries->m_hReadCloseEvent,500) == WAIT_OBJECT_0)
{
break;
}
}
return 0;
}

//串口写线程函数
DWORD WINAPI CCSeries::WriteThreadFunc(LPVOID lparam)
{
CCSeries *ceSeries = (CCSeries*)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);

delete[] buf;
}
}

//如果收到写线程退出信号,则退出线程
if (WaitForSingleObject(ceSeries->m_hWriteCloseEvent,500) == WAIT_OBJECT_0)
{
break;
}
ceSeries->m_hWriteThread = NULL;
}
return 0;
}

//关闭读线程
void CCSeries::CloseReadThread()
{
SetEvent(m_hReadCloseEvent);

//设置所有事件无效
SetCommMask(m_hComm,0);
//清空所有将要读的数据
PurgeComm(m_hComm,PURGE_RXCLEAR);

if (WaitForSingleObject(m_hReadThread,10000) == WAIT_TIMEOUT)
{
TerminateThread(m_hReadThread,0);
}
m_hReadThread = NULL;
}

//关闭写线程
void CCSeries::CloseWriteThread()
{
SetEvent(m_hWriteCloseEvent);

//设置所有事件无效
SetCommMask(m_hComm,0);
//清空所有将要读的数据
PurgeComm(m_hComm,PURGE_TXCLEAR);

if (WaitForSingleObject(m_hWriteThread,10000) == WAIT_TIMEOUT)
{
TerminateThread(m_hWriteThread,0);
}
m_hWriteThread = NULL;
}

BOOL CCSeries::OpenPort(CWnd *pProtOwner, UNIT portno, UNIT baud, UNIT parity, UNIT databits, UNIT stopbits)
{
DCB commParam;
TCHAR szPort[15];

if (m_hComm != INVALID_HANDLE_VALUE)
{
return TRUE;
}

ASSERT(pProtOwner != NULL);
ASSERT(portno > 0 && portno < 5);

//设置串口名
wsprintf(szPort,L"COM%d:",portno);

//打开串口
m_hComm = CreateFile(szPort,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);

if (m_hComm == INVALID_HANDLE_VALUE)
{
AfxMessageBox(_T("无法打开端口!请检查是否已被占用。"));
return FALSE;
}

//得到打开串口的当前属性参数,修改后再重新设置串口
//设置串口的超时 特性为立即返回

if (!GetCommState(m_hComm,&commParam))
{
AfxMessageBox(_T("GetCommState faild."));
return FALSE;
}

commParam.BaudRate = baud;
commParam.fBinary = TRUE;//设置二进制模式,此处必须设置为true
commParam.fParity = TRUE;//支持奇偶校验
commParam.ByteSize = databits;
commParam.Parity = NOPARITY;
commParam.StopBits = stopbits;
commParam.fOutxCtsFlow = FALSE;
commParam.fOutxDsrFlow = FALSE;
commParam.fDtrControl = DTR_CONTROL_ENABLE;

commParam.fDsrSensitivity = FALSE;
commParam.fTXContinueOnXoff = 0;
commParam.fOutX = 0;
commParam.fInX = 0;
commParam.ErrorChar = FALSE;
commParam.fNull = FALSE;
commParam.fRtsControl = RTS_CONTROL_ENABLE;

commParam.fAbortOnError = FALSE;

if (!SetCommState(m_hComm,&commParam))
{
AfxMessageBox(_T("SetCommState error."));
return FALSE;
}

COMMTIMEOUTS CommTimeOuts;
GetCommTimeouts(m_hComm,&CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout = 100;
CommTimeOuts.ReadTotalTimeoutMultiplier = 1;
CommTimeOuts.ReadTotalTimeoutConstant = 100;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0;

if (!SetCommTimeouts(m_hComm,&CommTimeOuts))
{
AfxMessageBox(_T("无法按当前参数配置端口,请检查参数!"));
return FALSE;
}
m_pPortOwner = pProtOwner;

SetCommMask(m_hComm,EV_RXCHAR);

SetupComm(m_hComm,1024,1024);

PurgeComm(m_hComm,PURGE_TXCLEAR | PURGE_RXCLEAR);

m_hReadCloseEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
if (NULL == m_hReadCloseEvent)
{
AfxMessageBox(_T("Create read close event failed."));
return FALSE;
}

m_hWriteCloseEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
if (NULL == m_hWriteCloseEvent)
{
AfxMessageBox(_T("Create write close event failed."));
return FALSE;
}

m_hReadThread = CreateThread(NULL,0,ReadThreadFunc,this,0,&m_dwReadThreadID);
if (NULL == m_hReadThread)
{
AfxMessageBox(_T("Create read thread failed."));
return FALSE;
}

m_hWriteThread = CreateThread(NULL,0,WriteThreadFunc,this,0,&m_dwWriteThreadID);
if (NULL == m_hWriteThread)
{
AfxMessageBox(_T("Create write thread failed."));
return FALSE;
}
return TRUE;
}
//关闭串口
void CCSeries::ClosePort()
{
if (m_hComm == INVALID_HANDLE_VALUE)
{
return;
}

CloseReadThread();
CloseWriteThread();

if (!CloseHandle(m_hComm))
{
m_hComm = INVALID_HANDLE_VALUE;
return;
}
}

BOOL CCSeries::WritePort(const BYTE *buf, DWORD bufLen)
{
if (PostThreadMessage(m_dwWriteThreadID,CM_THREADCOMMWRITE,WPARAM(bufLen),LPARAM(buf)))
{
return TRUE;
}

return FALSE;
}

BOOL CCSeries::SetSeriesTimeOuts(COMMTIMEOUTS CommTimeOuts)
{
ASSERT(m_hComm != INVALID_HANDLE_VALUE);
return SetCommTimeouts(m_hComm,&CommTimeOuts);
}
lenux 2007-10-10
  • 打赏
  • 举报
回复
还有可能读写线程有问题,死锁
lenux 2007-10-10
  • 打赏
  • 举报
回复
缓冲区设小一点,1k,
qfeng168 2007-10-10
  • 打赏
  • 举报
回复
是不是线程阻塞掉了
加载更多回复(6)

19,522

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 嵌入开发(WinCE)
社区管理员
  • 嵌入开发(WinCE)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧