界面设计
各控件说明
ID | Type | Member | 说明 |
---|---|---|---|
IDC_BUTTON_SERCHSEL | 检测串口按钮 | ||
IDC_BUTTON_OPENSEL | 打开串口按钮 | ||
IDC_BUTTON_CLOSESEL | 关闭串口按钮 | ||
IDC_BUTTON_CLEARGETDATA | 清空接收区按钮 | ||
IDC_BUTTON_SENDDATA | 发送数据按钮 | ||
IDC_BUTTON_CLEARSENDDATA | 清空发送区按钮 | ||
IDC_COMBO_CHOOSESEL | CComboBox | m_COMBO_ChooseSel | 串口选择下拉框 |
IDC_COMBO_BOTRAT | CComboBox | m_COMBO_BotRat | 波特率选择下拉框 |
IDC_COMBO_DABIT | CComboBox | m_COMBO_DaBit | 数据位选择下拉框 |
IDC_COMBO_CKBIT | CComboBox | m_COMBO_CkBit | 校验位选择下拉框 |
IDC_COMBO_STOPBIT | CComboBox | m_COMBO_StopBit | 停止位选择下拉框 |
IDC_CHECK_SENDDATATIME | BOOL | m_SendDataTime | 定时发送复选框 |
IDC_CHECK_GETHEXDATA | BOOL | m_GetHexData | HEX接收复选框 |
IDC_CHECK_SENDHEXDATA | BOOL | m_SendHexData | HEX发送复选框 |
IDC_EDIT_GETDATA | CString | m_EDIT_GetData | 显示接收数据编辑框 |
IDC_EDIT_GETDATABATE | CString | m_EDIT_GetDataBate | 显示已接收数据长度编辑框 |
IDC_EDIT_SENDDATA | CString | m_EDIT_SendData | 显示发送数据编辑框 |
IDC_EDIT_SENDDATABATE | CString | m_EDIT_SendDataBate | 显示已发送数据长度编辑框 |
IDC_EDIT_SENDDATATIME | int | m_EDIT_SendDataTime | 设置定时发送时间编辑框 |
IDC_MSCOMM | CMSComm | m_Comm | 串口控件 |
串口控件的插入
在页面设计界面点击鼠标右键,选择插入ActiveX控件…,在弹出的界面选择Microsoft Communications Control, Version 5…,点击确定进行串口控件的插入。
若出现Active X控件不能例示可到网上下载MSDATGRD.OCX和MSADODC.OCX两个文件,注册一下就好了,具体步骤如下:
1.先下载这两个文件
使用说明:
如果是64位系统:
请分别将MSADODC.OCX放入C:\Windows\SysWOW64目录下
MSDATGRD.OCX放入C:\Windows\System32目录下
如果是32位系统:
请将MSADODC.OCX和MSDATGRD.OCX都放入C:\Windows\System32目录下
2.对文件进行注册
按win+r开打“运行”对话框,输入"cmd",打开命令提示符,
输入"regsvr32 C:\Windows\SysWOW64\MSADODC.OCX"命令注册MSADODC.OCX
输入"regsvr32 C:\Windows\System32\MSDATGRD.OCX"命令注册MSDATGRD.OCX
再次打开工程文件,现在是不是已经可以正常使用了。文章来源:https://www.toymoban.com/news/detail-470632.html
若还是无法运行便可此文件进行注册表注册 注册表。文章来源地址https://www.toymoban.com/news/detail-470632.html
程序设计
初始化函数添加
// TODO: Add extra initialization here
// 波特率设置
m_COMBO_BotRat.AddString(_T("110"));
m_COMBO_BotRat.AddString(_T("300"));
m_COMBO_BotRat.AddString(_T("600"));
m_COMBO_BotRat.AddString(_T("1200"));
m_COMBO_BotRat.AddString(_T("2400"));
m_COMBO_BotRat.AddString(_T("4800"));
m_COMBO_BotRat.AddString(_T("9600"));
m_COMBO_BotRat.AddString(_T("11400"));
m_COMBO_BotRat.AddString(_T("19200"));
m_COMBO_BotRat.AddString(_T("38400"));
m_COMBO_BotRat.AddString(_T("56000"));
m_COMBO_BotRat.AddString(_T("57600"));
m_COMBO_BotRat.AddString(_T("115200"));
m_COMBO_BotRat.AddString(_T("128000"));
m_COMBO_BotRat.AddString(_T("256000"));
m_COMBO_BotRat.SetCurSel(6);
// 数据位设置
for (int i = 5; i <= 8; i++ )
{
CString strBit;
strBit.Format("%d", i);
m_COMBO_DaBit.AddString(strBit);
}
m_COMBO_DaBit.SetCurSel(3);
// 检验位设置
m_COMBO_CkBit.AddString(_T("NONE"));
m_COMBO_CkBit.AddString(_T("ODD"));
m_COMBO_CkBit.AddString(_T("EVEN"));
m_COMBO_CkBit.AddString(_T("MARK"));
m_COMBO_CkBit.AddString(_T("SPACE"));
m_COMBO_CkBit.SetCurSel(0);
// 停止位设置
m_COMBO_StopBit.AddString(_T("1"));
m_COMBO_StopBit.AddString(_T("1.5"));
m_COMBO_StopBit.AddString(_T("2"));
m_COMBO_StopBit.SetCurSel(0);
SendDataTimeState = 0;
GetHexDataState = 0;
SendHexDataState = 0;
OnButtonSerchsel(); // 串口检测函数
串口检测按钮相关函数
CUIntArray ports; //所有存在的串口
CUIntArray portse; //可用的串口
CUIntArray portsu; //已占用的串口
#define MAX_SCAN_CNT 128
void CSerial_DemoDlg::OnButtonSerchsel()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
unsigned short com_cnt;
while (m_COMBO_ChooseSel.DeleteString(0) >= 0);
com_cnt = AddCom(&m_COMBO_ChooseSel);
if(com_cnt)
{
m_COMBO_ChooseSel.DeleteString(com_cnt + 1);
m_COMBO_ChooseSel.SetCurSel(0);
}
UpdateData(FALSE);
}
void CSerial_DemoDlg::EnumerateSerialPorts(CUIntArray& porta, CUIntArray& portse, CUIntArray& portsu)
{
//清除串口数组内容
porta.RemoveAll();
portse.RemoveAll();
portsu.RemoveAll();
//因为至多有255个串口,所以依次检查各串口是否存在
//如果能打开某一串口,或打开串口不成功,但返回的是 ERROR_ACCESS_DENIED错误信息,
//都认为串口存在,只不过后者表明串口已经被占用
//否则串口不存在
for (int i = 1;i < MAX_SCAN_CNT;i++)
{
//形成原始设备名称
CString sPort;
sPort.Format(_T("\\\\.\\COM%d"),i);
//尝试打开该端口
BOOL bSuccess = FALSE;
HANDLE hPort = ::CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (hPort == INVALID_HANDLE_VALUE)
{
DWORD dwError = GetLastError();
if (dwError == ERROR_ACCESS_DENIED)
{
bSuccess = TRUE;
portsu.Add(i);//已占用的串口
}
}
else
{
//该端口已成功打开
bSuccess = TRUE;
portse.Add(i);//可用串口
//不要忘记关闭端口,因为我们不会对它做任何事情
CloseHandle(hPort);
}
//将端口号添加到将要返回的数组中
if (bSuccess)
porta.Add(i);//所有存在的串口
}
}
UShort CSerial_DemoDlg::AddCom(CComboBox* pvect)
{
UShort uicounter; //串口数量
UShort uisetcom;
CString str;
EnumerateSerialPorts(ports, portse, portsu); //获得可用串口数
//获取可用串口个数
uicounter = portse.GetSize();
//如果个数大于0
if (uicounter > 0)
{
//初始化串口列表框
for (int i = 0;i < uicounter;i++)
{
uisetcom = portse.ElementAt(i);
str.Format(_T("COM%d "), uisetcom);
pvect->InsertString(i, str);
}
}
return uicounter;
}
打开按钮相关函数
void CSerial_DemoDlg::OnButtonOpensel()
{
// TODO: Add your control notification handler code here
DWORD nCommPort;
nCommPort = (unsigned)GetCommPortN(); // 获取串口号
CString strPara = GetCommPortParameter();
if(strPara.GetLength() <= 0)
MessageBox(_T("参数获取错误!"), _T("Error"), MB_ICONERROR | MB_OK);
char *pszPara = strPara.GetBuffer(0);
strPara.ReleaseBuffer();
// 打开串口
if(m_Comm.GetPortOpen())
MessageBox(_T("串口已打开", _T("Warning"), MB_ICONWARNING | MB_OK));
m_Comm.SetCommPort(nCommPort); // 选择串口号
m_Comm.SetInBufferSize(1024); // 设置输入缓冲区的大小,Bytes
m_Comm.SetOutBufferSize(1024); // 设置输入缓冲区的大小,Bytes//
m_Comm.SetSettings(strPara);
m_Comm.SetInputMode(1); // 1:表示以二进制方式检取数据
m_Comm.SetRThreshold(1); // 参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnOnCommMscomm事件
m_Comm.SetInputLen(0); // 设置当前接收区数据长度为0
if( !m_Comm.GetPortOpen())
{
m_Comm.SetPortOpen(TRUE);
GetDlgItem(IDC_BUTTON_OPENSEL)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_CLOSESEL)->EnableWindow(TRUE);
}
else
AfxMessageBox("cannot open serial port");
m_Comm.GetInput();//先预读缓冲区以清除残留数据
UpdateData(false);
}
long CSerial_DemoDlg::GetCommPortN() // 获取COMBO BOX上的串口编号
{
CString strCommPort;
m_COMBO_ChooseSel.GetWindowText(strCommPort);
strCommPort = strCommPort.Mid(3);
return _ttol(strCommPort);
}
CString CSerial_DemoDlg::GetCommPortParameter() // 获取串口参数
{
CString strParameter = "";
CString strBaudRate; // 波特率
CString strDataBit; // 数据位
CString strCheckBit; // 校验位
CString strStopBit; // 停止位
m_COMBO_BotRat.GetWindowText(strBaudRate);
m_COMBO_CkBit.GetWindowText(strCheckBit);
m_COMBO_DaBit.GetWindowText(strDataBit);
m_COMBO_StopBit.GetWindowText(strStopBit);
strCheckBit = strCheckBit.Left(1);
strCheckBit.MakeLower();
strParameter += strBaudRate;
strParameter += _T(",");
strParameter += strCheckBit;
strParameter += _T(",");
strParameter += strDataBit;
strParameter += _T(",");
strParameter += strStopBit;
return strParameter;
}
void CSerial_DemoDlg::OnOnCommMscomm() // 该函数可在类向导中ID选择IDC_MSCOMM,Messages选择OnComm创建
{
// TODO: Add your control notification handler code here
VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed.
CString strtemp;
if(m_Comm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符
{
variant_inp=m_Comm.GetInput(); //读缓冲区
safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量
len = 0;
len=safearray_inp.GetOneDimSize(); //得到有效数据长度
for(k=0;k<len;k++)
safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组
if(GetHexDataState == 1) // 16进制接收
{
for (k = 0; k < len; k++)
{
switch (rxdata[k] / 16)
{
case 0: m_EDIT_GetData += '0'; break;
case 1: m_EDIT_GetData += '1'; break;
case 2: m_EDIT_GetData += '2'; break;
case 3: m_EDIT_GetData += '3'; break;
case 4: m_EDIT_GetData += '4'; break;
case 5: m_EDIT_GetData += '5'; break;
case 6: m_EDIT_GetData += '6'; break;
case 7: m_EDIT_GetData += '7'; break;
case 8: m_EDIT_GetData += '8'; break;
case 9: m_EDIT_GetData += '9'; break;
case 10: m_EDIT_GetData += 'A'; break;
case 11: m_EDIT_GetData += 'B'; break;
case 12: m_EDIT_GetData += 'C'; break;
case 13: m_EDIT_GetData += 'D'; break;
case 14: m_EDIT_GetData += 'E'; break;
case 15: m_EDIT_GetData += 'F'; break;
}
switch (rxdata[k] % 16)
{
case 0: m_EDIT_GetData += '0'; break;
case 1: m_EDIT_GetData += '1'; break;
case 2: m_EDIT_GetData += '2'; break;
case 3: m_EDIT_GetData += '3'; break;
case 4: m_EDIT_GetData += '4'; break;
case 5: m_EDIT_GetData += '5'; break;
case 6: m_EDIT_GetData += '6'; break;
case 7: m_EDIT_GetData += '7'; break;
case 8: m_EDIT_GetData += '8'; break;
case 9: m_EDIT_GetData += '9'; break;
case 10: m_EDIT_GetData += 'A'; break;
case 11: m_EDIT_GetData += 'B'; break;
case 12: m_EDIT_GetData += 'C'; break;
case 13: m_EDIT_GetData += 'D'; break;
case 14: m_EDIT_GetData += 'E'; break;
case 15: m_EDIT_GetData += 'F'; break;
}
m_EDIT_GetData += ' ';
}
SetDlgItemText(IDC_EDIT_GETDATA,m_EDIT_GetData); // 显示接受数据
}
if(GetHexDataState == 0)
{
for(k=0;k<len;k++) //将数组转换为Cstring型变量
{
BYTE bt=*(char*)(rxdata+k); //字符型
strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放
if(strtemp == '\n' || strtemp == '\r')
strtemp = "\r\n";
m_EDIT_GetData+=strtemp; //加入接收编辑框对应字符串
}
SetDlgItemText(IDC_EDIT_GETDATA,m_EDIT_GetData); // 显示接受数据
}
CString string;
GetDataBata += len;
string.Format(_T("%ld"), GetDataBata);
SetDlgItemText(IDC_EDIT_GETDATABATE,string); // 显示接受字节
}
}
发送数据按钮相关函数
void CSerial_DemoDlg::OnButtonSenddata()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE); //读取编辑框内容
CByteArray HexDataBuf;
int i = 0;
BYTE SendBuf[128]={0};
BYTE GetData[256]={0};
int SendLen = 0;
int GetLen = 0;
CString string;
if(m_EDIT_SendData.IsEmpty())
{
AfxMessageBox(_T("发送数据为空!"));
return;
}
HexDataBuf.RemoveAll(); //清空数组
if (SendHexDataState == 0)
{
m_Comm.SetOutput(COleVariant(m_EDIT_SendData));//发送数据
m_Comm.SetOutput(COleVariant("\r\n"));//发送回车
SendDataBata += m_EDIT_SendData.GetLength()+2;
}
if (SendHexDataState == 1)
{
GetLen = m_EDIT_SendData.GetLength();
for(i=0; i<GetLen; i++)
GetData[i] = (BYTE)m_EDIT_SendData.GetBuffer(GetLen)[i];
StringtoHex(GetData, GetLen, SendBuf, &SendLen);//将字符串转化为字节数据
HexDataBuf.SetSize(SendLen); //设置数组大小为帧长度
for(i=0; i<SendLen; i++)
HexDataBuf.SetAt(i,SendBuf[i]);
m_Comm.SetOutput(COleVariant(HexDataBuf)); //发送十六进制数据
SendDataBata += SendLen;
}
string.Format("%d", SendDataBata);
SetDlgItemText(IDC_EDIT_SENDDATABATE,string);
}
void CSerial_DemoDlg::StringtoHex(BYTE *GB, int glen, BYTE* SB, int* slen)
{
int i; //遍历输入的字符串
int a = 0;
char temp; //接收字符,用来判断是否为空格,若是则跳过
char temp1,temp2; //接收一个字节的两个字符 例如EB,则temp1='E',temp2 = 'B'
*slen = 0; //输出的16进制字符串长度
for(i=0;i<glen;i++)
{
temp = GB[i];
if(temp==' ')
continue;
if(a == 0)
temp1 = GB[i];
if(a == 1)
temp2 = GB[i];
a++;
if(a==2)
{
a = 0;
temp1 = temp1 - '0';
if (temp1>10)
temp1 = temp1 -7;
temp2 = temp2 - '0';
if (temp2>10)
temp2 = temp2 -7;
SB[*slen] = temp1*16+temp2;
(*slen)++;
}
}
}
点选定时发送复选框
void CSerial_DemoDlg::OnCheckSenddatatime()
{
// TODO: Add your control notification handler code here
if (SendDataTimeState == 0)
{
if( m_Comm.GetPortOpen())
{
UpdateData(TRUE); //读取编辑框内容
SetTimer( IDC_TIMER, m_EDIT_SendDataTime, NULL );
}
}
else
{
KillTimer( IDC_TIMER );
SendDataTimeState = 0;
}
}
void CSerial_DemoDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
OnButtonSenddata();
SendDataTimeState = 1;
CDialog::OnTimer(nIDEvent);
}
点选HEX发送复选框相关函数
void CSerial_DemoDlg::OnCheckGethexdata()
{
// TODO: Add your control notification handler code here
if(GetHexDataState == 0)
GetHexDataState = 1;
else if(GetHexDataState == 1)
GetHexDataState = 0;
}
点选HEX接收复选框相关函数
void CSerial_DemoDlg::OnCheckSendhexdata()
{
// TODO: Add your control notification handler code here
if (SendHexDataState == 0)
SendHexDataState = 1;
else if (SendHexDataState == 1)
SendHexDataState = 0;
}
清空接收区按钮相关函数
void CSerial_DemoDlg::OnButtonCleargetdata()
{
// TODO: Add your control notification handler code here
m_EDIT_GetData = _T("");
SetDlgItemText(IDC_EDIT_GETDATA,"");
}
清空发送区按钮相关函数
void CSerial_DemoDlg::OnButtonClearsenddata()
{
// TODO: Add your control notification handler code here
SetDlgItemText(IDC_EDIT_SENDDATA,"");
}
关闭串口按钮相关函数
void CSerial_DemoDlg::OnButtonClosesel()
{
// TODO: Add your control notification handler code here
if(m_Comm.GetPortOpen())
{
m_Comm.SetPortOpen(FALSE);
GetDlgItem(IDC_BUTTON_OPENSEL)->EnableWindow(TRUE);
GetDlgItem(IDC_BUTTON_CLOSESEL)->EnableWindow(FALSE);
GetDataBata = 0;
SendDataBata = 0;
SetDlgItemText(IDC_EDIT_GETDATABATE,"");
SetDlgItemText(IDC_EDIT_SENDDATABATE,"");
}
}
完整程序
.cpp文件
// Serial_DemoDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Serial_Demo.h"
#include "Serial_DemoDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CSerial_DemoDlg dialog
CSerial_DemoDlg::CSerial_DemoDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSerial_DemoDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CSerial_DemoDlg)
m_GetHexData = FALSE;
m_SendDataTime = FALSE;
m_SendHexTime = FALSE;
m_EDIT_GetData = _T("");
m_EDIT_SendData = _T("");
m_EDIT_SendDataTime = 1000;
SendDataTimeState = 0;
GetHexDataState = 0;
SendHexDataState = 0;
GetDataBata = 0;
SendDataBata = 0;
m_EDIT_GetDataBate = _T("");
m_EDIT_SendDataBate = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CSerial_DemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSerial_DemoDlg)
DDX_Control(pDX, IDC_COMBO_STOPBIT, m_COMBO_StopBit);
DDX_Control(pDX, IDC_COMBO_DABIT, m_COMBO_DaBit);
DDX_Control(pDX, IDC_COMBO_CKBIT, m_COMBO_CkBit);
DDX_Control(pDX, IDC_COMBO_CHOOSESEL, m_COMBO_ChooseSel);
DDX_Control(pDX, IDC_COMBO_BOTRAT, m_COMBO_BotRat);
DDX_Check(pDX, IDC_CHECK_GETHEXDATA, m_GetHexData);
DDX_Check(pDX, IDC_CHECK_SENDDATATIME, m_SendDataTime);
DDX_Check(pDX, IDC_CHECK_SENDHEXDATA, m_SendHexTime);
DDX_Text(pDX, IDC_EDIT_GETDATA, m_EDIT_GetData);
DDX_Text(pDX, IDC_EDIT_SENDDATA, m_EDIT_SendData);
DDX_Text(pDX, IDC_EDIT_SENDDATATIME, m_EDIT_SendDataTime);
DDX_Control(pDX, IDC_MSCOMM1, m_Comm);
DDX_Text(pDX, IDC_EDIT_GETDATABATE, m_EDIT_GetDataBate);
DDX_Text(pDX, IDC_EDIT_SENDDATABATE, m_EDIT_SendDataBate);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CSerial_DemoDlg, CDialog)
//{{AFX_MSG_MAP(CSerial_DemoDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_OPENSEL, OnButtonOpensel)
ON_BN_CLICKED(IDC_BUTTON_SERCHSEL, OnButtonSerchsel)
ON_BN_CLICKED(IDC_BUTTON_SENDDATA, OnButtonSenddata)
ON_BN_CLICKED(IDC_BUTTON_CLOSESEL, OnButtonClosesel)
ON_BN_CLICKED(IDC_CHECK_SENDDATATIME, OnCheckSenddatatime)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BUTTON_CLEARGETDATA, OnButtonCleargetdata)
ON_BN_CLICKED(IDC_BUTTON_CLEARSENDDATA, OnButtonClearsenddata)
ON_BN_CLICKED(IDC_CHECK_GETHEXDATA, OnCheckGethexdata)
ON_BN_CLICKED(IDC_CHECK_SENDHEXDATA, OnCheckSendhexdata)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CSerial_DemoDlg message handlers
BOOL CSerial_DemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 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
// 波特率设置
m_COMBO_BotRat.AddString(_T("110"));
m_COMBO_BotRat.AddString(_T("300"));
m_COMBO_BotRat.AddString(_T("600"));
m_COMBO_BotRat.AddString(_T("1200"));
m_COMBO_BotRat.AddString(_T("2400"));
m_COMBO_BotRat.AddString(_T("4800"));
m_COMBO_BotRat.AddString(_T("9600"));
m_COMBO_BotRat.AddString(_T("11400"));
m_COMBO_BotRat.AddString(_T("19200"));
m_COMBO_BotRat.AddString(_T("38400"));
m_COMBO_BotRat.AddString(_T("56000"));
m_COMBO_BotRat.AddString(_T("57600"));
m_COMBO_BotRat.AddString(_T("115200"));
m_COMBO_BotRat.AddString(_T("128000"));
m_COMBO_BotRat.AddString(_T("256000"));
m_COMBO_BotRat.SetCurSel(6);
// 数据位设置
for (int i = 5; i <= 8; i++ )
{
CString strBit;
strBit.Format("%d", i);
m_COMBO_DaBit.AddString(strBit);
}
m_COMBO_DaBit.SetCurSel(3);
// 检验位设置
m_COMBO_CkBit.AddString(_T("NONE"));
m_COMBO_CkBit.AddString(_T("ODD"));
m_COMBO_CkBit.AddString(_T("EVEN"));
m_COMBO_CkBit.AddString(_T("MARK"));
m_COMBO_CkBit.AddString(_T("SPACE"));
m_COMBO_CkBit.SetCurSel(0);
// 停止位设置
m_COMBO_StopBit.AddString(_T("1"));
m_COMBO_StopBit.AddString(_T("1.5"));
m_COMBO_StopBit.AddString(_T("2"));
m_COMBO_StopBit.SetCurSel(0);
SendDataTimeState = 0;
GetHexDataState = 0;
SendHexDataState = 0;
OnButtonSerchsel();
return TRUE; // return TRUE unless you set the focus to a control
}
void CSerial_DemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CSerial_DemoDlg::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();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CSerial_DemoDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
BEGIN_EVENTSINK_MAP(CSerial_DemoDlg, CDialog)
//{{AFX_EVENTSINK_MAP(CSerial_DemoDlg)
ON_EVENT(CSerial_DemoDlg, IDC_MSCOMM1, 1 /* OnComm */, OnOnCommMscomm, VTS_NONE)
//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()
// 检测按钮相关
CUIntArray ports; //所有存在的串口
CUIntArray portse; //可用的串口
CUIntArray portsu; //已占用的串口
#define MAX_SCAN_CNT 128
void CSerial_DemoDlg::OnButtonSerchsel()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
unsigned short com_cnt;
while (m_COMBO_ChooseSel.DeleteString(0) >= 0);
com_cnt = AddCom(&m_COMBO_ChooseSel);
if(com_cnt)
{
m_COMBO_ChooseSel.DeleteString(com_cnt + 1);
m_COMBO_ChooseSel.SetCurSel(0);
}
UpdateData(FALSE);
}
void CSerial_DemoDlg::EnumerateSerialPorts(CUIntArray& porta, CUIntArray& portse, CUIntArray& portsu)
{
//清除串口数组内容
porta.RemoveAll();
portse.RemoveAll();
portsu.RemoveAll();
//因为至多有255个串口,所以依次检查各串口是否存在
//如果能打开某一串口,或打开串口不成功,但返回的是 ERROR_ACCESS_DENIED错误信息,
//都认为串口存在,只不过后者表明串口已经被占用
//否则串口不存在
for (int i = 1;i < MAX_SCAN_CNT;i++)
{
//形成原始设备名称
CString sPort;
sPort.Format(_T("\\\\.\\COM%d"),i);
//尝试打开该端口
BOOL bSuccess = FALSE;
HANDLE hPort = ::CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (hPort == INVALID_HANDLE_VALUE)
{
DWORD dwError = GetLastError();
if (dwError == ERROR_ACCESS_DENIED)
{
bSuccess = TRUE;
portsu.Add(i);//已占用的串口
}
}
else
{
//该端口已成功打开
bSuccess = TRUE;
portse.Add(i);//可用串口
//不要忘记关闭端口,因为我们不会对它做任何事情
CloseHandle(hPort);
}
//将端口号添加到将要返回的数组中
if (bSuccess)
{
porta.Add(i);//所有存在的串口
}
}
}
UShort CSerial_DemoDlg::AddCom(CComboBox* pvect)
{
UShort uicounter; //串口数量
UShort uisetcom;
CString str;
EnumerateSerialPorts(ports, portse, portsu); //获得可用串口数
//获取可用串口个数
uicounter = portse.GetSize();
//如果个数大于0
if (uicounter > 0)
{
//初始化串口列表框
for (int i = 0;i < uicounter;i++)
{
uisetcom = portse.ElementAt(i);
str.Format(_T("COM%d "), uisetcom);
pvect->InsertString(i, str);
}
}
return uicounter;
}
// 打开按钮相关
void CSerial_DemoDlg::OnButtonOpensel()
{
// TODO: Add your control notification handler code here
DWORD nCommPort;
nCommPort = (unsigned)GetCommPortN(); // 获取串口号
CString strPara = GetCommPortParameter();
if(strPara.GetLength() <= 0)
MessageBox(_T("参数获取错误!"), _T("Error"), MB_ICONERROR | MB_OK);
char *pszPara = strPara.GetBuffer(0);
strPara.ReleaseBuffer();
// 打开串口
if(m_Comm.GetPortOpen())
MessageBox(_T("串口已打开", _T("Warning"), MB_ICONWARNING | MB_OK));
m_Comm.SetCommPort(nCommPort); // 选择串口号
m_Comm.SetInBufferSize(1024); // 设置输入缓冲区的大小,Bytes
m_Comm.SetOutBufferSize(1024); // 设置输入缓冲区的大小,Bytes//
m_Comm.SetSettings(strPara);
m_Comm.SetInputMode(1); // 1:表示以二进制方式检取数据
m_Comm.SetRThreshold(1); // 参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnOnCommMscomm事件
m_Comm.SetInputLen(0); // 设置当前接收区数据长度为0
if( !m_Comm.GetPortOpen())
{
m_Comm.SetPortOpen(TRUE);
GetDlgItem(IDC_BUTTON_OPENSEL)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_CLOSESEL)->EnableWindow(TRUE);
}
else
AfxMessageBox("cannot open serial port");
m_Comm.GetInput();//先预读缓冲区以清除残留数据
UpdateData(false);
}
long CSerial_DemoDlg::GetCommPortN() // 获取COMBO BOX上的串口编号
{
CString strCommPort;
m_COMBO_ChooseSel.GetWindowText(strCommPort);
strCommPort = strCommPort.Mid(3);
return _ttol(strCommPort);
}
CString CSerial_DemoDlg::GetCommPortParameter() // 获取串口参数
{
CString strParameter = "";
CString strBaudRate; // 波特率
CString strDataBit; // 数据位
CString strCheckBit; // 校验位
CString strStopBit; // 停止位
m_COMBO_BotRat.GetWindowText(strBaudRate);
m_COMBO_CkBit.GetWindowText(strCheckBit);
m_COMBO_DaBit.GetWindowText(strDataBit);
m_COMBO_StopBit.GetWindowText(strStopBit);
strCheckBit = strCheckBit.Left(1);
strCheckBit.MakeLower();
strParameter += strBaudRate;
strParameter += _T(",");
strParameter += strCheckBit;
strParameter += _T(",");
strParameter += strDataBit;
strParameter += _T(",");
strParameter += strStopBit;
return strParameter;
}
void CSerial_DemoDlg::OnOnCommMscomm()
{
// TODO: Add your control notification handler code here
VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed.
CString strtemp;
if(m_Comm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符
{
variant_inp=m_Comm.GetInput(); //读缓冲区
safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量
len = 0;
len=safearray_inp.GetOneDimSize(); //得到有效数据长度
for(k=0;k<len;k++)
safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组
if(GetHexDataState == 1) // 16进制接收
{
for (k = 0; k < len; k++)
{
switch (rxdata[k] / 16)
{
case 0: m_EDIT_GetData += '0'; break;
case 1: m_EDIT_GetData += '1'; break;
case 2: m_EDIT_GetData += '2'; break;
case 3: m_EDIT_GetData += '3'; break;
case 4: m_EDIT_GetData += '4'; break;
case 5: m_EDIT_GetData += '5'; break;
case 6: m_EDIT_GetData += '6'; break;
case 7: m_EDIT_GetData += '7'; break;
case 8: m_EDIT_GetData += '8'; break;
case 9: m_EDIT_GetData += '9'; break;
case 10: m_EDIT_GetData += 'A'; break;
case 11: m_EDIT_GetData += 'B'; break;
case 12: m_EDIT_GetData += 'C'; break;
case 13: m_EDIT_GetData += 'D'; break;
case 14: m_EDIT_GetData += 'E'; break;
case 15: m_EDIT_GetData += 'F'; break;
}
switch (rxdata[k] % 16)
{
case 0: m_EDIT_GetData += '0'; break;
case 1: m_EDIT_GetData += '1'; break;
case 2: m_EDIT_GetData += '2'; break;
case 3: m_EDIT_GetData += '3'; break;
case 4: m_EDIT_GetData += '4'; break;
case 5: m_EDIT_GetData += '5'; break;
case 6: m_EDIT_GetData += '6'; break;
case 7: m_EDIT_GetData += '7'; break;
case 8: m_EDIT_GetData += '8'; break;
case 9: m_EDIT_GetData += '9'; break;
case 10: m_EDIT_GetData += 'A'; break;
case 11: m_EDIT_GetData += 'B'; break;
case 12: m_EDIT_GetData += 'C'; break;
case 13: m_EDIT_GetData += 'D'; break;
case 14: m_EDIT_GetData += 'E'; break;
case 15: m_EDIT_GetData += 'F'; break;
}
m_EDIT_GetData += ' ';
}
SetDlgItemText(IDC_EDIT_GETDATA,m_EDIT_GetData); // 显示接受数据
}
if(GetHexDataState == 0)
{
for(k=0;k<len;k++) //将数组转换为Cstring型变量
{
BYTE bt=*(char*)(rxdata+k); //字符型
strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放
if(strtemp == '\n' || strtemp == '\r')
strtemp = "\r\n";
m_EDIT_GetData+=strtemp; //加入接收编辑框对应字符串
}
SetDlgItemText(IDC_EDIT_GETDATA,m_EDIT_GetData); // 显示接受数据
}
CString string;
GetDataBata += len;
string.Format(_T("%ld"), GetDataBata);
SetDlgItemText(IDC_EDIT_GETDATABATE,string); // 显示接受字节
}
}
void CSerial_DemoDlg::OnButtonSenddata()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE); //读取编辑框内容
CByteArray HexDataBuf;
int i = 0;
BYTE SendBuf[128]={0};
BYTE GetData[256]={0};
int SendLen = 0;
int GetLen = 0;
CString string;
if(m_EDIT_SendData.IsEmpty())
{
AfxMessageBox(_T("发送数据为空!"));
return;
}
HexDataBuf.RemoveAll(); //清空数组
if (SendHexDataState == 0)
{
m_Comm.SetOutput(COleVariant(m_EDIT_SendData));//发送数据
m_Comm.SetOutput(COleVariant("\r\n"));//发送回车
SendDataBata += m_EDIT_SendData.GetLength()+2;
}
if (SendHexDataState == 1)
{
GetLen = m_EDIT_SendData.GetLength();
for(i=0; i<GetLen; i++)
GetData[i] = (BYTE)m_EDIT_SendData.GetBuffer(GetLen)[i];
StringtoHex(GetData, GetLen, SendBuf, &SendLen);//将字符串转化为字节数据
HexDataBuf.SetSize(SendLen); //设置数组大小为帧长度
for(i=0; i<SendLen; i++)
HexDataBuf.SetAt(i,SendBuf[i]);
m_Comm.SetOutput(COleVariant(HexDataBuf)); //发送十六进制数据
SendDataBata += SendLen;
}
string.Format("%d", SendDataBata);
SetDlgItemText(IDC_EDIT_SENDDATABATE,string);
}
// 关闭串口
void CSerial_DemoDlg::OnButtonClosesel()
{
// TODO: Add your control notification handler code here
if(m_Comm.GetPortOpen())
{
m_Comm.SetPortOpen(FALSE);
GetDlgItem(IDC_BUTTON_OPENSEL)->EnableWindow(TRUE);
GetDlgItem(IDC_BUTTON_CLOSESEL)->EnableWindow(FALSE);
GetDataBata = 0;
SendDataBata = 0;
SetDlgItemText(IDC_EDIT_GETDATABATE,"");
SetDlgItemText(IDC_EDIT_SENDDATABATE,"");
}
}
void CSerial_DemoDlg::OnCheckSenddatatime()
{
// TODO: Add your control notification handler code here
if (SendDataTimeState == 0)
{
if( m_Comm.GetPortOpen())
{
UpdateData(TRUE); //读取编辑框内容
SetTimer( IDC_TIMER, m_EDIT_SendDataTime, NULL );
}
}
else
{
KillTimer( IDC_TIMER );
SendDataTimeState = 0;
}
}
void CSerial_DemoDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
OnButtonSenddata();
SendDataTimeState = 1;
CDialog::OnTimer(nIDEvent);
}
void CSerial_DemoDlg::OnButtonCleargetdata()
{
// TODO: Add your control notification handler code here
m_EDIT_GetData = _T("");
SetDlgItemText(IDC_EDIT_GETDATA,"");
}
void CSerial_DemoDlg::OnButtonClearsenddata()
{
// TODO: Add your control notification handler code here
SetDlgItemText(IDC_EDIT_SENDDATA,"");
}
void CSerial_DemoDlg::OnCheckGethexdata()
{
// TODO: Add your control notification handler code here
if(GetHexDataState == 0)
GetHexDataState = 1;
else if(GetHexDataState == 1)
GetHexDataState = 0;
}
void CSerial_DemoDlg::OnCheckSendhexdata()
{
// TODO: Add your control notification handler code here
if (SendHexDataState == 0)
SendHexDataState = 1;
else if (SendHexDataState == 1)
SendHexDataState = 0;
}
void CSerial_DemoDlg::StringtoHex(BYTE *GB, int glen, BYTE* SB, int* slen)
{
int i; //遍历输入的字符串
int a = 0;
char temp; //接收字符,用来判断是否为空格,若是则跳过
char temp1,temp2; //接收一个字节的两个字符 例如EB,则temp1='E',temp2 = 'B'
*slen = 0; //输出的16进制字符串长度
for(i=0;i<glen;i++)
{
temp = GB[i];
if(temp==' ')
continue;
if(a == 0)
temp1 = GB[i];
if(a == 1)
temp2 = GB[i];
a++;
if(a==2)
{
a = 0;
temp1 = temp1 - '0';
if (temp1>10)
temp1 = temp1 -7;
temp2 = temp2 - '0';
if (temp2>10)
temp2 = temp2 -7;
SB[*slen] = temp1*16+temp2;
(*slen)++;
}
}
}
.h文件
// Serial_DemoDlg.h : header file
//
//{{AFX_INCLUDES()
#include "mscomm.h"
//}}AFX_INCLUDES
#if !defined(AFX_SERIAL_DEMODLG_H__DE508F99_1751_4DEB_A238_570FE83B6374__INCLUDED_)
#define AFX_SERIAL_DEMODLG_H__DE508F99_1751_4DEB_A238_570FE83B6374__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/
// CSerial_DemoDlg dialog
typedef unsigned short UShort;
class CSerial_DemoDlg : public CDialog
{
// Construction
public:
CSerial_DemoDlg(CWnd* pParent = NULL); // standard constructor
public:
void EnumerateSerialPorts(CUIntArray& porta, CUIntArray& portse, CUIntArray& portsu);
UShort AddCom(CComboBox* pvect);
long GetCommPortN(); // 获取COMBO BOX上的串口编号
CString GetCommPortParameter(); // 获取串口参数
void StringtoHex(BYTE *GB, int glen, BYTE* SB, int* slen);
// Dialog Data
//{{AFX_DATA(CSerial_DemoDlg)
enum { IDD = IDD_SERIAL_DEMO_DIALOG };
CComboBox m_COMBO_StopBit;
CComboBox m_StopBit;
CComboBox m_COMBO_DaBit;
CComboBox m_COMBO_CkBit;
CComboBox m_COMBO_ChooseSel;
CComboBox m_COMBO_BotRat;
BOOL m_GetHexData;
BOOL m_SendDataTime;
BOOL m_SendHexTime;
CString m_EDIT_GetData;
CString m_EDIT_SendData;
int m_EDIT_SendDataTime;
CMSComm m_Comm;
int SendDataTimeState;
int GetHexDataState;
int SendHexDataState;
int SendDataBata;
long GetDataBata;
CString m_EDIT_GetDataBate;
CString m_EDIT_SendDataBate;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSerial_DemoDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CSerial_DemoDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnButtonOpensel();
afx_msg void OnButtonSerchsel();
afx_msg void OnOnCommMscomm();
afx_msg void OnButtonSenddata();
afx_msg void OnButtonClosesel();
afx_msg void OnCheckSenddatatime();
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnButtonCleargetdata();
afx_msg void OnButtonClearsenddata();
afx_msg void OnCheckGethexdata();
afx_msg void OnCheckSendhexdata();
DECLARE_EVENTSINK_MAP()
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_SERIAL_DEMODLG_H__DE508F99_1751_4DEB_A238_570FE83B6374__INCLUDED_)
Resource.h文件
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by Serial_Demo.rc
//
#define IDM_ABOUTBOX 0x0010
#define IDD_ABOUTBOX 100
#define IDS_ABOUTBOX 101
#define IDD_SERIAL_DEMO_DIALOG 102
#define IDR_MAINFRAME 128
#define IDC_BUTTON_SERCHSEL 1000
#define IDC_COMBO_CHOOSESEL 1001
#define IDC_COMBO_BOTRAT 1002
#define IDC_COMBO_DABIT 1003
#define IDC_COMBO_CKBIT 1004
#define IDC_COMBO_STOPBIT 1005
#define IDC_BUTTON_OPENSEL 1006
#define IDC_BUTTON_CLOSESEL 1007
#define IDC_EDIT_GETDATABATE 1008
#define IDC_EDIT_SENDDATABATE 1009
#define IDC_EDIT_GETDATA 1010
#define IDC_EDIT_SENDDATA 1011
#define IDC_CHECK_SENDDATATIME 1012
#define IDC_EDIT_SENDDATATIME 1013
#define IDC_CHECK_GETHEXDATA 1014
#define IDC_BUTTON_CLEARGETDATA 1015
#define IDC_CHECK_SENDHEXDATA 1016
#define IDC_BUTTON_CLEARSENDDATA 1017
#define IDC_MSCOMM1 1018
#define IDC_BUTTON_SENDDATA 1019
#define IDC_TIMER 1020
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1020
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
到了这里,关于【用MFC写串口调试助手】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!