MFC实现两个串口之间互相转发数据
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
MFC实现两个串口之间互相转发数据
本文档介绍一种基VS软件使用MFC框架开发一款软件工具的方法,实现两个串口之间互相转发数据的功能,通过该工具可以进行串口数据监听,支持两个不同通信参数的串口之间互相通信及数据转发,给相关的技术人员在排查问题的时候提供方便。
本文档将介绍该工具的使用说明、工具开发流程及提供主要功能对应的代码。
目录
一.使用说明 (1)
1.创建虚拟串口 (1)
2. 串口转发工具配置 (2)
3. 配置两个终端的串口通信参数 (2)
4. 数据互发验证 (3)
二.开发项目创建 (4)
1创建MFC对话框 (4)
2输入项目名称 (4)
3应用程序类型配置 (4)
4在资源视图添加各种控件 (5)
5给各种控件新增成员变量 (6)
6在资源视图下新增定时事件 (7)
三.代码实现 (7)
1.依次在各个按钮下新增触发事件的函数 (7)
2.添加初始化代码 (8)
3编译生成exe文件 (9)
4运行exe文件 (9)
四.附带关键功能的代码 (10)
串口转发拓扑图
一.使用说明
这里主要用虚拟串口为例子,实际的应用场合跟虚拟的使用方式是一样的。
1.创建虚拟串口
使用vspdpro(用其它工具也可以)创建两对虚拟串口。
两对虚拟串口分别为:COM3<->COM4 ,COM9<->COM10。
2.串口转发工具配置
工具界面如下所示,依次配置两个串口的通信参数。
3.配置两个终端的串口通信参数
为了方便区分,使用两个不同的模拟软件,如下所示:
4.数据互发验证
二.开发项目创建
1创建MFC对话框
打开VS2008开发软件,依次点击”文件”->“新建”->”项目”,在项目类型下选择“MFC”,如下图所示。
2输入项目名称
项目名称可以随意输入,例如“Mycom”。
3应用程序类型配置
选择”基于对话框”->”在静态库中使用MFC”,点击完成。
4在资源视图添加各种控件
在右边工具箱,选择各种控件,如下图所示。
最终生成如下所示的界面:
5给各种控件新增成员变量
6在资源视图下新增定时事件
新增定时事件,在项目属性那一栏,找到“WM_TIMER”,增加回调函数,如下图所示:
三.代码实现
1.依次在各个按钮下新增触发事件的函数
以打开串口为例子,如下所示:
双击该按钮,跳转到对应的事件处理函数。
2.添加初始化代码
添加位置如下图所示:
3编译生成exe文件
点击生成后选择“生成解决方案”->”编译”。
4运行exe文件
点击调试->“开始执行”,这个时候就可以开始进行调试了。
四.附带关键功能的代码
// MycomDlg.cpp : 实现文件
#include "stdafx.h"
#include "Mycom.h"
#include "MycomDlg.h"
#include "uart.h"
#include <string.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 用于应用程序“关于”菜单项的CAboutDlg 对话框
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CMycomDlg 对话框
CMycomDlg::CMycomDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMycomDlg::IDD, pParent)
, m_strRXData(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMycomDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_COMBO1, m_combo_select);
DDX_Text(pDX, IDC_EDIT_RXDATA, m_strRXData);
DDX_Control(pDX, IDC_EDIT_TXDATA, m_strTXData);
DDX_Control(pDX, IDC_COMBO2, m_combo_select1);
DDX_Control(pDX, IDC_COMBO_BAUD1, m_baud1);
DDX_Control(pDX, IDC_COMBO_BAUD2, m_baud2);
DDX_Control(pDX, IDC_COMBO_DATABIT1, m_databit1);
DDX_Control(pDX, IDC_COMBO_DATA2, m_databit2);
DDX_Control(pDX, IDC_COMBO_STOP1, m_stopbit1);
DDX_Control(pDX, IDC_COMBO_STOP2, m_stopbit2);
DDX_Control(pDX, IDC_COMBO_CHK1, m_chk1);
DDX_Control(pDX, IDC_COMBO_CHK2, m_chk2);
}
BEGIN_MESSAGE_MAP(CMycomDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BUTTON1, &CMycomDlg::OnBnClickedButton1)
ON_CBN_SELCHANGE(IDC_COMBO1, &CMycomDlg::OnCbnSelchangeCombo1)
ON_BN_CLICKED(IDC_BUTTON3, &CMycomDlg::OnBnClickedButton3)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BUTTON2, &CMycomDlg::OnBnClickedButton2)
ON_BN_CLICKED(IDC_BUTTON_CLR_RECV, &CMycomDlg::OnBnClickedButtonClrRecv) ON_CBN_SELCHANGE(IDC_COMBO2, &CMycomDlg::OnCbnSelchangeCombo2)
ON_BN_CLICKED(IDC_BUTTON4, &CMycomDlg::OnBnClickedButton4)
ON_BN_CLICKED(IDC_BUTTON5, &CMycomDlg::OnBnClickedButton5)
END_MESSAGE_MAP()
// CMycomDlg 消息处理程序
BOOL CMycomDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
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);
}
}
// 设置此对话框的图标。
当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE);// 设置大图标
SetIcon(m_hIcon, FALSE);// 设置小图标
// TODO: 在此添加额外的初始化代码
CStringArray arrCom;
CString strTmp;
int i = 0;
int cnt = GetSerialPort(arrCom);
m_combo_select.ResetContent();
while(i<arrCom.GetCount()) {
//m_combo_select.AddString(__T(arrCom[i]));
strTmp = arrCom.GetAt(i);
m_combo_select.AddString(strTmp);
i++;
}
m_combo_select.SetCurSel(0);
SetDlgItemText(IDC_COMBO1, _T(arrCom[0]));
i = 0;
while(i<cnt) {
m_combo_select1.AddString(__T(arrCom[i]));
i++;
}
m_combo_select1.SetCurSel(0);
SetDlgItemText(IDC_COMBO2, _T(arrCom[0]));
init_serial_param();
return TRUE; // 除非将焦点设置到控件,否则返回TRUE
}
void CMycomDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。
对于使用文档/视图模型的MFC 应用程序,
// 这将由框架自动完成。
void CMycomDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
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;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMycomDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CMycomDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
int iPos=((CComboBox*)GetDlgItem(IDC_COMBO1))->GetCurSel();
char com[10] = "";
CString str1;
m_combo_select.GetLBText(iPos,str1);
//AfxMessageBox(__T(str1));
strcpy(com, str1);
//hCom = uart_open(com,115200);
get_serial_param(1);
//str1.Format("%d %d %s %s", baudrate1,databit1,stopbit1,parity1);
//AfxMessageBox(__T(str1));
hCom = uart_open(com,baudrate1);
uart_set_param(hCom,databit1, stopbit1, parity1);
if (INVALID_HANDLE_VALUE != hCom) {
AfxMessageBox(__T("打开串口")+str1);
SetTimer(1,1000,NULL);
}
else
AfxMessageBox(__T("打开串口失败"));
}
void CMycomDlg::OnCbnSelchangeCombo1()
{
// TODO: 在此添加控件通知处理程序代码
int iPos=((CComboBox*)GetDlgItem(IDC_COMBO1))->GetCurSel();
}
void CMycomDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
char buf[2048] ="";
CEdit* pBoxOne;
pBoxOne = (CEdit*) GetDlgItem(IDC_EDIT_TXDATA);
CString str;
pBoxOne->GetWindowText(str);
strcpy(buf,str);
uart_write(hCom,buf,strlen(buf));
uart_write(hCom1,buf,strlen(buf));
}
void CMycomDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (nIDEvent == 1) {
//AfxMessageBox(__T("timeout"));
KillTimer(1);
unsigned char recvbuf[2048] = "";
int len;
len = uart_read(hCom,recvbuf, sizeof(recvbuf));
if (len>0) {
CString str;
if (BST_CHECKED == IsDlgButtonChecked(IDC_CHECK_HEX)) {
CString tmp="";
int i;
for (i = 0; i<len; i++) {
tmp.Format(__T("%02x "),recvbuf[i]);
str+=tmp;
}
m_strRXData+=str;
SetDlgItemText(IDC_EDIT_RXDATA,m_strRXData);
} else {
str.Format(__T("%s"),recvbuf);
m_strRXData+=str;
SetDlgItemText(IDC_EDIT_RXDATA,m_strRXData);
}
if (BST_CHECKED == IsDlgButtonChecked(IDC_CHECK_AUTO_REP)) { uart_write(hCom1,recvbuf,len);
//OnBnClickedButton3();
}
}
SetTimer(1,250,NULL);
}
if (nIDEvent == 2) {
//AfxMessageBox(__T("timeout"));
KillTimer(2);
unsigned char recvbuf[2048] = "";
int len;
len = uart_read(hCom1,recvbuf, sizeof(recvbuf));
if (len>0) {
CString str;
if (BST_CHECKED == IsDlgButtonChecked(IDC_CHECK_HEX)) {
CString tmp="";
int i;
for (i = 0; i<len; i++) {
tmp.Format(__T("%02x "),recvbuf[i]);
str+=tmp;
}
m_strRXData+=str;
SetDlgItemText(IDC_EDIT_RXDATA,m_strRXData);
} else {
str.Format(__T("%s"),recvbuf);
m_strRXData+=str;
SetDlgItemText(IDC_EDIT_RXDATA,m_strRXData);
}
if (BST_CHECKED == IsDlgButtonChecked(IDC_CHECK_AUTO_REP)) { uart_write(hCom,recvbuf,len);
//OnBnClickedButton3();
}
}
SetTimer(2,250,NULL);
}
CDialog::OnTimer(nIDEvent);
}
void CMycomDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
uart_close(hCom);
}
void CMycomDlg::OnBnClickedButtonClrRecv()
{
// TODO: 在此添加控件通知处理程序代码
m_strRXData = "";
SetDlgItemText(IDC_EDIT_RXDATA,m_strRXData);
CEdit* pedit = (CEdit*)GetDlgItem(IDC_EDIT_RXDATA);
pedit->LineScroll(pedit->GetLineCount());
}
void CMycomDlg::OnCbnSelchangeCombo2()
{
// TODO: 在此添加控件通知处理程序代码
int iPos=((CComboBox*)GetDlgItem(IDC_COMBO2))->GetCurSel(); }
void CMycomDlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
int iPos=((CComboBox*)GetDlgItem(IDC_COMBO2))->GetCurSel();
char com[10] = "";
CString str1;
m_combo_select1.GetLBText(iPos,str1);
//AfxMessageBox(__T(str1));
strcpy(com, str1);
get_serial_param(2);
hCom1 = uart_open(com,baudrate2);
uart_set_param(hCom1,databit2, stopbit2, parity2);
if (INVALID_HANDLE_VALUE != hCom1) {
AfxMessageBox(__T("打开串口")+str1);
SetTimer(2,1000,NULL);
}
else
AfxMessageBox(__T("打开串口失败"));
}
void CMycomDlg::OnBnClickedButton5()
{
// TODO: 在此添加控件通知处理程序代码
uart_close(hCom1);
}
void CMycomDlg::init_serial_param()
{
char
baud[][32]={"110","300","600","1200","2400","4800","9600","19200","38400","57600","115200 ","230400"};
int baudcnt=sizeof(baud)/sizeof(baud[0]);
int i=0;
m_baud1.ResetContent();
for(i=0;i<baudcnt;i++) {
m_baud1.AddString(__T(baud[i]));
}
SetDlgItemText(IDC_COMBO_BAUD1, _T("115200"));
for(i=0;i<baudcnt;i++) {
m_baud2.AddString(__T(baud[i]));
}
SetDlgItemText(IDC_COMBO_BAUD2, _T("115200"));
char databit[][32]={"8","7","6","5"};
int databitcnt=sizeof(databit)/sizeof(databit[0]);
for(i=0;i<databitcnt;i++) {
m_databit1.AddString(__T(databit[i]));
}
SetDlgItemText(IDC_COMBO_DATABIT1, _T(databit[0]));
for(i=0;i<databitcnt;i++) {
m_databit2.AddString(__T(databit[i]));
}
SetDlgItemText(IDC_COMBO_DATA2, _T(databit[0]));
char stopbit[][32]={"1","2","0"};
int stopbitcnt=sizeof(stopbit)/sizeof(stopbit[0]);
for(i=0;i<stopbitcnt;i++) {
m_stopbit1.AddString(__T(stopbit[i]));
}
SetDlgItemText(IDC_COMBO_STOP1, _T(stopbit[0]));
for(i=0;i<stopbitcnt;i++) {
m_stopbit2.AddString(__T(stopbit[i]));
}
SetDlgItemText(IDC_COMBO_STOP2, _T(stopbit[0]));
char checkbit[][32]={"None","Odd","Even"};
int checkbitcnt=sizeof(checkbit)/sizeof(checkbit[0]);
for(i=0;i<checkbitcnt;i++) {
m_chk1.AddString(__T(checkbit[i]));
}
SetDlgItemText(IDC_COMBO_CHK1, _T(checkbit[0]));
for(i=0;i<checkbitcnt;i++) {
m_chk2.AddString(__T(checkbit[i]));
}
SetDlgItemText(IDC_COMBO_CHK2, _T(checkbit[0]));
}
void CMycomDlg::get_serial_param(int idx)
{
CString retStr;
if(idx==1) {
m_baud1.GetWindowText(retStr);
baudrate1 = atoi(retStr);
m_databit1.GetWindowText(retStr);
databit1 = atoi(retStr);
m_stopbit1.GetWindowText(retStr);
strcpy(stopbit1, retStr.GetBuffer());
m_chk1.GetWindowText(retStr);
strcpy(parity1, retStr.GetBuffer());
}
else {
m_baud2.GetWindowText(retStr);
baudrate2 = atoi(retStr);
m_databit2.GetWindowText(retStr);
databit2 = atoi(retStr);
m_stopbit2.GetWindowText(retStr);
strcpy(stopbit2, retStr.GetBuffer());
m_chk2.GetWindowText(retStr);
strcpy(parity2, retStr.GetBuffer());
}
}
// MycomDlg.h : 头文件
//
#pragma once
#include "afxwin.h"
#include <Windows.h>
// CMycomDlg 对话框
class CMycomDlg : public CDialog
{
// 构造
public:
CMycomDlg(CWnd* pParent = NULL);// 标准构造函数
// 对话框数据
enum { IDD = IDD_MYCOM_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX);// DDX/DDV 支持// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CComboBox m_combo_select;
afx_msg void OnBnClickedButton1();
afx_msg void OnCbnSelchangeCombo1();
public:
HANDLE hCom;
HANDLE hCom1;
CString m_strRXData;
CEdit m_strTXData;
afx_msg void OnBnClickedButton3();
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnBnClickedButton2();
afx_msg void OnBnClickedButtonClrRecv();
afx_msg void OnCbnSelchangeCombo2();
afx_msg void OnBnClickedButton4();
CComboBox m_combo_select1;
afx_msg void OnBnClickedButton5();
void init_serial_param();
void get_serial_param(int idx);
CComboBox m_baud1;
CComboBox m_baud2;
CComboBox m_databit1;
CComboBox m_databit2;
CComboBox m_stopbit1;
CComboBox m_stopbit2;
CComboBox m_chk1;
CComboBox m_chk2;
int baudrate1;
int databit1;
char stopbit1[12];
char parity1[12];
int baudrate2;
int databit2;
char stopbit2[12];
char parity2[12];
};
// uart.h : 头文件
//
#ifndef __UART_H__
#define __UART_H__
#include <Windows.h>
//CBR_115200,CBR_57600,CBR_56000,CBR_38400,CBR_19200,CBR_14400,CBR_9600,CBR_4800, CBR_2400,CBR_1200,CBR_600,CBR_300,CBR_110
HANDLE uart_open(CString CommName, int rate);
int uart_write(HANDLE hCom, void *pSrc, int len);
int uart_read(HANDLE hCom, void *pRet, int retLen);
int uart_read_count(HANDLE hCom);
int uart_close(HANDLE hCom);
void uart_empty(HANDLE hCom);
void uart_set_speed(HANDLE hCom, int speed);
int GetSerialPort(CStringArray &arrCom);
int uart_set_param(HANDLE hCom,int dataSize,char *pStopBitStr,char *pParityStr);
void uart_set_rts(HANDLE hCom, int isEnable);
#endif。