当前位置:   article > 正文

C++之串口通讯_c++串口通信

c++串口通信

简介

串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口 (Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。

代码

头文件

SerialInterface.h

#ifndef __SerialInterface_H_
#define __SerialInterface_H_
#include <Windows.h>
#include <string>
using namespace std;

class SerialInterface
{
private:
    /* data */
    HANDLE hCom;
    string last_error;
public:
    SerialInterface();
    ~SerialInterface();
public:
    //同步方式打开串口,并配置默认信息
    bool openSyn(string serial_name,unsigned char baud_rate,unsigned char parity, unsigned char byte_size, unsigned char stop_bits);
    //同步方式打开串口(需自己配置串口参数)
    bool openSyn(string serial_name);

    //设置推荐的缓冲大小
    bool setBufferSize(DWORD inputBuff,DWORD outBuffer);
    //设置超时
    bool setTimeouts(COMMTIMEOUTS &timeouts);
    //设置串口信息
    bool setDCB(DCB& dcb);

    //刷新缓冲区
    bool purgeBuff(DWORD flags);
    //刷新缓冲区
    bool flushBuff();
    //写数据
    DWORD writeData(char *buffer,int length);
    //读数据
    DWORD readData(char *buffer,int length);
    //写字符串
    DWORD writeStr(string str);
    //关闭串口
    void closeComm();
    //判断串口是否打开
    bool isOpened();
    //得到最后一次失败的错误信息
    string getSerialLastError();
private:
    //设置最后一次的错误信息
    void setSerialLastError(string error_msg);
    //清chu最后一次的错误信息
    void clearSerialLastError();
};

#endif /*__SerialInterface_H_*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

源码文件

SerialInterface.cpp

#include "SerialInterface.h"

/*******************************************************************
* 名称: openSyn
* 功能: 同步方式打开串口,并配置默认信息
* 参数:
    serial_name:串口名称
    baud_rate  :波特率,取值如下
        ......
        CBR_9600    9600bps
        CBR_14400   14400bps
        ......
    parity     :校验方式
        EVENPARITY  偶校验
        MARKPARITY  标号校验
        NOPARITY    无校验
        ODDPARITY   奇校验
        SPACEPARITY 空格校验
    byte_size  :数据位大小
        4,5,6,7,8
    stop_bits  :停止位
        ONESTOPBIT      1个停止位
        ONE5STOPBITS    1.5个停止位
        TWOSTOPBITS     2个停止位
* 返回: 正确返回为ture,错误返回为false
*******************************************************************/
bool SerialInterface::openSyn(string serial_name, unsigned char baud_rate, unsigned char parity, unsigned char byte_size, unsigned char stop_bits)
{
    if (!openSyn(serial_name))
        return false;
    DCB dcb;

    if (false == GetCommState(hCom, &dcb))//获得当前串口的配置信息
    {
        setSerialLastError("SerialInterface::open() : GetCommState Error");
        return false;
    }

    dcb.DCBlength = sizeof(DCB);
    dcb.BaudRate = baud_rate;
    dcb.Parity = parity;
    dcb.ByteSize = byte_size;
    dcb.StopBits = stop_bits;

    if (false == SetCommState(hCom, &dcb))//用DCB结构重新配置串行端口信息
    {
        setSerialLastError("SerialInterface::open() : SetCommState Error");
        return false;
    }

    //超时处理
    COMMTIMEOUTS timeouts;
    timeouts.ReadIntervalTimeout = MAXDWORD; //读间隔超时
    // 把间隔超时设为最大,把总超时设为0将导致ReadFile立即返回并完成操作 

    timeouts.ReadTotalTimeoutMultiplier = 0; //读时间系数
    timeouts.ReadTotalTimeoutConstant = 0; //读时间常量
    timeouts.WriteTotalTimeoutMultiplier = 50; // 写时间系数
    timeouts.WriteTotalTimeoutConstant = 2000; //写时间常量
    //总的读/写超时时间 = Read(Write)TotalTimeoutMultiplier x 要读/写的字节数 + Read(Write)TotalTimeoutConstant. 
    if (false==SetCommTimeouts(hCom, &timeouts))
    {
        setSerialLastError("SerialInterface::open() : SetCommTimeouts Error");
        return false;
    }



    //清空缓冲区,为读写串口做准备
    if (false == PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT))
    {
        setSerialLastError("SerialInterface::open() : PurgeComm Error");
        return false;
    }
    return true;
}
/*******************************************************************
* 名称: openSyn
* 功能: 同步方式打开串口(需自己配置串口参数)
* 参数:
    serial_name:串口名称
* 返回: 正确返回为ture,错误返回为false
*******************************************************************/
bool SerialInterface::openSyn(string serial_name)
{
	hCom = CreateFileA(
		serial_name.data(),//普通文件名或者设备文件名,这里是串口名
		GENERIC_READ | GENERIC_WRITE,//访问模式,读和写
		0,//共享模式,独占模式
		NULL,//指向安全属性的指针,不使用,传NULL
		OPEN_EXISTING,//如何创建,在串口中必须设置为OPEN_EXISTING。表示不能创建新端口只能打开已有的端口。
		FILE_ATTRIBUTE_NORMAL,//文件属性,使用默认属性FILE_ATTRIBUTE_NORMAL。
		NULL//用于复制文件句柄,通常这个参数设置为NULL,为空表示不使用模板
	);


	if (INVALID_HANDLE_VALUE == hCom)//出错判断
	{
		hCom = NULL;
        setSerialLastError("open():CreateFileA Error!");
		return false;
	}
	return true;
}
/*******************************************************************
* 名称: closeComm
* 功能: 关闭串口
* 参数: 无
* 返回: 正确返回为ture,错误返回为false
*******************************************************************/
void SerialInterface::closeComm()
{
    if(NULL==hCom)
        return;
    CloseHandle(hCom);
    hCom=NULL;
}
/*******************************************************************
* 名称: closeComm
* 功能: 判断串口是否打开
* 参数: 无
* 返回: 正确返回为ture,错误返回为false
*******************************************************************/
bool SerialInterface::isOpened()
{
    return NULL == hCom ? false : true;
}

