最近测试一款产品的时候用到了 windows下的串口开发的内容,稍微记录一下,以后再用到 直接来拷代码就好了。

1. 需求介绍

只是开发一个临时的程序 可以简单的去分析一下 从串口发过来的数据都是什么,可以将串口数据打印到控制台上,当然 也可以将这些数据进行一些其他的操作,比如进行数据的拼接,转换,校验等等 ,当然 这个后话 第一步就是通过我们的程序拿到串口的数据,这是最基本的。

2. 代码的分析

代码的查找过程也不去介绍了,大致就是在网上找类似的代码 然后 这边抄点 那边抄点 就出来了一份简单的demo 了。
直接上代码,关于我的分析 也都放到了代码的注释中,所以请认真看代码!

声明 : 代码源自网络 代码注释中解释了代码来自这位大佬 代码出处找不到了,没法选择转载。。。。 望见谅 当时找了好多份代码。
在这里插入图片描述在这里插入图片描述

CMakeLists.txt

project(serial CXX)
add_executable(app 
    UPRE_Windows_Usart.cpp
    serial_test.cpp
)

serial_test.cpp

#include "windows.h"
#include "iostream"
#include "UPRE_Windows_Usart.hpp"
#include  "cstdio"
#include "string.h"
#include "math.h"
#include <stdint.h>
using namespace std;
using namespace UPRE;
//usage ./app.exe COMx
int main(int argc,char** argv)
{
	UPRE::v_uchar data(100);
	UPRE::Windows_Usart usart;
	int baudrate = 115200;
	if (argc == 2) {
		usart.open(argv[1], baudrate);
	}
	else {
		cout << "usage:  ./app.exe COMx " << endl;
		exit(0);
	}
	int readlen;
	while (1) 
	{
		if ((readlen = usart.Read_Data(data,1)) > 0) 
		{
			for(uint8_t i = 0;i< readlen;i++){
				printf("%02x ",data[i]);				
			}
			usart.Write_Data(data,readlen);
		}			
	}
}

UPRE_Windows_Usart.hpp

/*---------------------------------使用说明-------------------------------
使用:
将UPRE_Windows_Usart.cpp文件和UPRE_Windows_Usart.hpp文件放在工程目录下,在要使
用的文件中包含UPRE_Linux_Usart.hpp文件即可。Windows_Usart类封装了串口的相关函数。
            成员函数列表:
			public:
					Windows_Usart
					~Windows_Usart
					Read_Data
					Write_Data
					Get_HANDLE
注意:
      1、Windows_Usart类定义在 UPRE 命名空间下。
      2、如果在Visual Stdio 中使用提示CreatFile函数的第一个参数有问题,可以将Visual Stdio的字符集设置为多字节字符集。
	         (1)打开项目属性
			 (2)选择常规属性页
			 (3)将“字符集”属性修改为“使用多字节字符集”

声明:UPER_Windows_Usart.hpp和UPER_Windows_Usart.cpp文件内的代码为学习之用,使用中出现的任何的问题和后果自行负责,与作者和UPRE实验室无关。  

作者:丁欣童
-------------------------------------------------------------------------*/
#ifndef _UPRE_WINDOWS_USART_HPP_ 
#define _UPRE_WINDOWS_USART_HPP_

#include "Windows.h"
#include "vector"

namespace UPRE 
{
	typedef std::vector<unsigned char> v_uchar;

	class Windows_Usart 
	{
	public:
		/*--------------------------------------------------------
		@函数:Windows_Usart
		@功能:Windows_Usart类的构造函数,打开并初始化串口。
		@参数:参数一:flag为USART_NUM类型的枚举,代表要打开并初始化的串口。
		               有默认值COM1。
		       参数二:rate为串口速率,可选参数,有默认值115200。取值为任意。
		--------------------------------------------------------*/
		Windows_Usart();
		
		Windows_Usart(const char * com, int rate = 115200);
		
		void open(const char * com, int rate = 115200);
		

