IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> Windows下的串口同通信及类的封装 -> 正文阅读

[嵌入式]Windows下的串口同通信及类的封装

Windows下的串口同通信及类的封装

最近用到了串口编程,所以写篇随笔将其记录下来,能为其他人提供到一点帮助也好。

Windows下串口通信的基本流程

先来梳理一下在Windows下对串口读写数据操作的基本流程。在Windows下(linux也是)串口的读写是以文件的方式去操作的,所以使用WindowsAPI:CreateFile来打开串口,代码为:

	LPCTSTR Comname = _T("COM3");
	HANDLE hSerial;
	//API原型就不列了,可以去看文档,为了体流程这里使用方法。
	//要注意的是第一个参数Comname为要打开的串口名,第六参数FILE_FLAG_OVERLAPPED为使用异步方式打开串口。
	hSerial = CreateFile(Comname, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	if (hSerial == INVALID_HANDLE_VALUE)
	{
		printf("open fail \n");
		CloseHandle(hSerial);
		return -1;
	}

打开串口后我们对串口设置缓冲去的大小:

//第一个参数为打开的串口,后面分别为设备内部读和写缓冲区的大小。
	SetupComm(hSerial, 1024, 1024);

接下来开始设置串口的参数:

	DCB dcb;
	GetCommState(hSerial, &dcb);//获取当前的配置保存到dcb
	dcb.DCBlength = sizeof(DCB);
	dcb.BaudRate = CBR_115200;//设置串口波特率
	dcb.ByteSize = 8;//设置一个字节的长度
	dcb.StopBits = ONESTOPBIT;//设置停止位
	dcb.Parity = NOPARITY;//设置校验位
	SetCommState(hSerial, &dcb); //最后把存有配置信息的dcb设置给串口

然后对串口设置超时

	COMMTIMEOUTS timeout; //创建一个端口超时结构体
	timeout.ReadIntervalTimeout = MAXDWORD;
	timeout.ReadTotalTimeoutConstant = 0;
	timeout.ReadTotalTimeoutMultiplier = 0;
	timeout.WriteTotalTimeoutConstant = 500;
	timeout.WriteTotalTimeoutMultiplier = 5000;
	SetCommTimeouts(hSerial, &timeout);//设定好参数后将其设置给串口
	PurgeComm(hSerial, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);//最后对串口进行一下清空操作。

由于我们使用异步的方式打开的串口,所以需要一个OVERLAPPED结构,先创建它后面会用到

	OVERLAPPED ov_write, ov_read;
	memset(&ov_write, 0, sizeof(OVERLAPPED));//初始化
	memset(&ov_read, 0, sizeof(OVERLAPPED));
	ov_write.hEvent = CreateEvent(NULL, false, false, NULL);//创建事件
	ov_read.hEvent = CreateEvent(NULL, false, false, NULL);

然后为串口设置言关心的事件

SetCommMask(hSerial, EV_RXCHAR);//绑定串口接收到字符的事件

然后就是获取串口接收到的内容了,这里新开一个线程去后台监听串口是否收到数据,当有数据时将数据取出来,首先需要写一个读取串口的方法:

void readData(HANDLE serial, OVERLAPPED* ov_r)
{
	DWORD dwGetEventMask = 0;
	DWORD TrByte = 0;
	BOOL Status = 0;
	DWORD CError = 0;
	COMSTAT comstat;
	char readBuffer[1024] = { 0 };
	
	while (true)
	{
		Status = WaitCommEvent(serial, &dwGetEventMask, ov_r);
		if (Status == FALSE && GetLastError() == ERROR_IO_PENDING)
		{
			Status = GetOverlappedResult(serial, ov_r, &TrByte, TRUE);
		}
		ClearCommError(serial, &CError, &comstat);
		if (Status == TRUE && dwGetEventMask & EV_RXCHAR && comstat.cbInQue > 0)
		{
			DWORD readedSize = 0;
			memset(readBuffer, 0, sizeof(readBuffer));
			Status = ReadFile(serial, readBuffer, sizeof(readBuffer), &readedSize, ov_r);
			if (Status)
			{
				std::cout << "Read: " << readBuffer << std::endl;
			}

			PurgeComm(serial, PURGE_RXABORT | PURGE_RXCLEAR);
		}
	}
}

然后在刚才SetCommMask(hSerial, EV_RXCHAR);的后面启动线程去执行这个函数

std::thread readThread(&readData, hSerial, &ov_read);

至此便开始了对串口的监听,如果要向串口调用WindowsAPI函数WriteFile即可:

WriteFile(hSerial, writeBuffer, sizeof(writeBuffer), &writedSize, &ov_write);

C++封装

最后为了方便以后的复用,我使用C++对其进行了封装形成一个类,使用方法也简单了很多,以下为一个简单的示例:

//新建应用程序
#include "JSerialPortTool.h"

void showReadContant(char*indata);//槽函数,串口接收到数据后调用此函数,并把接收到的内容传给indata
int main()
{
	JSerialPortTool serialTool(_T("COM1")); //构造时传入串口名
	serialTool.SetComConf(CBR_115200, 8, 1, NOPARITY);//设置波特率、字节长度、停止位和校验位
	serialTool.SetTimeOut(MAXDWORD, 0, 0, 500, 5000);//设置超时参数

	serialTool.connectReadSlot(showReadContant);//绑定槽函数,在串口接收到数据后调用绑定的方法

	while (true)
	{
		char writebuff[1024] = { 0 };
		std::cin >> writebuff;
		serialTool.WriteData(writebuff);//调用WriteData成员函数向串口写数据
	}
	return 0;
}

void showReadContant(char*indata)
{
	std::cout << "get contance:" << indata << std::endl;
}

资源下载

CSDN下载
Gitee下载

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-16 18:59:57  更:2021-11-16 19:00:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:34:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码