求vc 串口通信源码

求vc 串口通信源码,第1张

我这边有,已经成功应用于项目中!

//送到窗口的消息 WPARAM 端口号

#define ON_COMM_RECEIVE WM_USER+2009

#define ON_COMM_ERROR WM_USER+2010

#define ON_COMM_CTS WM_USER+2011

#define ON_COMM_DSR WM_USER+2012

#define ON_COMM_BREAK WM_USER+2013

#define ON_COMM_TXEMPTY WM_USER+2014

#define ON_COMM_RING WM_USER+2015

#define ON_COMM_RLSD WM_USER+2016

// changed 2011.4.07 收到特定字符事件 而不是收到任何字符 EV_RXCHAR-->EV_RXFLAG

#define DEFALUT_COM_MASK_EVENT EV_RXFLAG | EV_ERR | EV_CTS | EV_DSR | EV_BREAK | EV_TXEMPTY | EV_RING | EV_RLSD

class CCom

{

public:

//------------------------------Construction-----------------------------------

//第1个参数为是否在打开串口时启动监视线程, 第2个参数为IO方式 阻塞方式(0)/ 异步重叠方式(默认)

CCom(BOOL bAutoBeginThread = TRUE, DWORD dwIOMode = FILE_FLAG_OVERLAPPED)

virtual ~CCom()

//----------------------------------Operations----------------------------------

//打开串口 缺省 9600, 8, n, 1

BOOL Open(DWORD dwPort)

//打开串口 缺省 baud_rate, 8, n, 1

BOOL Open(DWORD dwPort, DWORD dwBautRate)

//打开串口, 使用类似"9600, 8, n, 1"的设置字符串设置串口

BOOL Open(DWORD dwPort, char* szSetStr)

//读取串口 dwBufferLength个字符到 Buffer 返回实际读到的字符数 可读任意数据

DWORD Read(LPVOID Buffer, DWORD dwBufLength, DWORD dwWaitTime = 10)

//读取串口 dwBufferLength - 1 个字符到 szBuffer 返回ANSI C 模式字符串指针 适合一般字符通讯

char* ReadString(char* szBuffer, DWORD dwBufferLength, DWORD dwWaitTime = 20)

//读串口 同步应用

DWORD ReadSync(LPVOID Buffer, DWORD dwBufferLength)

//写串口 可写任意数据 "abcd" or "\x0\x1\x2"

DWORD Write(LPVOID Buffer, DWORD dwBufferLength, DWORD dwWaitTime = 20) // changed 2011.4.1 增加了第三个默认参数

//写串口 写ANSI C 模式字符串指针

DWORD Write(const char* szBuffer)

//写串口 同步应用

DWORD WriteSync(LPVOID Buffer, DWORD dwBufferLength)

//写串口 szBuffer 可以输出格式字符串 包含缓冲区长度

DWORD Write(char* szBuffer, DWORD dwBufferLength, char* szFormat, ...)

//写串口 szBuffer 可以输出格式字符串 不检查缓冲区长度 小心溢出

DWORD Write(char* szBuffer, char* szFormat)

//关闭串口 同时也关闭关联线程

virtual void Close()

struct InnerLock

{

CCom* ptr

InnerLock(CCom* p) : ptr(p)

{

ptr->Lock()

}

~InnerLock()

{

ptr->UnLock()

}

}

//锁定资源

void Lock()

{

::EnterCriticalSection(&m_mutex)

}

void UnLock()

{

::LeaveCriticalSection(&m_mutex)

}

//DTR 电平控制

BOOL SetDtr(BOOL OnOrOff)

{

return IsOpen()? EscapeCommFunction(m_hComHandle, OnOrOff? SETDTR : CLRDTR) !=0 : FALSE

}

//RTS 电平控制

BOOL SetRts(BOOL OnOrOff)

{

return IsOpen()? EscapeCommFunction(m_hComHandle, OnOrOff? SETRTS : CLRRTS) != 0 : FALSE

}

BOOL SetBreak(BOOL OnOrOff)

{

return IsOpen()? EscapeCommFunction(m_hComHandle, OnOrOff? SETBREAK : CLRBREAK) != 0 : FALSE

}

//辅助线程控制 建监视线程

BOOL BeginThread()

//暂停监视线程

inline BOOL SuspendThread()

{

return IsThreadRunning()? ::SuspendThread(m_hThreadHandle) != 0xFFFFFFFF : FALSE

}

//恢复监视线程

inline BOOL ResumeThread()

{

return IsThreadRunning()? ::ResumeThread(m_hThreadHandle) != 0xFFFFFFFF : FALSE

}

//终止线程

BOOL EndThread(DWORD dwWaitTime = 100)

//----------------------------------Attributes----------------------------------

//判断串口是或打开

inline BOOL IsOpen() {return m_hComHandle != INVALID_HANDLE_VALUE}

//获得串口句炳

HANDLE GetHandle() {return m_hComHandle}

//获得串口序号

const int GetPortID() {return m_dwPort}

//获得串口全名

const char* GetPortName() {return m_szComStr}

//获得串口参数 DCB

DCB* GetState()

{

return IsOpen() &&::GetCommState(m_hComHandle, &m_DCB) == TRUE ? &m_DCB : NULL

}

//设置串口参数 DCB

BOOL SetState(DCB* pDCB = NULL)

{

return IsOpen() ? SetCommState(m_hComHandle, pDCB == NULL? &m_DCB : pDCB) == TRUE : FALSE

}

//设置串口参数:波特率,停止位,等 支持设置字符串 "9600, 8, n, 1"

BOOL SetState(char* szSetStr)

//设置串口参数:波特率,停止位,等

BOOL SetState(DWORD dwBautRate, DWORD dwByteSize = 8, DWORD dwParity = NOPARITY, DWORD dwStopBits = ONESTOPBIT)

//获得超时结构

LPCOMMTIMEOUTS GetTimeouts()

{

return IsOpen()&&::GetCommTimeouts(m_hComHandle, &m_ComTimeOuts) == TRUE ? &m_ComTimeOuts : NULL

}

//设置超时

BOOL SetTimeouts(LPCOMMTIMEOUTS lpCO)

{

return IsOpen()? ::SetCommTimeouts(m_hComHandle, lpCO) == TRUE : FALSE

}

//设置串口的I/O缓冲区大小

BOOL SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize)

