一个简单的串口封装类

//---------------------------------------------------------------------------

// SerialPort.h

 

class CSerialPort
{
private:
    HANDLE  m_hComm;
public:
    CSerialPort();  // 构造函数
    ~CSerialPort();  // 析构函数

    BOOL OpenComm(int nComm);  //打开串口函数
    void CloseComm();          //关闭串口函数

    BOOL SetComm(int nBaudRate /*波特率*/,
                 int nParity /*奇偶校验位*/,
                 int nByteSize /*字节位数*/,
                 int nStopBits /*停止位*/);    //设置串口函数

    BOOL SetTimeOuts();                      //设置超时函数

    DWORD ReadComm(void* lpBuf,int nLen);    //读串口函数
    DWORD WriteComm(const void* lpBuf, int nLen);   //写串口函数
};

 

 

//---------------------------------------------------------------------------

// SerialPort.cpp

 

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


// 功能描述:构造函数
CSerialPort::CSerialPort()
{
}

// 功能描述:析构函数
CSerialPort::~CSerialPort()
{
    CloseComm();  //关闭串口
}

// 功能描述:打开串口函数
BOOL CSerialPort::OpenComm(int nComm)
{
    CString strCommName;
    CString strErrInfo;

    strCommName.Format(_T("COM%d"), nComm);

    m_hComm = ::CreateFile(strCommName,  /*要打开串口名称*/
        GENERIC_READ | GENERIC_WRITE,  /*允许读和写*/
        0,         /*独占方式*/
        NULL,        /*安全属性*/
        OPEN_EXISTING,      /*打开而不是创建*/
        0,         /*同步方式*/
        NULL);        /*模板句柄*/

    if(m_hComm == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    }

 return TRUE;
}

// 功能描述:关闭串口函数
void CSerialPort::CloseComm()
{
    if(m_hComm != INVALID_HANDLE_VALUE)
    {
        ::CloseHandle(m_hComm);
        m_hComm = INVALID_HANDLE_VALUE;
    }
}

// 功能描述:设置串口函数
BOOL CSerialPort::SetComm(int nBaudRate,int nParity,int nByteSize,int nStopBits)
{
    DCB  stDCB;
    memset(&stDCB,0,sizeof(stDCB));
    if(!::GetCommState(m_hComm,&stDCB))  //获取串口当前状态属性?
 {
        return FALSE;
 }

    stDCB.BaudRate = nBaudRate;    // 波特率
    stDCB.fParity = 0;
    stDCB.Parity = nParity;     // 奇偶校验位(NOPARITY等)
    stDCB.ByteSize = nByteSize;    // 每个字节有位
    stDCB.StopBits = nStopBits;    // 停止位(ONESTOPBIT等)

    if(!::SetCommState(m_hComm,&stDCB))  // 设置串口状态属性
 {
        return FALSE;
 }

    if(!::SetupComm(m_hComm,1024,1024))  //设置输入缓冲区和输出缓冲区的大小
 {
        return FALSE;
 }

 ::PurgeComm(m_hComm,PURGE_TXCLEAR | PURGE_RXCLEAR);  // 清空输入输出缓冲区

    return TRUE;
}

// 功能描述:设置超时函数
BOOL CSerialPort::SetTimeOuts()
{
    COMMTIMEOUTS stTimeOuts;
 ::GetCommTimeouts(m_hComm, &stTimeOuts);

    stTimeOuts.ReadTotalTimeoutMultiplier = 0;
    stTimeOuts.ReadTotalTimeoutConstant = 1;
    stTimeOuts.WriteTotalTimeoutMultiplier = 0;   // 设定写超时
    stTimeOuts.WriteTotalTimeoutConstant = 0;

    ::SetCommTimeouts(m_hComm,&stTimeOuts);     // 设置超时
    ::PurgeComm(m_hComm,PURGE_TXCLEAR | PURGE_RXCLEAR);  // 清空输入输出缓冲区

    return TRUE;
}

