📄 serialdlg.cpp
字号:
// SerialDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "Serial.h"
#include "SerialDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CSerialDlg 对话框
CSerialDlg::CSerialDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSerialDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CSerialDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX,IDC_CLOSE_BUTTON ,ButClose);
DDX_Control(pDX,IDC_OPEN_BUTTON ,ButOpen);
DDX_Control(pDX,IDC_SEND_BUTTON ,ButSend);
DDX_Text(pDX,IDC_SEND ,strSendEdit);
}
BEGIN_MESSAGE_MAP(CSerialDlg, CDialog)
#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
ON_WM_SIZE()
#endif
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_OPEN_BUTTON, OnOpenCom)
ON_BN_CLICKED(IDC_CLOSE_BUTTON, OnCloseCom)
ON_BN_CLICKED(IDC_SEND_BUTTON, OnSend)
ON_WM_DESTROY()
END_MESSAGE_MAP()
// CSerialDlg 消息处理程序
BOOL CSerialDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
strRecDisp=_T("");
CenterWindow(GetDesktopWindow());
hComm = INVALID_HANDLE_VALUE; /* 串口操作句柄无效 */
ExitThreadEvent=NULL; /* 关闭线程事件句柄无效*/
ButClose.EnableWindow(FALSE); /* "关闭串口"按键无效 */
UpdateData(FALSE); /*把变量的值传给控件*/
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
void CSerialDlg::OnSize(UINT /*nType*/, int /*cx*/, int /*cy*/)
{
DRA::RelayoutDialog(
AfxGetInstanceHandle(),
this->m_hWnd,
DRA::GetDisplayMode() != DRA::Portrait ?
MAKEINTRESOURCE(IDD_SERIAL_DIALOG_WIDE) :
MAKEINTRESOURCE(IDD_SERIAL_DIALOG));
}
#endif
BOOL CSerialDlg::OpenPort(LPCTSTR Port, int BaudRate, int DataBits, int StopBits, int Parity)
{
COMMTIMEOUTS CommTimeOuts; //创建超时变量参数
DWORD error; //获得错误代码
hComm = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if(hComm == INVALID_HANDLE_VALUE)
{
error=GetLastError();
MessageBox(_T("无法打开端口或端口已打开!请检查是否已被占用."));
return FALSE;
}
GetCommState(hComm, &dcb); /* 读取串口的DCB */
dcb.BaudRate= BaudRate; /*设置波特率*/
dcb.ByteSize = DataBits; /*设置数据位*/
dcb.Parity= Parity; /*设置校验位*/
dcb.StopBits= StopBits; /*设置停止位*/
dcb.fParity= FALSE; /* 禁止奇偶校验 */
dcb.fBinary= TRUE;
dcb.fOutX= 0;
dcb.fInX= 0;
//设置状态参数
SetCommMask(hComm, EV_RXCHAR); /* 串口事件:接收到一个字符 */
SetupComm(hComm, 16384, 16384); /* 设置接收与发送的缓冲区大小 */
SetCommState(hComm, &dcb);
BOOL isSucces=SetCommState(hComm, &dcb);/* 设置串口的DCB */
if(!isSucces)
{
error=GetLastError();
MessageBox(_T("无法按当前参数配置端口,请检查参数!"));
ClosePort();
return FALSE;
}
GetCommTimeouts(hComm, &CommTimeOuts); /*获得超时参数*/
//设置超时参数
CommTimeOuts.ReadIntervalTimeout = 100; /* 接收字符间最大时间间隔 */
CommTimeOuts.ReadTotalTimeoutMultiplier = 1;
CommTimeOuts.ReadTotalTimeoutConstant = 100; /* 读数据总超时常量 */
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
if(!SetCommTimeouts(hComm, &CommTimeOuts))
{
MessageBox(_T("无法设置超时参数!"));
ClosePort();
return FALSE;
}
PurgeComm(hComm, PURGE_TXCLEAR | PURGE_RXCLEAR); /* 清除收/发缓冲区 */
return TRUE;
}
BOOL CSerialDlg::ClosePort(void)
{
if(hComm != INVALID_HANDLE_VALUE)
{
SetCommMask(hComm, 0); //disables all events
PurgeComm(hComm, PURGE_TXCLEAR | PURGE_RXCLEAR); /* 清除收/发缓冲 */
CloseHandle(hComm); /* 关闭串口操作句柄 */
hComm = INVALID_HANDLE_VALUE;
return TRUE;
}
return FALSE;
}
void CALLBACK CSerialDlg::OnComRecv(CWnd* pWnd, char *buf, int buflen)
{
CString tmp;
CSerialDlg *pDlg = (CSerialDlg*)pWnd;
CEdit *pRecvStrEdit = (CEdit*)pDlg->GetDlgItem(IDC_REV);
for (int i = 0; i < buflen; i++, buf++)
{
tmp.Format(_T("%c"), *buf); /* 将字符转换为字符串 */
pDlg->strRecDisp += tmp;
}
pRecvStrEdit->SetWindowText(pDlg->strRecDisp); /* 显示在窗口上 */
}
DWORD CSerialDlg::ComRecvThread(LPVOID lparam)
{
DWORD dwLength;
char *recvBuf = new char[1024];
CSerialDlg *pDlg = (CSerialDlg*)lparam;
while(TRUE)
{
/* 等待线程退出事件 */
if (WaitForSingleObject(pDlg->ExitThreadEvent, 0) == WAIT_OBJECT_0)
break;
if (pDlg->hComm != INVALID_HANDLE_VALUE)
{ /* 从串口读取数据 */
BOOL fReadState = ReadFile(pDlg->hComm, recvBuf, 1024, &dwLength, NULL);
if(!fReadState)
{
//MessageBox(_T("无法从串口读取数据!"));
}
else
{
if(dwLength != 0)
OnComRecv(pDlg, recvBuf, dwLength-2); /* 接收成功调用回调函数 */
}
}
}
delete[] recvBuf;
return 0;
}
void CSerialDlg::OnOpenCom()
{
DWORD IDThread;
HANDLE hRecvThread;
UpdateData(TRUE); /*把控件的值传给变量*/
CString strPort =_T("COM1:"); /* 设置参数值 */
DWORD baud = 115200;
DWORD databit = 8;
BYTE stopbit = ONESTOPBIT;
BYTE parity = NOPARITY;
BOOL ret = OpenPort(strPort, baud, databit, stopbit, parity); /* 打开串口 */
if (ret == FALSE)
return;
ExitThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* 创建串口接收线程退出事件*/
hRecvThread = CreateThread(0, 0, ComRecvThread, this, 0, &IDThread);
if (hRecvThread == NULL)
{
MessageBox(_T("创建接收线程失败!"));
return;
}
CloseHandle(hRecvThread);
ButOpen.EnableWindow(FALSE); /* 打开端口按键禁止 */
ButClose.EnableWindow(TRUE); /* 关闭端口按键使能 */
MessageBox(_T("打开串口COM1成功!"));
}
void CSerialDlg::OnCloseCom()
{
if (ExitThreadEvent != NULL)
{
SetEvent(ExitThreadEvent); /* 通知线程退出 */
Sleep(1000);
CloseHandle(ExitThreadEvent);
ExitThreadEvent = NULL;
}
ButOpen.EnableWindow(TRUE); /* 打开端口按键禁止 */
ButClose.EnableWindow(FALSE); /* 关闭端口按键使能 */
ClosePort();
}
void CSerialDlg::OnSend()
{
DWORD dwactlen;
char *recvBuf = new char[1024];
if (hComm == INVALID_HANDLE_VALUE)
{
MessageBox(_T("串口未打开!"));
return;
}
UpdateData(TRUE);
int len = strSendEdit.GetLength(); /* 取得输入字符串长度 */
char *psendbuf = new char[len];
for(int i = 0; i < len;i++)
psendbuf[i] = (char)strSendEdit.GetAt(i); /* 转换为单字节字符 */
WriteFile(hComm, psendbuf, len, &dwactlen, NULL); /* 从串口发送数据 */
WriteFile(hComm, "\r", 1, &dwactlen, NULL); /* 发送回车,weibing */
delete[] psendbuf;
}
void CSerialDlg::OnDestroy()
{
CDialog::OnDestroy();
if (ExitThreadEvent != NULL)
{
SetEvent(ExitThreadEvent); /* 通知串口接收线程退出 */
Sleep(1000);
CloseHandle(ExitThreadEvent); /* 关闭接收线程退出事件句柄 */
ExitThreadEvent = NULL;
}
ClosePort(); /* 关闭串口 */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -