首    页 界面/窗口 网络/通讯 数据库 组件开发 图像/多媒体 NET/Web 其它技术 源码下载 资料下载 软件共享 软件外包 曲艺杂谈
栏目导航:  首    页  |  网络/通讯  |  串口通讯  


同步串口类


原作者:郑新华    源出处:不详   发布者:施昌权    发布类型:转载    发布日期:2008-08-27

                  

        头文件

        // SerialPort.h: interface for the CSerialPort class.
        // 类名: CSerialPort
        // 创建人: 郑新华
        // 创建日期:2005-7-13
        // 概述:该类封装了对串口的基本操作,目前为同步操作,日后逐渐完善为同步
        //        异步可配置状态
        //////////////////////////////////////////////////////////////////////

        #if !defined(AFX_SERIALPORT_H__5F418CEB_1BFD_4A54_9ABD_4984A825E4CF__INCLUDED_)
        #define AFX_SERIALPORT_H__5F418CEB_1BFD_4A54_9ABD_4984A825E4CF__INCLUDED_

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

        typedef struct {
                //串口号
                DWORD m_dwPort;
                //波特率
                DWORD m_dwBaudRate;
                //停止位
                DWORD m_dwStopBit;
                //奇偶校验
                //DWORD m_dwParity;
                char m_chrParity;
                //字节大小
                BYTE m_bytByteSize;
                //串口输入缓冲大小
                DWORD m_dwInputSize;
                //串口输出缓冲大小
                DWORD m_dwOutputSize;
                //串口句柄
                HANDLE m_hCommHandle;
                //是否同步
                BOOL m_bSync;
        }UDT_PortParam;

        class CSerialPort
        {
        public:
                BOOL IsOpen();
                //获取串口配置参数
                UDT_PortParam GetParam();
                //设置串口配置
                void SetParam(UDT_PortParam udtParam);
                //向串口写数据
                DWORD Write(char* pszBuffer, DWORD dwBufferLen);
                //从串口读数据
                DWORD Read(char* pszBuffer, DWORD dwBufferLen, DWORD dwWaitTime = 20);
                //关闭串口
                void Close();
                //打开串口
                BOOL Open();
                CSerialPort(UDT_PortParam udtPortParam);
                CSerialPort();
                virtual ~CSerialPort();
        protected:
                char szPort[20];
        private:
                BOOL Setup();
                UDT_PortParam m_udtPortParam;
        };

        #endif // !defined(AFX_SERIALPORT_H__5F418CEB_1BFD_4A54_9ABD_4984A825E4CF__INCLUDED_)

        cpp文件

        // SerialPort.cpp: implementation of the CSerialPort class.
        //
        //////////////////////////////////////////////////////////////////////

        #include "stdafx.h"
        #include "Comm.h"
        #include "SerialPort.h"

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

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

        CSerialPort::CSerialPort()
        {
                m_udtPortParam.m_dwBaudRate = 9600;
                m_udtPortParam.m_dwPort = 1;
                m_udtPortParam.m_bytByteSize = 8;
                m_udtPortParam.m_dwStopBit = ONESTOPBIT;
                //m_udtPortParam.m_dwParity = NOPARITY;
                m_udtPortParam.m_chrParity = 'N';
                m_udtPortParam.m_dwInputSize = 4096;
                m_udtPortParam.m_dwOutputSize = 4096;
                m_udtPortParam.m_hCommHandle = INVALID_HANDLE_VALUE;
                m_udtPortParam.m_bSync = TRUE;
        }

        CSerialPort::~CSerialPort()
        {
                Close();
        }

        CSerialPort::CSerialPort(UDT_PortParam udtPortParam)
        {
                m_udtPortParam = udtPortParam;
        }

        /***************************************************************************
        *功能: 打开串口
        *参数: 无
        *返回值:执行成功返回TRUE,否则返回FALSE
        ***************************************************************************/
        BOOL CSerialPort::Open()
        {
                ASSERT(m_udtPortParam.m_dwPort >= 1 && m_udtPortParam.m_dwPort <= 1024);

                //组合成欲打开的串口名
                memset(szPort, '\0', 20);
                strcpy(szPort, "\\\\.\\COM");
                char p[5];
                ltoa(m_udtPortParam.m_dwPort, p, 10);

                strcat(szPort, p);

                TRACE1("\n串口为:%s", szPort);
                if(IsOpen())
                        Close();

                m_udtPortParam.m_hCommHandle = CreateFile(
                                szPort,
                                GENERIC_READ | GENERIC_WRITE,
                                0,
                                NULL,
                                OPEN_EXISTING,
                                FILE_ATTRIBUTE_NORMAL,
                                NULL
                );

                if(m_udtPortParam.m_hCommHandle == INVALID_HANDLE_VALUE)
                        return FALSE;

                //设置缓冲区
                if(!::SetupComm(m_udtPortParam.m_hCommHandle, m_udtPortParam.m_dwInputSize, m_udtPortParam.m_dwOutputSize))
                {

                        Close();
                        return FALSE;
                }

                //设置超时时间
                COMMTIMEOUTS _CO;
                if(!::GetCommTimeouts(m_udtPortParam.m_hCommHandle, &_CO))
                        return FALSE;
                _CO.ReadIntervalTimeout = 0xFFFFFFFF;
                _CO.ReadTotalTimeoutMultiplier = 0;
                _CO.ReadTotalTimeoutConstant = 0;
                _CO.WriteTotalTimeoutMultiplier = 0;
                _CO.WriteTotalTimeoutConstant = 2000;
                if(!::SetCommTimeouts(m_udtPortParam.m_hCommHandle, &_CO))
                {
                        Close();
                       return FALSE;
                }

                //清空串口缓冲区
                if(!::PurgeComm(m_udtPortParam.m_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))
                {
                        Close();
                        return FALSE;
                }

                return Setup();
        }

        /*********************************************************************************
        *功能: 关闭串口
        *参数: 无
        *返回值:无
        *********************************************************************************/
        void CSerialPort::Close()
        {
                if(IsOpen())
                {
                        ::CloseHandle(m_udtPortParam.m_hCommHandle);
                        m_udtPortParam.m_hCommHandle = INVALID_HANDLE_VALUE;
                }
        }

        /***************************************************************************
        *功能: 读取串口
        *参数: pszBuffer    数据存放缓冲区首地址
        *        dwBufferLen 缓冲长度
        *        dwWaitTime   等待时间,默认20毫秒
        *返回值:执行失败返回0,否则为读出数据长度
        ****************************************************************************/
        DWORD CSerialPort::Read(char *pszBuffer, DWORD dwBufferLen, DWORD dwWaitTime)
        {
                ASSERT(pszBuffer != NULL);

                if(!IsOpen())
                {
                        TRACE0("\n串口没有打开!");
                        return 0;
                }

                COMSTAT Stat;
                DWORD dwError;

                //清除错误
                if(::ClearCommError(m_udtPortParam.m_hCommHandle, &dwError, &Stat) && dwError > 0)
                {
                        //清空输入缓冲区
                        ::PurgeComm(m_udtPortParam.m_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);
                        TRACE0("\n清除错误失败!");
                        return 0;
                }
                //Sleep(500);

                pszBuffer[0] = '\0';

                unsigned long uReadLength = 0;
                //dwBufferLen = dwBufferLen - 1 > Stat.cbInQue ? Stat.cbInQue : dwBufferLen - 1;

                //同步读取
                if(m_udtPortParam.m_bSync)
                { 
                        if(!::ReadFile(m_udtPortParam.m_hCommHandle, pszBuffer, dwBufferLen, &uReadLength, NULL))
                        {
                                TRACE0("\n读取串口失败!");
                                if(::GetLastError() != ERROR_IO_PENDING)
                                        uReadLength = 0;
                        }
                        TRACE1("\nReadFile读出%d个字符!", uReadLength);

                        //清空缓冲区
                        ::PurgeComm(m_udtPortParam.m_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);
                }
                else //异步
                {
                        OVERLAPPED _ReadOverlapped;
                        memset(&_ReadOverlapped, 0 ,sizeof(_ReadOverlapped));
                        _ReadOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
                        ASSERT(_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE);

                        if(!::ReadFile(m_udtPortParam.m_hCommHandle, pszBuffer, dwBufferLen, &uReadLength, &_ReadOverlapped))
                        {
                                //结束异步IO
                                if(::GetLastError() == ERROR_IO_PENDING)
                                {
                                        WaitForSingleObject(_ReadOverlapped.hEvent, dwWaitTime);
                                        if(!::GetOverlappedResult(m_udtPortParam.m_hCommHandle, &_ReadOverlapped, &uReadLength, false))
                                        {
                                               //其他错误
                                               if(::GetLastError() == ERROR_IO_INCOMPLETE)
                                                        uReadLength = 0;
                                        }
                                        else
                                                uReadLength = 0;
                                }
                        }
                        if(_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE)
                        CloseHandle(_ReadOverlapped.hEvent);
                }

                pszBuffer[uReadLength] = '\0';

                return uReadLength;
        }

        /*********************************************************************************
        *功能: 向串口写入数据
        *参数: pszBuffer   欲写入数据首地址
        *        dwBufferLen 欲写入数据长度
        *返回值:执行失败返回0,否则为写入数据长度
        **********************************************************************************/
        DWORD CSerialPort::Write(char *pszBuffer, DWORD dwBufferLen)
        {
                ASSERT(pszBuffer != NULL);

                if(!IsOpen())
                        return FALSE;

                DWORD dwError;
                //清除错误
                if(::ClearCommError(m_udtPortParam.m_hCommHandle, &dwError, NULL) && dwError > 0)
                        //清空输入缓冲区
                        ::PurgeComm(m_udtPortParam.m_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);

                unsigned long uWriteLength = 0;

                //同步写入
                if(m_udtPortParam.m_bSync)
                {
                        if(!::WriteFile(m_udtPortParam.m_hCommHandle, pszBuffer, dwBufferLen, &uWriteLength, NULL))
                                if(::GetLastError() != ERROR_IO_PENDING)
                                        uWriteLength = 0;
                }
                else //异步
                {
                        OVERLAPPED _WriteOverlapped;
                        memset(&_WriteOverlapped, 0 ,sizeof(_WriteOverlapped));
                        _WriteOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
                        ASSERT(_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE);

                        if(!::WriteFile(m_udtPortParam.m_hCommHandle, pszBuffer, dwBufferLen, &uWriteLength, &_WriteOverlapped))
                               if(::GetLastError() != ERROR_IO_PENDING)
                                        uWriteLength = 0;

                        if(_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE)
                                CloseHandle(_WriteOverlapped.hEvent);
                }

               return uWriteLength;
        }

        void CSerialPort::SetParam(UDT_PortParam udtParam)
        {
                m_udtPortParam = udtParam;
        }

        UDT_PortParam CSerialPort::GetParam()
        {
                return m_udtPortParam;
        }

        BOOL CSerialPort::IsOpen()
        {
                return m_udtPortParam.m_hCommHandle != INVALID_HANDLE_VALUE;
        }

        /****************************************************************************
        *功能: 设置波特率、停止位等
        *参数: 无
        *返回值:执行成功返回TRUE,否则返回FALSE
        *****************************************************************************/
        BOOL CSerialPort::Setup()
        {
                BOOL bResult = FALSE;
                if(IsOpen())
                {
                        DCB dcb;
                        if(!::GetCommState(m_udtPortParam.m_hCommHandle, &dcb))
                                return FALSE;

                        /*
                        dcb.BaudRate = m_udtPortParam.m_dwBaudRate;
                        dcb.ByteSize = m_udtPortParam.m_bytByteSize;
                        dcb.StopBits = m_udtPortParam.m_dwStopBit;
                        dcb.Parity = m_udtPortParam.m_dwParity;*/
                        char chrSet[50];
   
                        sprintf(chrSet, "%d,%c,%d,%d", m_udtPortParam.m_dwBaudRate, m_udtPortParam.m_chrParity, m_udtPortParam.m_bytByteSize, m_udtPortParam.m_dwStopBit);
                        if(BuildCommDCB(chrSet, &dcb))
                        {
                                if(::SetCommState(m_udtPortParam.m_hCommHandle, &dcb))
                                        bResult = TRUE;
                        }
  
                }
                if(!bResult)
                        Close();
                return bResult;
        }
 

关于我们 版权声明 广告服务 联系我们 友情链接 加入收藏
站长:施昌权    Email:scq2099yt@163.com    MSN:scq2099yt@live.cn    QQ:14046300    本站QQ群:67202409
Copyright © 2008     卓为VC(www.joyvc.cn)    All Rights Reserved    建议分辨率 1024×768
本站由施昌权制作维护
京ICP备09012297号