{

return IsOpen()? ::SetupComm(m_hComHandle, dwInputSize, dwOutputSize) == TRUE : FALSE

}

//清除接受缓冲区

void ClearInputBuffer()

{

if(IsOpen())

PurgeComm(m_hComHandle, PURGE_RXABORT|PURGE_RXCLEAR)

}

//清除发送缓冲区

void ClearOutputBuffer()

{

if (IsOpen())

PurgeComm(m_hComHandle, PURGE_TXABORT|PURGE_TXCLEAR)

}

//关联消息的窗口句柄

inline void SetWnd(HWND hWnd)

{

assert(::IsWindow(hWnd))

m_hNotifyWnd = hWnd

}

//设定发送通知, 接受字符最小值

inline void SetNotifyNum(DWORD dwNum)

{

m_dwNotifyNum = dwNum

}

//线程是否运行

inline BOOL IsThreadRunning() {return m_hThreadHandle != NULL}

//获得线程句柄

inline HANDLE GetThread()

{

return m_hThreadHandle

}

//设置要监视的事件, 打开前设置有效

void SetMaskEvent(DWORD dwEvent = DEFALUT_COM_MASK_EVENT)

{

m_dwMaskEvent = dwEvent

}

//获得读缓冲区的字符数

int GetInputSize()

{

COMSTAT Stat

DWORD dwError

return ::ClearCommError(m_hComHandle, &dwError, &Stat) == TRUE? Stat.cbInQue : (DWORD)-1L

}

//Attributes

protected:

volatile DWORD m_dwPort //串口号

volatile HANDLE m_hComHandle //串口句柄

char m_szComStr[20] //保存Com1类似的字符串

DCB m_DCB //定义波特率,停止位,等

COMMTIMEOUTS m_ComTimeOuts //超时结构

DWORD m_dwIOMode //0,同步 默认 FILE_FLAG_OVERLAPPED 重叠I/O 异步