		/*--------------------------------------------------------
		@函数: ~Windows_Usart
		@功能:Windows_Usart类的析构函数,关闭串口。
		--------------------------------------------------------*/
		~Windows_Usart();
		
		
		/*--------------------------------------------------------
		@函数:Write_Data
		@功能:从data中向串口写入writeLengh个字节的数据。
		@参数:参数一:data为unsigned char类型的vector,为要写入的数据
		       参数二:writeLengh 要写入的字节个数。有默认值0,表示把data
		               全部写入。
		       参数三: startLocation为操作data的起始位置。默认为0,表示从data[0]开始读取。
		@返回值:返回写入进的字节数,如写入失败,则返回 -1
		--------------------------------------------------------*/
		size_t Write_Data(v_uchar &data, size_t writeLengh = 0, size_t startLocation = 0);
		
		
		/*--------------------------------------------------------
		@函数:Read_Data
		@功能:从串口读取readLengh个字节的数据存到data中。
		@参数:参数一:data为unsigned char类型的vector,读出的数据存在data
		               对象里。
		       参数二:readLengh 要读取的字节个数。有默认值0,表示读取和data
		               长度大小一样的字节数。
		       参数三: startLocation为操作data的起始位置。默认为0,表示从data[0]开始写入。
		@返回值:返回读取到的字节数。
		--------------------------------------------------------*/
		size_t Read_Data(v_uchar &data, size_t readLengh = 0, size_t startLocation = 0);
		
		
		/*--------------------------------------------------------
		@函数:Get_HANDLE
		@功能:获取当前Linux_Usart对象的串口描述符fd。
		       借助这个函数可以用WriteFile函数和ReadFile函数直接操作串口。
		@返回值:串口句柄
		--------------------------------------------------------*/
		HANDLE Get_HANDLE();
	private:
		
		/*--------------------------------------------------------
		@变量:HANDLE
		@功能:CreateFile函数返回的串口句柄。
		--------------------------------------------------------*/
		HANDLE serial;
	};
}
#endif 


UPRE_Windows_Usart.cpp

#include "UPRE_Windows_Usart.hpp"

#include "vector"
#include "iostream"


using namespace UPRE;
using namespace std;

UPRE::Windows_Usart::Windows_Usart()
{
}

Windows_Usart::Windows_Usart(const char * com, int rate)
{
	this->open(com, rate);
}

void UPRE::Windows_Usart::open(const char * com, int rate)
{
	DCB serial_opt;
	serial = CreateFile(com, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
	if (serial == INVALID_HANDLE_VALUE)
	{
		cout << "open failed" << endl;
		exit(0);
	}
	if (GetCommState(serial, &serial_opt) == 0)
	{
		cout << "GetCommState failed" << endl;
		exit(0);
	}
	serial_opt.BaudRate = rate;
	serial_opt.fParity = FALSE;
	serial_opt.fBinary = TRUE;
	serial_opt.ByteSize = 8;
	serial_opt.StopBits = ONESTOPBIT;
	serial_opt.fAbortOnError = FALSE;
	serial_opt.Parity = NOPARITY;
	if (SetCommState(serial, &serial_opt) == 0)
	{
		cout << "SetCommState failed" << endl;
	}
	cout << "successful to open " << com << endl;	
}

Windows_Usart::~Windows_Usart() 
{
	CloseHandle(serial);
}

size_t Windows_Usart::Write_Data(v_uchar &data, size_t writeLengh, size_t startLocation) 
{
	DWORD writeNum;
	if (writeLengh == 0) 
	{
		writeLengh = data.size();
	}
	if (writeLengh > data.size() - startLocation) 
	{
		cout << "error : 数组越界" << endl;
		return 0;
	}
	if (WriteFile(serial, &data[startLocation], writeLengh, &writeNum, NULL)) 
	{
		return writeNum;
	}
	else 
	{
		return 0;
	}
}
// 这个函数是阻塞的读取指定的字节的数据,读取不到指定的数据帧 就不会退出!!!
size_t Windows_Usart::Read_Data(v_uchar &data, size_t readLengh, size_t startLocation) 
{
	DWORD readNum;
	if(readLengh==0)
	{
		readLengh = data.size();
    }
	if (readLengh > data.size() - startLocation)
	{
		cout << "error : 数组越界" << endl;
		return 0;
	}
	if (ReadFile(serial, &data[startLocation], readLengh, &readNum, NULL))
	{
		return readNum;
	}
	else
	{
		return 0;
	}
}

HANDLE Windows_Usart::Get_HANDLE()
{
	return serial;
}

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