DWORD SerialInterface::readData(char *buffer,int length)
{
    DWORD writeSize=0;

    bool ret=false;

    ret=ReadFile(hCom,buffer,length,&writeSize,NULL);

    if(false==ret)
        return 0;

    return writeSize;
}


DWORD SerialInterface::writeData(char *buffer,int length)
{
    DWORD writeSize=0;

    bool ret=false;

    ret=WriteFile(hCom,buffer,length,&writeSize,NULL);

    if(false==ret)
        return 0;

    return writeSize;

}


DWORD SerialInterface::writeStr(string str)
{
	bool ret = false;

	DWORD writeSize = 0;


	ret = WriteFile(hCom, str.data(), str.length(), &writeSize, NULL);

    if (0 == ret)
    {
        last_error = "Error By writeStr(string str)";
        return 0;
    }
		

    last_error = "";
	return writeSize;

}
/*******************************************************************
* 名称: setTimeouts
* 功能: 设置超时
* 参数:
    timeouts:超时配置的COMMTIMEOUTS结构体
* 返回: 正确返回为ture,错误返回为false
*******************************************************************/
bool SerialInterface::setTimeouts(COMMTIMEOUTS &timeouts)
{

    if (false == SetCommTimeouts(hCom, &timeouts))
    {
        setSerialLastError("SerialInterface::setTimeouts() : SetCommTimeouts Error");
        return false;
    }
    return true;
}
/*******************************************************************
* 名称: setDCB
* 功能: 设置串口信息
* 参数:
    dcb:串口信息配置的DCB结构体
* 返回: 正确返回为ture,错误返回为false
*******************************************************************/
bool SerialInterface::setDCB(DCB& dcb)
{
    if (false == SetCommState(hCom, &dcb))
    {
        setSerialLastError("SerialInterface::setDCB() : SetCommState Error");
        return false;
    }
    return true;
}
/*******************************************************************
* 名称: purgeBuff
* 功能: 刷新缓冲区
* 参数: 
    flags:需要完成的操作,取值如下
        PURGE_RXABORT 终止所有未完成的重叠读取操作并立即返回,即使读取操作尚未完成。
        PURGE_RXCLEAR 清除输入缓冲区(如果设备驱动程序有一个)。
        PURGE_TXABORT 终止所有未完成的重叠写操作并立即返回,即使写操作尚未完成。
        PURGE_TXCLEAR 清除输出缓冲区(如果设备驱动程序有一个)。
* 返回: 正确返回为ture,错误返回为false
* 提示:PurgeComm()函数可以在读写操作的同时,清空缓冲区。当应用程序在读写操作时
调用PurgeComm()函数,不能保证缓冲区内的所有字符都被发送。
*******************************************************************/
bool SerialInterface::purgeBuff(DWORD flags)
{

    if (false == PurgeComm(hCom, flags))
    {
        setSerialLastError("SerialInterface::purgeBuff() : PurgeComm Error");
        return false;
    }
    return true;
}
/*******************************************************************
* 名称:flushBuff
* 功能:刷新缓冲区
* 参数:无
* 返回:正确返回为ture,错误返回为false
* 提示:该函数只受流量控制的支配,不受超时控制的支配,它在所有的写操作完成后才返回。
*******************************************************************/
bool SerialInterface::flushBuff()
{
    if(FlushFileBuffers(hCom))
    {
        setSerialLastError("SerialInterface::flushBuff() : FlushFileBuffers Error");
        return false;
    }
    return true;
}
/*******************************************************************
* 名称: setBufferSize
* 功能: 设置推荐的缓冲大小
* 参数:
    inputBuff:输入缓冲大小
    outBuffer:输出缓冲大小
* 返回: 正确返回为ture,错误返回为false
*******************************************************************/
bool SerialInterface::setBufferSize(DWORD inputBuff,DWORD outBuffer)
{
    if(inputBuff<=0||outBuffer<=0)
        return false;
    
    return SetupComm(hCom,inputBuff,outBuffer);
}
/*******************************************************************
* 名称: getSerialLastError
* 功能: 得到最后一次失败的错误信息
* 参数: 无
* 返回: 数据类型:string,错误信息
*******************************************************************/
string SerialInterface::getSerialLastError()
{
    return last_error;
}