OVERLAPPED m_overlappedRead, m_overlappedWrite

volatile HANDLE m_hThreadHandle //辅助线程

volatile HWND m_hNotifyWnd //通知窗口

volatile DWORD m_dwNotifyNum//接受多少字节(>=m_dwNotifyNum)发送通知消息

volatile DWORD m_dwMaskEvent //监视的事件

volatile BOOL m_bRunFlag //线程运行循环标志

BOOL m_bAutoBeginThread //open() 自动BeginThread()

OVERLAPPED m_overlappedWait

protected:

//初始化

virtual void Init()

//析构

virtual void Destroy()

//绑定串口

void BindCommPort(DWORD dwPort)

//打开串口

virtual BOOL OpenCommPort()

//设置串口

virtual BOOL SetUpPort()

//---------------------------------------threads callback-----------------------------------------------------

//线程收到消息自动调用, 如窗口句柄有效, 送出消息, 包含串口编号, 均为虚函数可以在基层类中扩展

virtual DWORD ThreadFunc()

virtual void OnReceive()

virtual void OnCts()

virtual void OnDsr()

virtual void OnRing()

virtual void OnRlsd()

virtual void OnBreak()

virtual void OnTxEmpty()

virtual void OnError()

private:

CCom(const CCom&)

CCom&operator = (const CCom&)

CRITICAL_SECTION m_mutex

#ifdef _MT

static UINT APIENTRY CommThreadProc(LPVOID lpPara)

#else

static DWORD WINAPI CommThreadProc(LPVOID lpPara)

#endif

{

return ((CCom*)lpPara)->ThreadFunc()

}

}

#endif

#endif // !defined(AFX_COM_H__5427C4C8_CC6C_4135_9607_AF8BF6C1C679__INCLUDED_)

vb写串口调试软件很简单,就用一个mscomm控件就可以了

下面是主要代码:

Private Sub Cmd_Click()

MSComm1.CommPort = 1 '决定串口号

MSComm1.Settings = "9600,n,8,1" '设置波特率、校验位、数据位、停止位的字符串

MSComm1.PortOpen = True '打开串口

MSComm1.Output = "abcd" '向串口发送字符串"abcd"

MSComm1.PortOpen = False '关闭串口

End Sub

Private Sub MSComm1_OnComm() '当收到串口返回值时触发这个事件

Dim s As String '定义一个字符串变量

s = MSComm1.Input '将串口返回值放到字符串变量s中

MsgBox s '以消息框的方式显示串口返回的内容

End Sub

串串口服务器模块的参数包括本地IP地址、工作模式、串口波特率等,具体可以参考串口服务器模块参数简介。

3.串口服务器模块参数配置方法

卓岚串口服务器内嵌模块可以通过3种方式配置参数。分别是网页法、windows工具法、串口类AT命令法。这里是指用户使用卓岚的现有的工具来配置参数。关于开发用户自己的模块搜索、参数配置工具请看下一章节。

3.1 网页法

串口服务器核心模块内部运行了一个小型的Web服务器可以用于参数的配置,使用过路由器配置的用户对此方法一定不陌生。首先在浏览器的地址栏中输入串口服务器模块的当前IP地址,默认出厂IP为192.168.1.200。此时打开的页面即是串口服务器模块上的登录页面,输入登录密码(默认为123456)点击Login,进入参数配置页面。如图所示。修改相应参数后点击“Sbumit”按钮即可提交参数。

网页法配置参数的优点是:简单易用,无需安装任何配置工具,使用浏览器即可进行配置。缺点是:串口服务器模块的IP地址必须是和本机计算机处于同一个网段,否则无法访问网页。另外某些高级参数需要通过windows工具法进行配置。

3.2 Windows工具法

Windows工具法是推荐的参数配置方法。即在用户Windows计算机上运行卓岚ZLVircom软件或ZLDevManager,只要点击搜索即可搜索局域网内的所有串口服务器模块。其中ZLDevManager是一个简易工具,直接拷贝无需安装。对搜索列表中的模块选中后,点击“设备编辑”按钮或者双击列表中此行,即可弹出参数配置对话框,修改相应参数后点击“修改参数”按钮即可。如图所示。

