WINCE EVC 中串口通信的问题 附源码

shmilyprince 2008-05-20 03:48:24
我使用WINCE5.0和EVC4
在处理一段串口通讯的代码
代码是我按照书上写的写的
但出现了一些问题:先附代码如下(内容过长,分开发)

串口通信类文件

CESeries.h文件

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

#if !defined(AFX_CESERIES_H__1952D4CB_F6A6_489B_80B2_FD59F845BC86__INCLUDED_)
#define AFX_CESERIES_H__1952D4CB_F6A6_489B_80B2_FD59F845BC86__INCLUDED_

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

//定义串口接收数据函数类型
typedef void (CALLBACK* ONSERIESREAD)(CWnd*,BYTE* buf,int bufLen);

//CE串口通讯类
class CCESeries
{
public:
CCESeries();
virtual ~CCESeries();

//打开串口
BOOL OpenPort(CWnd* pPortOwner, //使用串口类,窗体句柄
UINT portNo = 1, //串口号
UINT baud = 19200, //波特率
UINT parity = NOPARITY, //奇偶校验
UINT databits = 8, //数据位
UINT stopbits = 1 //停止位
);
//关闭串口
void ClosePort();
//设置串口读取、写入超时
BOOL SetSeriesTimeouts(COMMTIMEOUTS CommTimeOuts);
//向串口写入数据
BOOL WritePort(const BYTE *buf,DWORD bufLen);
//串口读取回调函数
ONSERIESREAD m_OnSeriesRead;

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();

//已打开的串口句柄
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;

};

#endif // !defined(AFX_CESERIES_H__1952D4CB_F6A6_489B_80B2_FD59F845BC86__INCLUDED_)


...全文
489 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
xujun360979679 2011-02-07
  • 打赏
  • 举报
回复
可以把你的代码发给我吗?
xujun360979679@gmail.com
  • 打赏
  • 举报
回复
怎么不把细节发出来啊???
怎么可以这样??
别人也想知道问题的答案的啊.
shmilyprince 2008-05-21
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 zhuyaqi2006 的回复:]
我有代码,经过修改了的。以前的代码确实存在很多问题,我多一一修改过来了。
而且你调用的时候也出现了很多错误
你这段代码
m_ceSeries.ClosePort();
m_ceSeries.OpenPort(this,1,19200,NOPARITY,8,1);

CString s;
s="0175";
bufLen = s.GetLength()*2;
ZeroMemory(buf,bufLen);
buf=(BYTE*)s.GetBuffer(s.GetLength());
s.ReleaseBuffer();
bool ii=m_ceSe…
[/Quote]


太感谢你了!!
用了你的调用方法 我可以正常发送了
PC上也正常显示了!

细节问题我EMAIL你!


zhuyaqi2006 2008-05-21
  • 打赏
  • 举报
回复
我有代码,经过修改了的。以前的代码确实存在很多问题,我多一一修改过来了。
而且你调用的时候也出现了很多错误
你这段代码
m_ceSeries.ClosePort();
m_ceSeries.OpenPort(this,1,19200,NOPARITY,8,1);

CString s;
s="0175";
bufLen = s.GetLength()*2;
ZeroMemory(buf,bufLen);
buf=(BYTE*)s.GetBuffer(s.GetLength());
s.ReleaseBuffer();
bool ii=m_ceSeries.WritePort(buf,bufLen);
if (!ii)
{
AfxMessageBox(L"写入失败");

}
应该这样写:
m_ceSeries.ClosePort();
m_ceSeries.OpenPort(this,1,19200,NOPARITY,8,1);
CString strUnlogall("UNLOGALL\r\n");

int length=strUnlogall.GetLength();
char *cUnlogall=new char[length+1];
WideCharToMultiByte(CP_ACP, 0, (const unsigned short*)strUnlogall,
-1, cUnlogall, length+1, NULL, NULL);

if (!m_ceSeries.WritePort((BYTE*)cUnlogall,length+1))
{
AfxMessageBox(L"写入失败");
}

可以与我联系。zhuyaqi2004@sohu.com
shmilyprince 2008-05-21
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 lenux 的回复:]
建议不要使用messagebox来看消息,你应该把消息每次都写入到一个文件中,然后去查看是否一致
[/Quote]


