日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > C# >内容正文

C#

C#调用C++函数来与串口通信

發(fā)布時(shí)間:2023/12/18 C# 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C#调用C++函数来与串口通信 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前些日子幫朋友寫個(gè)小軟件,要求用C#來(lái)實(shí)現(xiàn)主程序,主要的功能是與一些通信設(shè)備打交道,當(dāng)然就是通過(guò)串口了,以十進(jìn)制發(fā)送和讀取串口

的數(shù)據(jù),考慮到C#調(diào)用API并沒有C++來(lái)得方便,因此,我用C++封裝了一個(gè)讀寫串口的DLL,只提供一個(gè)函數(shù)供外部調(diào)用,這樣的好處在于,C#

只要調(diào)用這個(gè)函數(shù)發(fā)送完數(shù)據(jù)后,函數(shù)立即就能獲得串口返回的數(shù)據(jù)。另一個(gè)好處在于,一些不熟悉C++的朋友,也能夠直接通過(guò)這個(gè)DLL來(lái)對(duì)

串口做一些操作。

?? 雜話就不多講了,直接貼這個(gè)讀寫串口的dll代碼:

?一. C++部分:
? 1)頭文件:
?? // SerialPortSync.h: interface for the CSerialPortSync class.
//
//

#if !defined(AFX_SERIALPORTSYNC_H__7FC698BB_BF4D_449E_8DE9_62B8876187CF__INCLUDED_)
#define AFX_SERIALPORTSYNC_H__7FC698BB_BF4D_449E_8DE9_62B8876187CF__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CSerialPortSync??
{
public:
?CSerialPortSync();
public:
?bool Open(int nPort, int nBaud,int nDatabit, int nStopbit, int nParity, int nTimeOut = 500);
?DWORD SendData(const char *buffer, const unsigned int writebytes, char *RecBuffer, int nSendType = 1);
?void Close();
private:
?HANDLE m_hCom;?//串口句柄
?bool m_bOpened;

?char ConvertHexChar(char ch);
?int String2Hex(const char *str, const unsigned int nLen, byte *senddata);
};

#endif // !defined(AFX_SERIALPORTSYNC_H__7FC698BB_BF4D_449E_8DE9_62B8876187CF__INCLUDED_)

?

?2). CPP文件:

// SerialPortSync.cpp: implementation of the CSerialPortSync class.
//
//

#include "stdafx.h"
//#include "SerialPortDemo.h"
#include "SerialPortSync.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//
// Construction/Destruction
//
#define MAXSENDLENGTH 20?
#define MAXRECEIVELENGTH 20

CSerialPortSync::CSerialPortSync()
{
?m_bOpened = false;
}

/******************************************************************************
*函數(shù)功能:打開串口,設(shè)置串口參數(shù)
*參數(shù)說(shuō)明:
??? nCom:操作的串口值,如COM1:,COM2:等等
??? lnBaudrate: 波特率
??? nStopbits: 停止位
??? nDatabits: 數(shù)據(jù)位
??? nParity:奇偶校驗(yàn)
*返回值: 返回串口的句柄
*時(shí)間:2008/10/22
*作者:XiangDing
*****************************************************************************/
bool CSerialPortSync::Open(int nPort, int nBaud,int nDatabit,int nStopbit,int nParity, int nTimeOut)
{
?if( m_bOpened ) return( true );

?char strPort[10]={0};
?sprintf(strPort,"COM%d",nPort);

?m_hCom=CreateFile(strPort, GENERIC_READ|GENERIC_WRITE, 0, NULL ,OPEN_EXISTING, 0,NULL);
?if ((m_hCom==INVALID_HANDLE_VALUE) || (m_hCom==NULL ))
?{
??m_bOpened = false;
??return false;
?}

??? COMMTIMEOUTS ct;
??? ct.ReadIntervalTimeout???????? = MAXDWORD;????????????????????????????????? //設(shè)置超時(shí)設(shè)置
??? ct.ReadTotalTimeoutMultiplier? = 0;
??? ct.ReadTotalTimeoutConstant??? = nTimeOut;
??? ct.WriteTotalTimeoutMultiplier = 0;
??? ct.WriteTotalTimeoutConstant?? = nTimeOut;?
?SetCommTimeouts( m_hCom, &ct );

?DCB dcb;
?GetCommState( m_hCom, &dcb );
??? dcb.BaudRate?????????? = nBaud;
??? dcb.StopBits?????????? = nStopbit;
??? dcb.Parity???????????? = nParity;
??? dcb.ByteSize?????????? = (BYTE)nDatabit;?????? // number of bits/byte, 4-8

?BOOL bl = SetCommState( m_hCom, &dcb );

?m_bOpened = TRUE;
?
?return true;
}

