modbus串口通信代码示例

modbus_rtu 代码示例

1.目前编写modbus_rtu控制钧舵的产品,控制夹爪的开关,modbus_rtu主要掌握如下几点:
1>串口打开
2>串口读写
3>串口报文组包
4>串口报文校验
5>串口关闭

下列为vs2015 mfc工程编写代码示例:
串口打开代码:

xxx.cpp

#include "stdafx.h"
#include "Serial.h"
#include "afxmt.h"
#include <time.h>
#include <process.h>

CSerial::CSerial()
{
    
    
	m_hCom = NULL;
}

CSerial::~CSerial()
{
    
    
	//500ms
	Sleep(500);
	CloseSerial();
}

bool CSerial::OpenSerial(int com,int baud,int parity,int bytesize,int stopbit)
{
    
    
	char msg[100];
	BOOL result;
	DCB dcb;
	CString comName;

	char buf[256];
	memset(buf, 0, 256);
	m_sCom = com, m_baud = baud, m_parity = parity, m_bytesize = bytesize, m_stopbit = stopbit;
	sprintf_s(buf, "serial=%d,baud=%d,parity=%d,bytesize=%d,stopbit=%d", m_sCom, m_baud, m_parity, m_bytesize, m_stopbit);
	_cprintf("%s\n", buf);

	//_T会根据项目选择的无编码和多编码来决定一个字符占的位数
	comName.Format(_T("\\\\.\\COM%d"), m_sCom);

	//1.获取串口句柄
	CloseSerial();
	m_hCom = CreateFile(comName, GENERIC_READ | GENERIC_WRITE,
		0,//独占方式
		NULL, OPEN_EXISTING,
		NULL,
		NULL);
	if (m_hCom == INVALID_HANDLE_VALUE)
	{
    
    
		CString str;
		str.Format(_T("串口%s不存在或已坏!"), comName);
		USES_CONVERSION;
		_cprintf("%s\n", W2A(str));
		CloseSerial();
		return false;
	}

	//2.初始化输入/输出缓冲区大小
	result = SetupComm(m_hCom, 512, 512);
	if (!result) 
	{
    
    
		return false;
	}

	//3.获得设备句柄的当前参数
	result = GetCommState(m_hCom, &dcb);
	if (!result)
	{
    
    
		return false;
	}

	//4.设置串口波特率
	dcb.BaudRate = m_baud;

    //5.设置串口为奇/偶校验为NONE
	dcb.Parity = m_parity;

	//6.设置串口数据位
	dcb.ByteSize = m_bytesize;

    //7.设置串口停止位
	int sbit;
	if (m_stopbit == 1)
	{
    
    
		sbit = ONESTOPBIT;
	}
	else if (m_stopbit == 2)
	{
    
    
		sbit = TWOSTOPBITS;
	}
	else 
	{
    
    
		sbit = ONE5STOPBITS;
	}
	dcb.StopBits = sbit;

	//8.
	dcb.fOutX = 0;
	dcb.fInX = 1;
	dcb.fRtsControl = RTS_CONTROL_DISABLE;//RTS_CONTROL_HANDSHAKE;
	dcb.fDtrControl = DTR_CONTROL_DISABLE;

	//9.更新设备句柄的参数
	result = SetCommState(m_hCom, &dcb);
	if (!result)
	{
    
    
		int dwLastError = GetLastError();
		sprintf(msg, "串口:SetComState error(%d)", dwLastError);
		_cprintf("%s\n", msg);
		return false;
	}

	//10.设置串口读入/写出等候超时时间
	COMMTIMEOUTS timeout;
	result = GetCommTimeouts(m_hCom, &timeout);
	if (!result)
	{
    
    
		int dwLastError = GetLastError();
		sprintf(msg, "串口:GetComTimeouts error(%d)", dwLastError);
		_cprintf("%s\n", msg);
		return false;
	}
	timeout.ReadIntervalTimeout = MAXDWORD;
	timeout.ReadTotalTimeoutMultiplier = 0;
	timeout.ReadTotalTimeoutConstant = 0;
	timeout.WriteTotalTimeoutMultiplier = 0;
	timeout.WriteTotalTimeoutConstant = 0;
	result = SetCommTimeouts(m_hCom, &timeout);

	if (!result)
	{
    
    
		int dwLastError = GetLastError();
		sprintf(msg, "串口:SetComTimeouts error(%d)", dwLastError);
		_cprintf("%s\n", msg);
		return false;
	}

	//11.清除输入/输出缓冲区内的数据
	result = PurgeComm(m_hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
	if (!result)
	{
    
    
		int dwLastError = GetLastError();
		sprintf(msg, "串口:PurgeCom error(%d)", dwLastError);
		_cprintf("%s\n", msg);
		return false;
	}

	//mfc的工作线程,必须为全局函数或静态函数
	//AfxBeginThread(OnRead, LPVOID(this), THREAD_PRIORITY_LOWEST);
	sprintf(msg, "打开串口%d成功", m_sCom);
	_cprintf("%s\n", msg);
	return true;
}

bool CSerial::CloseSerial()
{
    
    
	if (m_hCom != NULL)
	{
    
    
		CloseHandle(m_hCom);
		m_hCom = NULL;
		_cprintf("%s\n", "串口通道关闭");
	}
	return true;
}

//bool CSerial::GetState()
//{
    
    
//	if (m_hCom)
//	{
    
    
//		return true;
//	}
//	else 
//	{
    
    
//		return false;
//	}
//}

int CSerial::Read(BYTE * lpBuf)
{
    
    
	BOOL result = FALSE;
	BYTE buff[1024] = {
    
     0 };
	DWORD nRead = 0;

	result = ReadFile(m_hCom, buff, 1024, &nRead, NULL);
	if (!result)
	{
    
    
		if (GetLastError() == ERROR_HANDLE_EOF)
		{
    
    
			char msg[256] = {
    
     0 };
			sprintf(msg, "OnRead关闭通道,错误码%d\n", ERROR_HANDLE_EOF);
			CloseSerial();
			return -1;
		}
	}
	else
	{
    
    
		memcpy(lpBuf, buff, nRead);
		_cprintf("Rx: ");
		for (int i = 0;i < nRead;i++)
		{
    
    
			char buf[4096] = {
    
     0 };
			sprintf(buf, "%02X ", lpBuf[i]);
			_cprintf("%s", buf);
		}
		_cprintf("\n");
	}
	return nRead;
}

int CSerial::Write(BYTE * lpBuf, int len)
{
    
    
	DWORD nWrite = 0;
	BOOL result = WriteFile(m_hCom, lpBuf, (DWORD)len, &nWrite, NULL);
	if ((!result) || (len != nWrite))
	{
    
    
		_cprintf("%s\n", "发送数据失败");
		if ((GetLastError() == ERROR_INVALID_HANDLE) || (GetLastError() == ERROR_ACCESS_DENIED))
		{
    
    
			CloseSerial();
			return -1;
		}
	}
	else
	{
    
    
		//解析报文:
	}
	return nWrite;
}

xxx.h

#pragma once
#ifndef _SERIAL_H__
#define _SERIAL_H__
#include<conio.h>
#include <iostream>
#include <map>
#include <locale.h>// setlocale函数的头文件
using namespace std;
#pragma warning(disable:4996)

typedef map<string, string> PARA;//存放串口配置文件参数
//#include "common.h"

//串口通信主要四步:
//1.设置初始化并打开串口
//2.配置串口
//3.串口上传输数据,传输过程中并校验
//4.不需要此串口,关闭串口

class CSerial
{
    
    
public:
	CSerial();
	~CSerial();

	//打开串口
	bool OpenSerial(int com, int baud, int parity, int bytesize, int stopbit);

	//关闭串口
	bool CloseSerial();

	//普通模式读
	int Read(BYTE * lpBuf);
	
	//普通模式写
	int Write(BYTE * lpBuf, int len);
public:
	int m_sCom;     //串口号
	int m_baud;    //波特率
	int m_parity;  //校验
	int m_bytesize; //数据位
	int m_stopbit; //停止位

	HANDLE m_hCom;//串口句柄
};

#endif

代码下载地址:
链接:https://pan.baidu.com/s/1n001s1RIBhPbf5Hbt2bs0w
提取码:pw8z

猜你喜欢

转载自blog.csdn.net/xt18971492243/article/details/115318104
今日推荐