windows工具法配置参数的优点是:1. 不要求串口服务器模块和计算机在同一个网段。2. 一次搜索多个模块,通过名字管理,无需记忆IP地址。3.可以配置高级参数。

windows工具法配置参数实际上是通过“卓岚管理端口协议”进行设备的搜索和参数配置。有两种方法可以将该设备搜索和参数修改功能直接集成到用户软件里:卓岚设备管理函数库DLL、卓岚管理端口协议。前者是一个可供用户调用的DLL库,后者是将管理端口协议的详细内容告诉用户,并由用户自己实现。该项内容属于增值服务。

3.3 串口类AT命令法

以上两种方法都是通过串口服务器模块的网口来配置参数。在某些时候,用户不仅需要通过网口来配置而且希望本地配置,即无需通过另外一台计算机来配置,而是直接通过设备本身来配置自己的参数。例如对于需要现场配置IP地址、现场配置目的IP地址的情况。卓岚的串口类AT命令法很好地满足了该要求。当用户MCU和串口服务器模块通过TTL(UART)串口连接后,用户MCU可以随时发送串口命令来配置参数。该命令类似AT指令,具体的指令格式请参考卓岚相关文档。

卓岚串口类AT命令能够实现的功能,包括但是不限于:

1.读取ZLSN2002/ZLSN2000的当前TCP连接状态,这样就知道模块是否和远端计算机建立了TCP连接。

2.随意控制ZLSN2002模块向任意的目的IP发起TCP连接,在多个目标之间随意切换,在多种工作模式中随意切换。

3.读取串口服务器模块的本地IP。如果是通过DHCP获得IP也能够读取。

4.重新启动串口服务器模块。

使用卓岚串口类AT命令可以完全控制串口服务器模块的TCP运行状态,也就是可以通过AT命令实现socket的connet、listen、send、recv等的函数调用。可以把ZLSN2002看成是“硬件TCP/IP协议栈”,因为ZLSN2002内部完全集成了socket函数的全部功能,而且可以通过串口AT命令的方式进行调用,相对于软件的socket接口来说,“硬件TCP/IP协议栈”不需要用户MCU运行协议栈、也可以保证协议栈的稳定性。卓岚提供有通过串口类AT命令实现让ZLSN串口服务器模块连接、监听、发送、接收的源代码,可方便用户参考。

4.参数配置方法的二次开发

如果用户需要将参数配置、设备搜索集成到到用户自己的软件中可以采用卓岚提供的设备管理函数库、管理端口协议方法。有的时候用户可能需要将IP的配置、波特率的配置集成到用户的管理软件中,而不是用卓岚的zlvircom进行配置,这增加了软件的统一性。以下就介绍这种方法。

4.1 设备管理函数

ZLAN可以提供一个供用户二次开发的动态连接库(DLL),这个动态连接库提供了简单的类似SearchDev()、 GetDevParam()、 SetDevParam()等函数来实现设备的搜索、参数获取、参数设置。使用起来非常方便,并提供有调用此DLL的C代码例子程序。这个函数库目前已经可以下载使用,参考《二次开发函数库的使用》。

4.2 管理端口协议

有的时候用户可能不想让自己的程序带有DLL库,此时更加灵活的控制方法是向ZLAN获取“管理端口协议”,这个协议是卓岚用户搜索模块、获取模块参数、设置模块参数的协议。用户完全可以在读懂协议的基础上自己实现这个协议。

设备管理函数库、ZLDevManage、ZLVircom的设备管理功能也是基于这个协议实现的。用户可以在读懂这个协议的基础上将ZLDevManage、ZLVircom的设备管理功能集成到用户自己的软件中。“管理端口协议”通过网口来配置模块,至少可以实现:

1.设备的搜索:搜索局域网、外网的所有的卓岚串口服务器模块。

2.读取设备参数:读取不同的设备的参数、设备ID、设备运行状态等。

3.重启指定的串口服务器模块。

4.修改指定的串口服务器模块的任何一个参数。


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/367489.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-12
下一篇2023-05-12

发表评论

登录后才能评论

评论列表(0条)

    保存