// 功能描述:读串口函数
DWORD CSerialPort::ReadComm(void* lpBuf,int nLen)
{
 DWORD  dwBytesRead = 0;
 OVERLAPPED overlap;
 memset(&overlap, 0, sizeof(overlap));

    if(::ReadFile(m_hComm, lpBuf, nLen, &dwBytesRead, &overlap) == FALSE)
    {
        return 0;
    }
    else
    {
        //::PurgeComm(m_hComm,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
        return dwBytesRead;
    }
}

// 功能描述:写串口函数
DWORD CSerialPort::WriteComm(const void* lpBuf, int nLen)
{
 DWORD dwBytesWritten = 0;
 OVERLAPPED overlap;
 memset(&overlap, 0, sizeof(overlap));

    if(::WriteFile(m_hComm, lpBuf, nLen, &dwBytesWritten, &overlap) == FALSE)
    {
        return 0;
    }
    else
    {
        return dwBytesWritten;
    }
}

 

//---------------------------------------------------------------------------

// 调用方法

 

  // 首先初始化串口

  CSerialPort  m_oSerialPort;s
  m_oSerialPort.OpenComm(m_nPort);
  m_oSerialPort.SetComm(m_dwBaud, NOPARITY, 8, ONESTOPBIT);
  m_oSerialPort.SetTimeOuts();

 