谢谢,我试一下
lenux 2008-05-21
  • 打赏
  • 举报
回复
建议不要使用messagebox来看消息,你应该把消息每次都写入到一个文件中,然后去查看是否一致
shmilyprince 2008-05-21
  • 打赏
  • 举报
回复
这个程序使我从书上照着抄下来的

应该没有问题

可能就是我的设备上有点问题。
我再查一下
shmilyprince 2008-05-21
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 zzhll 的回复:]
这个程序有些眼熟,我的串口通信程序也是用这个改的,原来的程序我也试过,应该是没有问题。
我认为还可能是你的AfxMessageBox或者嵌入式设备那边的问题。
建议你直接使用,应该就可以看到结果了。
[/Quote]


谢谢,我的PC和主板没有连接,EVC也没法远程调试
程序只能通过U盘考来考去
单步调试 没法实现
11000000 2008-05-21
  • 打赏
  • 举报
回复
这个程序有些眼熟,我的串口通信程序也是用这个改的,原来的程序我也试过,应该是没有问题。
我认为还可能是你的AfxMessageBox或者嵌入式设备那边的问题。
建议你直接使用单步调试,应该就可以看到结果了。
shmilyprince 2008-05-21
  • 打赏
  • 举报
回复
实在不好意思。说了半天,问题没说清。
出现的问题
因为在目标板上无法在线仿真调试,没法得知确切过程中的信息
故在几个方法中增加了AfxMessageBox来查看buf中的信息

CString s=buf;
AfxMessageBox(s);


发现在发送时(进入消息前)和通过消息截获后buf中的内容不一致
即 WriteThreadFunc 方法中
if (msg.message == CM_THREADCOMMWRITE)
{
//向串口写
buf = (BYTE*)msg.lParam;
dwWriteLen = msg.wParam;

得到的buf AfxMessageBox出来是 “U”
无论发送的字串如何修改都是这样。
也收不到信息


我是在电脑上用一个了串口通信的软件进行接收发送一个信息的。
用我的程序,发送一个信息然后在电脑上接收这个信息,
目前的情况是:
1、程序中发送的不论是什么在WriteThreadFunc 方法中截获的消息的buf显示出来都是字母“U”
2、电脑上没有接收到任何信息 但在程序错误时,能出现一堆乱码,我觉得串口通信应该没有问题程序也执行到了WriteFile,并显示结束
3、电脑通过串口软件发送的信息,程序并为截获到消息ReadThreadFunc根本无响应


xiaohf702 2008-05-20
  • 打赏
  • 举报
回复
用MessageBox也行,把buf作为第二个参数输出,不过类型要是THCAR型
int MessageBox(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType
);
lenux 2008-05-20
  • 打赏
  • 举报
回复
你的messagebox显示需要把buf转换成TCHAR*才能正确显示。

这么长的帖子居然连你的“出了一些问题”到底是什么也没有说清楚!!!
载舟之水 2008-05-20
  • 打赏
  • 举报
回复
内容过长的话,一般没人看,建议缩小范围,另外用messagebox来调试是不正确的,应当通过调试串口输出或写文件。
shmilyprince 2008-05-20
  • 打赏
  • 举报
回复
UNICODE编码??

能说得详细些么?

我影响中CE好像只是别UNICODE编码
难道我还需要对我的数据进行转换?
sunrain_hjb 2008-05-20
  • 打赏
  • 举报
回复
大概是UNICODE编码的问题吧,你再看一看。
shmilyprince 2008-05-20
  • 打赏
  • 举报
回复

//串口读线程函数
DWORD CCESeries::ReadThreadFunc(LPVOID lparam)
{
CCESeries *ceSeries = (CCESeries*)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))
{
SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );
//表示串口收到字符
if (evtMask & 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);
}
}
}
//如果收到读线程退出信号,则退出线程
if (WaitForSingleObject(ceSeries->m_hReadCloseEvent,500) == WAIT_OBJECT_0)
{
break;
}
}
return 0;
}

//串口写线程函数
DWORD CCESeries::WriteThreadFunc(LPVOID lparam)
{
CCESeries *ceSeries = (CCESeries*)lparam;
MSG msg;
DWORD dwWriteLen = 0;
BYTE * buf= new BYTE();
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;
}