// nSendType 1: 以十六進(jìn)制發(fā)送.? 0: 直接發(fā)送字符串
//返回值是已接收的個(gè)數(shù)
//返回 -1: 寫串口失敗. -2:清除串口錯(cuò)誤;? -3: 串口返回?cái)?shù)據(jù)為0;
DWORD CSerialPortSync::SendData(const char *sendBuffer, const unsigned int writebytes, char *RecBuffer, int nSendType)
{

?if( !m_bOpened ) return 0;
?
??? DWORD dwWritten = 0;
??? DWORD dwError;
?DWORD dwBytesRead = 0;


?if (nSendType == 1)
?{
??byte bHexData[MAXSENDLENGTH] = {0};
??memset(bHexData, 0, MAXSENDLENGTH);

??int len = String2Hex(sendBuffer, writebytes, bHexData);
??BOOL bWriteRet = FALSE;
??????? bWriteRet = WriteFile(m_hCom, bHexData, len, &dwWritten, NULL);
??
??BOOL bReadStatus;
??BYTE bReadBuf[MAXRECEIVELENGTH] = {0};

??bReadStatus = ReadFile( m_hCom, bReadBuf, MAXRECEIVELENGTH, &dwBytesRead, NULL);
??
??if (dwBytesRead <1 ) return dwBytesRead;

??CString strBuf;
??CString strTemp;
??for(int i=0; i<dwBytesRead; i++ )
??{
???strTemp.Format("%02X", bReadBuf[i]);
???strBuf += strTemp;
??}
??strBuf.TrimRight();
??strncpy(RecBuffer, (LPCTSTR)strBuf, dwBytesRead * 2 + 1);

??return dwBytesRead;
?}
?return dwBytesRead;
}

void CSerialPortSync::Close()
{???????????????????????????????????????????????????????????????????????????????
??? if(m_hCom != INVALID_HANDLE_VALUE)
??? {
??????? CloseHandle(m_hCom);?
??m_hCom = INVALID_HANDLE_VALUE;
??? }

?if( m_bOpened ) m_bOpened = false;
}


//由于這個(gè)轉(zhuǎn)換函數(shù)的格式限制,在發(fā)送框中的十六制字符應(yīng)該每?jī)蓚€(gè)字符之間插入一個(gè)空隔
//如:A1 23 45 0B 00 29
int CSerialPortSync::String2Hex(const char *str, const unsigned int nLen, byte *senddata)
{
?int hexdata,lowhexdata;
?int hexdatalen=0;
?int len=nLen;
?for(int i=0;i<len;)
?{
??char lstr,hstr=str[i];
??if(hstr==' ')
??{
???i++;
???continue;
??}
??i++;
??if(i>=len)
???break;
??lstr=str[i];
??hexdata=ConvertHexChar(hstr);
??lowhexdata=ConvertHexChar(lstr);
??if((hexdata==16)||(lowhexdata==16))
???break;
??else?
???hexdata=hexdata*16+lowhexdata;
??i++;
??senddata[hexdatalen]=(char)hexdata;
??hexdatalen++;
?}
//?senddata.SetSize(hexdatalen);
?return hexdatalen;
}

//這是一個(gè)將字符轉(zhuǎn)換為相應(yīng)的十六進(jìn)制值的函數(shù)
//功能:若是在0-F之間的字符,則轉(zhuǎn)換為相應(yīng)的十六進(jìn)制字符,否則返回-1
char CSerialPortSync::ConvertHexChar(char ch)?
{
?if((ch>='0')&&(ch<='9'))
??return ch-0x30;
?else if((ch>='A')&&(ch<='F'))
??return ch-'A'+10;
?else if((ch>='a')&&(ch<='f'))
??return ch-'a'+10;
?else?
??return (-1);
}


3) DLL導(dǎo)出函數(shù)實(shí)現(xiàn):
/*
返回值:
?-9: 打開串口失敗。
?-1: 往串口寫數(shù)據(jù)失敗。
?-2: 清除串口錯(cuò)誤失敗。
?-3: 串口返回?cái)?shù)據(jù)為0。
? 正值: 返回正常。
*/

SERIALPORT_DLL int __stdcall SendData(int nPort, int nBaud,int nDatabit,int nStopbit,
??int nParity, const char *sendBuffer, int writebytes,
??char *RecBuffer, int nSendType, int nTimeOut)

{

?CSerialPortSync sPort;
?if (!sPort.Open(nPort,nBaud,nDatabit,nStopbit,nParity))
?{
??return -9;
?}
?
?int nReadCount = sPort.SendData(sendBuffer, writebytes, RecBuffer);
?
?sPort.Close();

?return nReadCount;
}

?4). 我為什么要用類來(lái)實(shí)現(xiàn)C++的串口讀寫呢,主要也是方便C++開發(fā)人員可以直接使用該類,而C#的開發(fā)人員,直可以通過(guò)上面第三步,導(dǎo)出

到dll中,在C#中直接調(diào)用。


二. C#調(diào)用的代碼就更簡(jiǎn)單啦,像平常調(diào)API函數(shù)一樣,用DllImport聲明一下即可。這時(shí)就不多講了。

本人一直從事mobile/wince/linux平臺(tái)下開發(fā),使用C++雖有多年,但覺得自已對(duì)很多底層細(xì)節(jié)技術(shù)理解仍不夠深刻,希望有機(jī)會(huì)得到高手指點(diǎn)

總結(jié)

以上是生活随笔為你收集整理的C#调用C++函数来与串口通信的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。