如何用VC进行串口编程

如何用VC进行串口编程,第1张

1、新建MFC对话框工程如下

2、给编辑框控件添加变量,其中Edit Box添加Value变量,Button添加Control变量,ID和变量分别为:

IDC_BTNOPEN()    数橘源           伍链                   CButton m_cBtnOpen

IDC_BTNSEND()                                  CButton m_cBtnSend

IDC_EDIT_RXDATA()                          CString m_sRXDATA

IDC_EDIT_TXDATA()                           CString m_sTXDATA

3、右击插入Active X控件:

右击电话图标选择“Class Wirzard”,添加变量m_comm1,添加Function:

双击两个薯态Button按钮;

代码中显示如下:

[cpp] view plain copy print?

void CMSCommTestDlg::OnBnClickedBtnopen()

{

// TODO: Add your control notification handler code here

}

void CMSCommTestDlg::OnBnClickedBtnsend()

{

// TODO: Add your control notification handler code here

}

void CMSCommTestDlg::OnOncommMscomm1()

{

// TODO: Add your message handler code here

}

void CMSCommTestDlg::OnBnClickedBtnopen()

{

// TODO: Add your control notification handler code here

}

void CMSCommTestDlg::OnBnClickedBtnsend()

{

// TODO: Add your control notification handler code here

}

void CMSCommTestDlg::OnOncommMscomm1()

{

// TODO: Add your message handler code here

}

5、将上面代码补全如下:

[cpp] view plain copy print?

void CMSCommTestDlg::OnClickedBtnopen()

{

// TODO: Add your control notification handler code here

//如果端口已经开启,那么先关闭

if (m_comm1.get_PortOpen())

{

m_comm1.put_PortOpen(FALSE)

}

m_comm1.put_CommPort(3)                //选择com3,可以根据具体情况更改

m_comm1.put_InBufferSize(1024)         //设置输入缓冲区的大小,Bytes

m_comm1.put_OutBufferSize(1024)        //设置输出缓冲区的大小,Bytes

m_comm1.put_Settings(_T("9600,n,8,1")) //波特率9600,无校验,8个数据位,停止位1

m_comm1.put_InputMode(1)               //1:表示以二进制方式检索数据

m_comm1.put_RThreshold(1)              //参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件

m_comm1.put_InputLen(0)                //设置当前接收区长度是0

if (!m_comm1.get_PortOpen())

{

m_comm1.put_PortOpen(TRUE)

}

else

{

AfxMessageBox(_T("Can not open serial port!"))

}

m_comm1.get_Input()                    //先预读缓冲区以清除残留数据

UpdateData(FALSE)

}

void CMSCommTestDlg::OnClickedBtnsend()

{

// TODO: Add your control notification handler code here

UpdateData(TRUE)

m_comm1.put_Output(COleVariant(m_sTXDATA))//发送数据

}

void CMSCommTestDlg::OnOncommMscomm1()

{

// TODO: Add your message handler code here

VARIANT variant_inp

COleSafeArray safearray_inp

LONG len, k

BYTE rxdata[2048]

CString strtemp

if (m_comm1.get_CommEvent() == 2)       //事件值为2表示缓冲区内有字符

{

variant_inp = m_comm1.get_Input()  //读缓冲区

safearray_inp = variant_inp        //VARIANT型变量转换为ColeSafeArray型变量

len = safearray_inp.GetDim()       //得到有效数据长度

for (k = 0 k < len k++)

{

safearray_inp.GetElement(&k, rxdata + k)//转换为BYTE型数组

}

for (k = 0 k < len k++)            //将数组转换为CString型变量

{

BYTE bt = *(char*)(rxdata + k) //字符型

strtemp.Format(_T("%c"), bt)   //将字符送入临时变量strtemp存放

m_sRXDATA += strtemp           //接收到的数据放到编辑框对应的变量中

}

}

SetDlgItemText(IDC_EDIT_RXDATA, m_sRXDATA)

}

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

//送到窗口的消息 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_)


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/12536085.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2025-08-26
下一篇2025-08-26

发表评论

登录后才能评论

评论列表(0条)

    保存