8461|16

89

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

WINCE EVC 中串口通信的问题 附源码 [复制链接]

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

串口通信类文件

CESeries.h文件

  1. // CESeries.h: interface for the CCESeries class.
  2. //
  3. //////////////////////////////////////////////////////////////////////

  4. #if !defined(AFX_CESERIES_H__1952D4CB_F6A6_489B_80B2_FD59F845BC86__INCLUDED_)
  5. #define AFX_CESERIES_H__1952D4CB_F6A6_489B_80B2_FD59F845BC86__INCLUDED_

  6. #if _MSC_VER > 1000
  7. #pragma once
  8. #endif // _MSC_VER > 1000

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

  11. //CE串口通讯类
  12. class CCESeries  
  13. {
  14. public:
  15.         CCESeries();
  16.         virtual ~CCESeries();

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

  33. private:
  34.     //串口读线程函数
  35.     static  DWORD WINAPI ReadThreadFunc(LPVOID lparam);
  36.         //串口写线程函数
  37.     static DWORD WINAPI WriteThreadFunc(LPVOID lparam);

  38.         //向串口写入数据
  39.         static BOOL WritePort(HANDLE hComm,const BYTE *buf,DWORD bufLen);

  40.         //关闭读线程
  41.         void CloseReadThread();
  42.         //关闭写线程
  43.         void CloseWriteThread();

  44.         //已打开的串口句柄
  45.         HANDLE        m_hComm;
  46.         CWnd* m_pPortOwner;

  47.         //读写线程句柄
  48.         HANDLE m_hReadThread;
  49.         HANDLE m_hWriteThread;

  50.         //读写线程ID标识
  51.         DWORD m_dwReadThreadID;
  52.         DWORD m_dwWriteThreadID;

  53.         //读线程退出事件
  54.         HANDLE m_hReadCloseEvent;
  55.         //写线程退出事件
  56.         HANDLE m_hWriteCloseEvent;

  57. };

  58. #endif // !defined(AFX_CESERIES_H__1952D4CB_F6A6_489B_80B2_FD59F845BC86__INCLUDED_)
复制代码


最新回复

怎么不把细节发出来啊??? 怎么可以这样?? 别人也想知道问题的答案的啊.  详情 回复 发表于 2010-2-28 09:48
点赞 关注

回复
举报

73

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
CESeries.cpp文件
[code]
// 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;
}
 
 

回复

78

帖子

0

TA的资源

一粒金砂(初级)

板凳
 

//串口读线程函数
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]


调用代码:


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

  3.         CString s;
  4.         s="0175";
  5.         bufLen = s.GetLength()*2;
  6.         ZeroMemory(buf,bufLen);
  7.         buf=(BYTE*)s.GetBuffer(s.GetLength());  
  8.         s.ReleaseBuffer();
  9.         bool ii=m_ceSeries.WritePort(buf,bufLen);
  10.         if (!ii)
  11.         {
  12.                 AfxMessageBox(L"写入失败");
  13.        
  14.         }
复制代码


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

  1.       if (msg.message == CM_THREADCOMMWRITE)
  2.         {
  3.         //向串口写
  4.         buf = (BYTE*)msg.lParam;
  5.         dwWriteLen = msg.wParam;
复制代码



得到的buf MessageBox出来是 “U”
无论发送的字串如何修改都是这样。
另:也收不到信息
请各位帮忙查看一下。
 
 
 

回复

85

帖子

0

TA的资源

一粒金砂(初级)

4
 
大概是UNICODE编码的问题吧,你再看一看。
 
 
 

回复

81

帖子

0

TA的资源

一粒金砂(初级)

5
 
UNICODE编码??

能说得详细些么?

我影响中CE好像只是别UNICODE编码
难道我还需要对我的数据进行转换?
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

6
 
内容过长的话,一般没人看,建议缩小范围,另外用messagebox来调试是不正确的,应当通过调试串口输出或写文件。
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

7
 
你的messagebox显示需要把buf转换成TCHAR*才能正确显示。

这么长的帖子居然连你的“出了一些问题”到底是什么也没有说清楚!!!
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

8
 
用MessageBox也行,把buf作为第二个参数输出,不过类型要是THCAR型
int MessageBox(
  HWND hWnd,
  LPCTSTR lpText,
  LPCTSTR lpCaption,
  UINT uType
);
 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

9
 
实在不好意思。说了半天,问题没说清。
出现的问题
因为在目标板上无法在线仿真调试,没法得知确切过程中的信息
故在几个方法中增加了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根本无响应


 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

10
 
这个程序有些眼熟,我的串口通信程序也是用这个改的,原来的程序我也试过,应该是没有问题。
我认为还可能是你的AfxMessageBox或者嵌入式设备那边的问题。
建议你直接使用单步调试,应该就可以看到结果了。
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

11
 
引用 9 楼 zzhll 的回复:
这个程序有些眼熟,我的串口通信程序也是用这个改的,原来的程序我也试过,应该是没有问题。
我认为还可能是你的AfxMessageBox或者嵌入式设备那边的问题。
建议你直接使用,应该就可以看到结果了。



谢谢,我的PC和主板没有连接,EVC也没法远程调试
程序只能通过U盘考来考去
单步调试 没法实现
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

12
 
这个程序使我从书上照着抄下来的

应该没有问题

可能就是我的设备上有点问题。
我再查一下
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

13
 
建议不要使用messagebox来看消息,你应该把消息每次都写入到一个文件中,然后去查看是否一致
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

14
 
引用 12 楼 lenux 的回复:
建议不要使用messagebox来看消息,你应该把消息每次都写入到一个文件中,然后去查看是否一致



谢谢,我试一下
 
 
 

回复

63

帖子

0

TA的资源

一粒金砂(初级)

15
 
我有代码,经过修改了的。以前的代码确实存在很多问题,我多一一修改过来了。
而且你调用的时候也出现了很多错误
你这段代码
    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
 
 
 

回复

99

帖子

0

TA的资源

一粒金砂(初级)

16
 
引用 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…



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

细节问题我EMAIL你!


 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

17
 
怎么不把细节发出来啊???
怎么可以这样??
别人也想知道问题的答案的啊.
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表