C++编写台达ME300变频器串口通讯实例
用C++编写台达ME300变频器串口通讯,读取变频器频率设定值,将接收的16进制数值转为十进制数值显示。
1、RS485CommDlg.h中代码
class CRS485CommDlg : public CDialog
{
// Construction
public:
CRS485CommDlg(CWnd* pParent = NULL); // standard constructor
int hexToDecimal(const char* hexNum);
int getDicimalByChar(char a);
int selfPow(int baseNum, int &tempRes, int exp);
}
2、RS485CommDlg.cpph中代码
// RS485CommDlg.cpp : implementation file
//
#include "stdafx.h"
#include "RS485Comm.h"
#include "RS485CommDlg.h"
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CRS485CommDlg::CRS485CommDlg(CWnd* pParent /*=NULL*/)
: CDialog(CRS485CommDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CRS485CommDlg)
m_disp = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CRS485CommDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CRS485CommDlg)
DDX_Text(pDX, IDC_DISP, m_disp);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CRS485CommDlg, CDialog)
//{{AFX_MSG_MAP(CRS485CommDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_SEND, OnSend)
ON_BN_CLICKED(IDC_RECEIVE, OnReceive)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CRS485CommDlg message handlers
HANDLE hCom;//全局变量,串口句柄
BOOL CRS485CommDlg::OnInitDialog()
{
CDialog::OnInitDialog();
hCom=CreateFile("COM5",// 串口名称
GENERIC_READ|GENERIC_WRITE,//允许读和写
0,//独占方式
NULL,
OPEN_EXISTING,//打开而不是创建
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,//重叠方式
NULL);
if(hCom==(HANDLE)-1)
{
MessageBox("打开 COM 失败!");
return FALSE;
}
SetupComm(hCom,100,100);//输入缓冲区和输出缓冲区的大小都是 100
COMMTIMEOUTS TimeOuts;
//设定读超时
TimeOuts.ReadIntervalTimeout=MAXDWORD;
TimeOuts.ReadTotalTimeoutMultiplier=0;
TimeOuts.ReadTotalTimeoutConstant=0;
//在读一次输入缓冲区的内容后读操作就立即返回,
//而不管是否读入了要求的字符.
//设定写超时
TimeOuts.WriteTotalTimeoutMultiplier=100;
TimeOuts.WriteTotalTimeoutConstant=500;
SetCommTimeouts(hCom,&TimeOuts);//设置超时
DCB dcb;
GetCommState(hCom,&dcb);
dcb.BaudRate=9600;//波特率为 9600
dcb.ByteSize=8;//每个字节有 8 位
dcb.Parity=NOPARITY;//无奇偶校验位
dcb.StopBits=ONESTOPBIT;//TWOSTOPBITS;//两个停止位
SetCommState(hCom,&dcb);
PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CRS485CommDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
void CRS485CommDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
HCURSOR CRS485CommDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CRS485CommDlg::OnSend()
{
OVERLAPPED m_osWrite;
memset(&m_osWrite,0,sizeof(OVERLAPPED));
m_osWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
char lpOutBuffer[8];
memset(lpOutBuffer,'\0',8);
lpOutBuffer[0]='\x01';
lpOutBuffer[1]='\x03';
lpOutBuffer[2]='\x21';
lpOutBuffer[3]='\x02';
lpOutBuffer[4]='\x00';
lpOutBuffer[5]='\x02';
lpOutBuffer[6]='\x6F';
lpOutBuffer[7]='\xF7';
DWORD dwBytesWrite=8;
COMSTAT ComStat;
DWORD dwErrorFlags;
BOOL bWriteStat;
DWORD bytesWritten;
ClearCommError(hCom,&dwErrorFlags,&ComStat);
//bWriteStat=WriteFile(hCom,lpOutBuffer, dwBytesWrite,& dwBytesWrite,&m_osWrite);
bWriteStat=WriteFile(hCom,lpOutBuffer, sizeof(lpOutBuffer),&bytesWritten,&m_osWrite);
if(!bWriteStat)
{
if(GetLastError()==ERROR_IO_PENDING)
{
WaitForSingleObject(m_osWrite.hEvent,1000);
}
}
}
void CRS485CommDlg::OnReceive()
{
// TODO: Add your control notification handler code here
OVERLAPPED m_osRead;
memset(&m_osRead,0,sizeof(OVERLAPPED));
m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
COMSTAT ComStat;
DWORD dwErrorFlags;
char str[100];
memset(str,'\0',100);
DWORD dwBytesRead=100;//读取的字节数
DWORD bytesRead;
BOOL bReadStat;
ClearCommError(hCom,&dwErrorFlags,&ComStat);
dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);
bReadStat=ReadFile(hCom,str,dwBytesRead,&bytesRead,&m_osRead);
CString c=str;
if(!bReadStat)
{
if(GetLastError()==ERROR_IO_PENDING)
//GetLastError() 函数返回ERROR_IO_PENDING,表明串口正在进行读操作
{
WaitForSingleObject(m_osRead.hEvent,2000);
}
}
PurgeComm(hCom,PURGE_TXABORT|
PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
CString RecText="",str2;
for(int i=0;i<9;i++)
{
str2.Format("%02X ",str[i]);//将接收到的BYTE型数据转换为对应的十六进制
str2=str2.Right(3);
RecText=RecText+ str2;
}
m_disp=RecText;
CString RecText1="",str21;
for( i=0;i<9;i++)
{
str21.Format("%02X",str[i]);//将接收到的BYTE型数据转换为对应的十六进制
str21=str21.Right(2);
RecText1=RecText1+ str21;
}
SetDlgItemText(IDC_STATIC1, RecText1);
CString RecText11="",str211;
for( i=0;i<9;i++)
{
str211.Format("%02X",str[i]);//将接收到的BYTE型数据转换为对应的十六进制
str211=str211.Right(2);
RecText11=RecText11+ str211;
}
RecText11=RecText11.Right(12);
RecText11=RecText11.Left(4);
CString str4;
SetDlgItemText(IDC_STATIC2, RecText11);
CString str5,str6;
int res=hexToDecimal(RecText11);
double res1=res/100;
str5.Format("设定频率:%.1f",res1);
SetDlgItemText(IDC_STATIC3,str5);
UpdateData(FALSE);
}
int CRS485CommDlg::hexToDecimal(const char* hexNum)
{
int res = 0;
vector<char> temp;
for (int i = 0; hexNum[i] != NULL; i++)
{
temp.insert(temp.begin(), hexNum[i]);
}
for ( i = 0; i< temp.size(); i++)
{
int tempD = getDicimalByChar(temp.at(i));
int tempRes = 1;
res += tempD * selfPow(16, tempRes, i); // pow(16, i)
}
return res;
}
int CRS485CommDlg::getDicimalByChar(char a)
{
int res = 0;
char b = '\0';
if (a >= 'a' && a <= 'f')
{
b = a - 32;
}
else {
b = a;
}
if (b >= 'A' && b <= 'F')
{
res = b - 55;
}
else if (b >= '0' && b <= '9')
{
res = b - 48;
}
else
{
return -1;
}
return res;
}
int CRS485CommDlg::selfPow(int baseNum, int &tempRes, int exp)
{
if (exp == 0)
{
return tempRes;
}
else
{
tempRes = baseNum* tempRes;
exp--;
selfPow(baseNum, tempRes, exp);
}
}
运行程序