//私用方法,用于向串口写数据,被写线程调用
BOOL CCESeries::WritePort(HANDLE hComm,const BYTE *buf,DWORD bufLen)
{
DWORD dwNumBytesWritten;
DWORD dwHaveNumWritten =0 ; //已经写入多少
ASSERT(hComm != INVALID_HANDLE_VALUE);

CString s=buf;
AfxMessageBox(s);

do
{
if (WriteFile (hComm, //串口句柄
buf+dwHaveNumWritten, //被写数据缓冲区
bufLen - dwHaveNumWritten, //被写数据缓冲区大小
&dwNumBytesWritten, //函数执行成功后,返回实际向串口写的个数
NULL)) //此处必须设置NULL
{
dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;
//写入完成
if (dwHaveNumWritten == bufLen)
{
break;
}
Sleep(10);
}
else
{
return FALSE;
}
}while (TRUE);

return TRUE;
}

/*
*函数介绍:向串口发送数据
*入口参数:buf : 将要往串口写入的数据的缓冲区
bufLen : 将要往串口写入的数据的缓冲区长度
*出口参数:(无)
*返回值:TRUE:表示成功地将要发送的数据传递到写线程消息队列。
FALSE:表示将要发送的数据传递到写线程消息队列失败。
注视:此处的TRUE,不直接代表数据一定成功写入到串口了。
*/
BOOL CCESeries::WritePort(const BYTE *buf,DWORD bufLen)
{
//将要发送的数据传递到写线程消息队列
bool ini=PostThreadMessage(m_dwWriteThreadID,CM_THREADCOMMWRITE,WPARAM(bufLen), LPARAM(buf));

if (ini)
{
return TRUE;
}

return FALSE;
}
[/code]


调用代码:


m_ceSeries.ClosePort();
m_ceSeries.OpenPort(this,1,19200,NOPARITY,8,1);

CString s;
s="0175";
bufLen = s.GetLength()*2;
ZeroMemory(buf,bufLen);
buf=(BYTE*)s.GetBuffer(s.GetLength());
s.ReleaseBuffer();
bool ii=m_ceSeries.WritePort(buf,bufLen);
if (!ii)
{
AfxMessageBox(L"写入失败");

}


出现的问题
因为在目标板上无法在线仿真调试,没法得知确切过程中的信息
故在几个方法中增加了MessageBox来查看buf中的信息,发现在发送时(进入消息前)和通过消息截获后buf中的内容不一致
即 WriteThreadFunc 方法中

if (msg.message == CM_THREADCOMMWRITE)
{
//向串口写
buf = (BYTE*)msg.lParam;
dwWriteLen = msg.wParam;



得到的buf MessageBox出来是 “U”
无论发送的字串如何修改都是这样。
另:也收不到信息
请各位帮忙查看一下。
shmilyprince 2008-05-20
  • 打赏
  • 举报
回复
CESeries.cpp文件
[code=C/C++]
// CESeries.cpp: implementation of the CCESeries class.

#include "stdafx.h"
#include "CESeries.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//定义向写线程发送的消息常量
const CM_THREADCOMMWRITE = WM_USER+110;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

//类CCESeries构造函数
CCESeries::CCESeries()
{
m_hComm = INVALID_HANDLE_VALUE;
}

//类CCESeries析构函数
CCESeries::~CCESeries()
{

}

//关闭读线程
void CCESeries::CloseReadThread()
{
SetEvent(m_hReadCloseEvent);
//设置所有事件无效无效
SetCommMask(m_hComm, 0);
//清空所有将要读的数据
PurgeComm( m_hComm, PURGE_RXCLEAR );
//等待10秒,如果读线程没有退出,则强制退出
if (WaitForSingleObject(m_hReadThread,10000) == WAIT_TIMEOUT)
{
TerminateThread(m_hReadThread,0);
}
m_hReadThread = NULL;
}

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

//清空所有将要写的数据
PurgeComm( m_hComm, PURGE_TXCLEAR );

//等待10秒,如果写线程没有退出,则强制退出
if (WaitForSingleObject(m_hWriteThread,10000) == WAIT_TIMEOUT)
{
TerminateThread(m_hWriteThread,0);
}
m_hWriteThread = NULL;
}