void SerialInterface::setSerialLastError(string error_msg)
{
    last_error = error_msg;
}
void SerialInterface::clearSerialLastError()
{
    last_error = "";
}
SerialInterface::SerialInterface()
{
    hCom=NULL;
}
SerialInterface::~SerialInterface()
{

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293

示例

创建两个虚拟串口

注意:这两个串口是连通的,给COM1发数据,COM2可以收到,反之亦然。
在这里插入图片描述## 用串口调试助手连接COM2来接数据

用串口调试助手连接COM2来接数据

在这里插入图片描述

编写测试代码发送数据

在这里插入图片描述
代码如下所示:

#include <iostream>
#include <cstdlib>
#include "SerialInterface.h"
#include <windows.h>
#include <tchar.h>

using namespace std;

int main()
{

    SerialInterface com;

    if(!com.openSyn("COM1", CBR_9600, NOPARITY,8, ONESTOPBIT))
    {
        cout << com.getSerialLastError() << endl;
        getchar();
        return 0;
    }
    //测试发送
    if (com.writeStr("Hello World!"))
    {
        cout << "send success" << endl;
    }
    else
    {
        cout << "send fail" << endl;
    }

    com.closeComm();


    //getchar();
    return 0;    
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

注意串口信息的配置要一致
在这里插入图片描述
参数的取值在函数的开头有详细的讲解,例如:

在这里插入图片描述

结果

在这里插入图片描述

总结

因为时间关系,只详细写了同步的串口操作,异步的情况后续有空会慢慢更新

此项目以经挂到GitHub:
https://github.com/LairdXavier/MyTool.git
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/837028
推荐阅读
相关标签
  

闽ICP备14008679号