...

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CSerialPort First Version by Remon Spekreijse on 2000-02-08 http://www.codeguru.com/cpp/i-n/network/serialcommunications/article.php/c2483/A-communication-class-for-serial-port.htm Second Version by mrlong on 2007-12-25 https://code.google.com/p/mycom/ 增加 ClosePort 增加 WriteToPort 两个方法 增加 SendData 与 RecvData 方法 by liquanhai on 2011-11-04 http://blog.csdn.net/liquanhai/article/details/4955253 增加 ClosePort 中交出控制权,防止死锁问题 by liquanhai on 2011-11-06 http://blog.csdn.net/liquanhai/article/details/6941574 增加 ReceiveChar 中防止线程死锁 by viruscamp on 2013-12-04 https://github.com/viruscamp/CSerialPort 增加 IsOpen 判断是否打开 修正 InitPort 中 parity Odd Even 参数取值错误 修改 InitPort 中 portnr 取值范围,portnr>9 时特殊处理 取消对 MFC 的依赖,使用 HWND 替代 CWnd,使用 win32 thread 函数而不是 MFC 的 增加用户消息编号自定义,方法来自 CnComm by itas109 on 2014-01-10 http://blog.csdn.net/itas109/article/details/18358297 解决COM10以上端口无法显示的问题 扩展可选择端口,最大值MaxSerialPortNum可以自定义 添加QueryKey()和Hkey2ComboBox两个方法,用于自动查询当前有效的串口号。 by liquanhai on 2014-12-18 增加一些处理措施,主要是对减少CPU占用率 by itas109 on 2016-05-07 http://blog.csdn.net/itas109 修复每次打开串口发送一次,当串口无应答时,需要关闭再打开或者接收完数据才能发送的问题。 解决办法:在m_hEventArray中调整m_hWriteEvent的优先级高于读的优先级。CommThread(LPVOID pParam)函数中读写的位置也调换。 参考:http://zhidao.baidu.com/link?url=RSrbPcfTZRULFFd2ziHZPBwnoXv1iCSu_Nmycb_yEw1mklT8gkoNZAkWpl3UDhk8L35DtRPo5VV5kEGpOx-Gea 修复停止位在头文件中定义成1导致SetCommState报错的问题,应为1对应的停止位是1.5。UINT stopsbits = ONESTOPBIT switch(stopbits)和switch(parity)增加默认情况,增强程序健壮性 by itas109 on 2016-06-22 http://blog.csdn.net/itas109 增加ReceiveStr方法,用于接收字符串(接收缓冲区有多少字符就接收多少字符)。 解决ReceiveChar只能接收单个字符的问题。 by itas109 on 2016-06-29 http://blog.csdn.net/itas109 解决RestartMonitoring方法和StopMonitoring方法命令不准确引起的歧义,根据实际作用。 将RestartMonitoring更改为ResumeMonitoring,将StopMonitoring更改为SuspendMonitoring。 增加IsThreadSuspend方法,用于判断线程是否挂起。 改进ClosePort方法,增加线程挂起判断,解决由于线程挂起导致串口关闭死锁的问题。 增加IsReceiveString宏定义,用于接收时采用单字节接收还是多字节接收 by itas109 on 2016-08-02 http://blog.csdn.net/itas109 https://github.com/itas109 改进IsOpen方法,m_hComm增加INVALID_HANDLE_VALUE的情况,因为CreateFile方法失败返回的是INVALID_HANDLE_VALUE,不是NULL 改进ClosePort方法:增加串口句柄无效的判断(防止关闭死锁);m_hWriteEvent不使用CloseHandle关闭 改进CommThread、ReceiveChar、ReceiveStr和WriteChar方法中异常处理的判断,增加三种判断:串口打开失败(error code:ERROR_INVALID_HANDLE)、连接过程中非法断开(error code:ERROR_BAD_COMMAND)和拒绝访问(error code:ERROR_ACCESS_DENIED) 采用安全函数sprintf_s和strcpy_s函数替换掉sprintf和strcpy 改进QueryKey方法,用于查询注册表的可用串口值,可以搜索到任意的可用串口 改进InitPort方法,串口打开失败,增加提示信息:串口不存在(error code:ERROR_FILE_NOT_FOUND)和串口拒绝访问(error code:ERROR_ACCESS_DENIED) 加入viruscamp 取消对 MFC 的依赖 改进InitPort方法,如果上次串口是打开,再次调用InitPort方法,关闭串口需要做一定的延时,否则有几率导致ERROR_ACCESS_DENIED拒绝访问,也就是串口占用问题 初始化默认波特率修改为9600 修复一些释放的BUG 规范了一些错误信息,参考winerror.h -- error code definitions for the Win32 API functions 删除SendData和RecvData方法 by itas109 on 2016-08-10 http://blog.csdn.net/itas109 https://github.com/itas109 改进ReceiveStr方法,comstat.cbInQue = 0xcccccccc的情况(如串口异常断开),会导致RXBuff初始化失败 by itas109 on 2017-02-14 http://blog.csdn.net/itas109 https://github.com/itas109 兼容ASCII和UNICODE编码 ReceiveStr函数中发送函数SendMessage的第二个参数采用结构体形式,包括portNr串口号和bytesRead读取的字节数,可以处理16进制的时候0x00截断问题 精简不必要的函数SendData和RecvData 尽量的取消对 MFC 的依赖,Hkey2ComboBox函数暂时保留 其他小问题修改 博客:blog.csdn.net/itas109 Email:itas109@qq.com
好的,以下是一个简单的用Java封装串口通信的示例代码: ```java import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.TooManyListenersException; import gnu.io.CommPortIdentifier; import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener; public class SerialCommunication implements SerialPortEventListener { private SerialPort serialPort; private InputStream input; private OutputStream output; private CommPortIdentifier portIdentifier; private static final int TIME_OUT = 2000; private static final int DATA_RATE = 9600; public SerialCommunication(String portName) throws Exception { portIdentifier = CommPortIdentifier.getPortIdentifier(portName); if (portIdentifier.isCurrentlyOwned()) { throw new Exception("Port is currently in use"); } else { serialPort = (SerialPort) portIdentifier.open(getClass().getName(), TIME_OUT); serialPort.setSerialPortParams(DATA_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); input = serialPort.getInputStream(); output = serialPort.getOutputStream(); serialPort.addEventListener(this); serialPort.notifyOnDataAvailable(true); } } public void serialEvent(SerialPortEvent spe) { if (spe.getEventType() == SerialPortEvent.DATA_AVAILABLE) { try { int available = input.available(); byte[] data = new byte[available]; input.read(data); System.out.println(new String(data)); } catch (IOException e) { e.printStackTrace(); } } } public void sendData(String data) { try { output.write(data.getBytes()); output.flush(); } catch (IOException e) { e.printStackTrace(); } } public void close() { serialPort.removeEventListener(); serialPort.close(); } } ``` 这个串口通信使用了RXTXcomm库,可以让Java程序与串口进行通信。在这个中,我们封装串口的打开、读取、写入和关闭等操作。您可以根据自己的需求进行更改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值