/*
*函数介绍:关闭串口
*入口参数:(无)
*出口参数:(无)
*返回值: (无)
*/
void CCESeries::ClosePort()
{
//表示串口还没有打开
if (m_hComm == INVALID_HANDLE_VALUE)
{
return ;
}

//关闭读线程
CloseReadThread();

//关闭写线程
CloseWriteThread();

//关闭串口
if (!CloseHandle (m_hComm))
{
m_hComm = INVALID_HANDLE_VALUE;
return ;
}
}

/*
*函数介绍:设置串口读取、写入超时
*入口参数:CommTimeOuts : 指向COMMTIMEOUTS结构
*出口参数:(无)
*返回值:TRUE:设置成功;FALSE:设置失败
*/
BOOL CCESeries::SetSeriesTimeouts(COMMTIMEOUTS CommTimeOuts)
{
ASSERT(m_hComm != INVALID_HANDLE_VALUE);
return SetCommTimeouts(m_hComm,&CommTimeOuts);
}

/*
*函数介绍:打开串口
*入口参数:pPortOwner :使用此串口类的窗体句柄
portNo :串口号
baud :波特率
parity :奇偶校验
databits :数据位
stopbits :停止位
*出口参数:(无)
*返回值:TRUE:成功打开串口;FALSE:打开串口失败
*/
BOOL CCESeries::OpenPort(CWnd* pPortOwner, /*使用串口类,窗体句柄*/
UINT portNo , /*串口号*/
UINT baud , /*波特率*/
UINT parity , /*奇偶校验*/
UINT databits , /*数据位*/
UINT stopbits /*停止位*/
)
{
DCB commParam;
TCHAR szPort[15];

// 已经打开的话,直接返回
if (m_hComm != INVALID_HANDLE_VALUE)
{
return TRUE;
}
ASSERT(pPortOwner != 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)
{
// 无效句柄,返回。
return FALSE;
}

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

if (!GetCommState(m_hComm,&commParam))
{
return FALSE;
}

commParam.BaudRate = baud; // 设置波特率
commParam.fBinary = TRUE; // 设置二进制模式,此处必须设置TRUE
commParam.fParity = TRUE; // 支持奇偶校验
commParam.ByteSize = databits; // 数据位,范围:4-8
commParam.Parity = NOPARITY; // 校验模式
commParam.StopBits = stopbits; // 停止位

commParam.fOutxCtsFlow = FALSE; // No CTS output flow control
commParam.fOutxDsrFlow = FALSE; // No DSR output flow control
commParam.fDtrControl = DTR_CONTROL_ENABLE;
// DTR flow control type
commParam.fDsrSensitivity = FALSE; // DSR sensitivity
commParam.fTXContinueOnXoff = TRUE; // XOFF continues Tx
commParam.fOutX = FALSE; // No XON/XOFF out flow control
commParam.fInX = FALSE; // No XON/XOFF in flow control
commParam.fErrorChar = FALSE; // Disable error replacement
commParam.fNull = FALSE; // Disable null stripping
commParam.fRtsControl = RTS_CONTROL_ENABLE;
// RTS flow control
commParam.fAbortOnError = FALSE; // 当串口发生错误,并不终止串口读写

if (!SetCommState(m_hComm, &commParam))
{
return FALSE;
}


//设置串口读写时间
COMMTIMEOUTS CommTimeOuts;
GetCommTimeouts (m_hComm, &CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 10;
CommTimeOuts.WriteTotalTimeoutConstant = 1000;

if(!SetCommTimeouts( m_hComm, &CommTimeOuts ))
{
return FALSE;
}

m_pPortOwner = pPortOwner;

//指定端口监测的事件集
SetCommMask (m_hComm, EV_RXCHAR);

//分配设备缓冲区
SetupComm(m_hComm,512,512);

//初始化缓冲区中的信息
PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);

m_hReadCloseEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
m_hWriteCloseEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
//创建读串口线程
m_hReadThread = CreateThread(NULL,0,ReadThreadFunc,this,0,&m_dwReadThreadID);
//创建写串口线程
m_hWriteThread = CreateThread(NULL,0,WriteThreadFunc,this,0,&m_dwWriteThreadID);

return TRUE;
}

19,500

社区成员

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

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