www.pudn.com > SerialPortTest.rar > SerialPortTestDlg.cpp
// SerialPortTestDlg.cpp : implementation file
//
#include "stdafx.h"
#include "SerialPortTest.h"
#include "SerialPortTestDlg.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()
/////////////////////////////////////////////////////////////////////////////
// CSerialPortTestDlg dialog
CSerialPortTestDlg::CSerialPortTestDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSerialPortTestDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CSerialPortTestDlg)
m_strEditReceiveMsg = _T("");
m_strEditSendMsg = _T("");
m_unEditPosition = 0;
m_unEditVelocity = 0;
m_unEditVelocity2 = 0;
m_unEditPosition2 = 0;
m_strEditDispData2 = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_bSerialPortOpened=FALSE; //初始状态:串口1没有打开
m_bSerialPortOpened2=FALSE; //初始状态:串口2没有打开
m_unPort=1;
m_unPort2=2;
m_strPortRXData2="";
m_strChecksum2="";
}
void CSerialPortTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSerialPortTestDlg)
DDX_Control(pDX, IDC_STATIC_ICONS1, m_ctrlStaticIconS1);
DDX_Control(pDX, IDC_STATIC_ICONS2, m_ctrlStaticIconS2);
DDX_Control(pDX, IDC_STATIC_ICONS3, m_ctrlStaticIconS3);
DDX_Control(pDX, IDC_STATIC_ICONS4, m_ctrlStaticIconS4);
DDX_Control(pDX, IDC_STATIC_ICONS5, m_ctrlStaticIconS5);
DDX_Control(pDX, IDC_STATIC_ICONS6, m_ctrlStaticIconS6);
DDX_Control(pDX, IDC_STATIC_ICONS7, m_ctrlStaticIconS7);
DDX_Control(pDX, IDC_STATIC_ICONS8, m_ctrlStaticIconS8);
DDX_Control(pDX, IDC_STATIC_ICONS9, m_ctrlStaticIconS9);
DDX_Control(pDX, IDC_CHECK_SWITCH1, m_ctrlCheckSwitch1);
DDX_Control(pDX, IDC_CHECK_SWITCH2, m_ctrlCheckSwitch2);
DDX_Control(pDX, IDC_CHECK_SWITCH3, m_ctrlCheckSwitch3);
DDX_Control(pDX, IDC_CHECK_SWITCH4, m_ctrlCheckSwitch4);
DDX_Control(pDX, IDC_CHECK_SWITCH5, m_ctrlCheckSwitch5);
DDX_Control(pDX, IDC_CHECK_SWITCH6, m_ctrlCheckSwitch6);
DDX_Control(pDX, IDC_CHECK_SWITCH7, m_ctrlCheckSwitch7);
DDX_Control(pDX, IDC_CHECK_SWITCH8, m_ctrlCheckSwitch8);
DDX_Control(pDX, IDC_CHECK_SWITCH9, m_ctrlCheckSwitch9);
DDX_Control(pDX, IDC_COMBO_COMPORT2, m_ctrlComboComPort2);
DDX_Control(pDX, IDC_COMBO_COMPORT, m_ctrlComboComPort);
DDX_Text(pDX, IDC_EDIT_RECEIVEMSG, m_strEditReceiveMsg);
DDX_Text(pDX, IDC_EDIT_SENDMSG, m_strEditSendMsg);
DDX_Text(pDX, IDC_EDIT_POSITION, m_unEditPosition);
DDV_MinMaxUInt(pDX, m_unEditPosition, 0, 31);
DDX_Text(pDX, IDC_EDIT_VELOCITY, m_unEditVelocity);
DDV_MinMaxUInt(pDX, m_unEditVelocity, 0, 120);
DDX_Text(pDX, IDC_EDIT_VELOCITY2, m_unEditVelocity2);
DDX_Text(pDX, IDC_EDIT_POSITION2, m_unEditPosition2);
DDX_Text(pDX, IDC_EDIT_DISPDATA2, m_strEditDispData2);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CSerialPortTestDlg, CDialog)
//{{AFX_MSG_MAP(CSerialPortTestDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_MESSAGE(WM_COMM_RXCHAR, OnComm)
ON_BN_CLICKED(IDC_BUTTON_OPEN, OnButtonOpen)
ON_BN_CLICKED(IDC_BUTTON_CLOSE, OnButtonClose)
ON_BN_CLICKED(IDC_BUTTON_SEND, OnButtonSend)
ON_BN_CLICKED(IDC_BUTTON_OPEN2, OnButtonOpen2)
ON_BN_CLICKED(IDC_BUTTON_CLOSE2, OnButtonClose2)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSerialPortTestDlg message handlers
BOOL CSerialPortTestDlg::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_ctrlComboComPort.SetCurSel(0); //初始选择串口1
m_ctrlComboComPort2.SetCurSel(1); //初始选择串口2
//以下两句分别设置“打开串口”、“关闭串口”两个按状态的使能状态
GetDlgItem(IDC_BUTTON_OPEN)->EnableWindow(!m_bSerialPortOpened);
GetDlgItem(IDC_BUTTON_CLOSE)->EnableWindow(m_bSerialPortOpened);
GetDlgItem(IDC_BUTTON_OPEN2)->EnableWindow(!m_bSerialPortOpened2);
GetDlgItem(IDC_BUTTON_CLOSE2)->EnableWindow(m_bSerialPortOpened2);
//载入图标
m_hIconRed = AfxGetApp()->LoadIcon(IDI_ICON_RED);
m_hIconOff = AfxGetApp()->LoadIcon(IDI_ICON_OFF);
return TRUE; // return TRUE unless you set the focus to a control
}
void CSerialPortTestDlg::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 CSerialPortTestDlg::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 CSerialPortTestDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
#define CR 0X0D //回车
#define LF 0X0A //换行
LONG CSerialPortTestDlg::OnComm(WPARAM ch, LPARAM port)
{
static char checksum=0,checksum1=0;
static int count1=0;//,count2=0,count3=0;
static unsigned char buf[20];
static char c1,c2; //用于计算半Byte校验
static int flag; //用于接收阶段标记
static int twoflag=0;
if(port == m_unPort)
{
if(ch>127) //是不是首字节
{
count1=0; //记录接收字符的个数
buf[count1]=ch;
checksum1= ch-128; //开始计算校验值
}
else
{
count1++;
buf[count1]=ch;
checksum1 = checksum1^ch;
if(count1==3) //包括校验字节在内的全部接收完毕
{
if(checksum1) //校验错
{
m_strEditReceiveMsg = "接收校验出错";
UpdateData(FALSE);
}
else
{
CString str;
unsigned char * temp=(unsigned char*)buf;
m_strEditReceiveMsg ="接收到的简单通信协议字节为:";
for(int i=0;i<4;i++)
{
str.Format("%02X ",*(buf+i));
m_strEditReceiveMsg += str;
}
UpdateData(FALSE);
}
if(count1>5) //防止出错
count1=0;
}
}
}
if(port==m_unPort2) //串口2的数据处理
{
m_strPortRXData2 += (char)ch;
switch(ch)
{
case '$':
checksum=0; //开始计算CheckSum
flag=0;
break;
case '*': //有效数据结束,可以$和*之间数据的半Byte校验值了
flag=2;
c2=checksum & 0x0f; c1=((checksum >> 4) & 0x0f);
if (c1 < 10) c1+= '0'; else c1 += 'A' - 10;
if (c2 < 10) c2+= '0'; else c2 += 'A' - 10;
break;
case CR: //这句必须加上,否则会出错的
break;
case LF: //数据包的最后一个字符
m_strPortRXData2.Empty();
break;
default:
if(flag>0) //注意:只有在接收到'*'后,flag才大于0
{
m_strChecksum2 += ch;
if(flag==1)
{
CString strCheck="";
strCheck.Format("%c%c",c1,c2);
if(strCheck!=m_strChecksum2) //校验计算不正确,说明接收数据出错
{
m_strPortRXData2.Empty();
}
else //校验计算正确则处理数据
{
CString strSwitchSetData;
strSwitchSetData = m_strPortRXData2.Mid(1,9);
//以下设置信号灯状态
for(int i=0;i<9;i++)
{
if(strSwitchSetData.Mid(i,1)=="1")
SetSwitchStatus(i+1,TRUE);
else
SetSwitchStatus(i+1,FALSE);
}
//以下取出位置与速度数据
CString strTemp;
strTemp = m_strPortRXData2.Mid(10,5);
char *temp=(char*)((LPCTSTR)strTemp);
char tbuf[4];
tbuf[0]=temp[0]; tbuf[1]=temp[1]; tbuf[2]=0;
m_unEditPosition2 = atoi(tbuf); //得到位置状态值
tbuf[0]=temp[2]; tbuf[1]=temp[3];
tbuf[2]=temp[4]; tbuf[3]=0;
m_unEditVelocity2 = atoi(tbuf); //得到速度值
//将接收到的数据包内容显示
m_strEditDispData2 = "接收到NMEA数据包:"+m_strPortRXData2;
//下面准备发送"简单自定义通信协议"数据包
unsigned char ucChar[4];
//首字节
ucChar[0]=0x80; //首字节最高位置1
if(strSwitchSetData.Mid(0,1)=="1") // 开关1状态
ucChar[0] |= 0x40; //0100 0000
else
ucChar[0] &= 0xBF; //1011 1111
if(strSwitchSetData.Mid(1,1)=="1") // 开关2状态
ucChar[0] |= 0x20; //0010 0000
else
ucChar[0] &= 0xDF; //1101 1111
if(m_unEditPosition2>31) //对位置值进行限值
m_unEditPosition2=31;
ucChar[0] &= 0xE0; //将首字节的低5位置0
ucChar[0] += m_unEditPosition2; //再加上位置值
ucChar[3] = ucChar[0]; //同时计算校验值
//第二字节
unsigned char ucTemp=0x40;
for(i=0; i<7; i++)
{
if(strSwitchSetData.Mid(2+i,1)=="1")
ucChar[1] |= ucTemp;
else
ucChar[1] &= (~ucTemp);
ucTemp >>= 1;
}
ucChar[1] &= 0x7F; //前面做了那么多运算,用这条语句保证一下最高位为0
ucChar[3] ^= ucChar[1]; //计算校验值
//第三字节
if(m_unEditVelocity2>120)
m_unEditVelocity2=120;
ucChar[2] = m_unEditVelocity2;
ucChar[3] ^= ucChar[2]; //计算校验值
//第四字节
ucChar[3] &= 0x7F;
//把"简单自定义通信协议"数据包发送出去
if(m_bSerialPortOpened2)
m_SerialPort2.WriteToPort(ucChar,4);
//同时把发送的内容显示
CString strTemp1;
strTemp= _T("发送的内容为: ");
for(int j=0;j<4;j++)
{
strTemp1.Format("0x%02X",ucChar[j]);
strTemp += strTemp1 + ",";
}
m_strEditDispData2 += strTemp;
UpdateData(FALSE);
}
m_strChecksum2.Empty();
}
//从'*'后收,flag=2,1次减1操作,正好将数据包的校验值保存在m_strChecksum中
flag--;
}
else
checksum=checksum^ch; //当flag<=0时,计算校验值
break;
}
}
return 0;
}
void CSerialPortTestDlg::OnButtonOpen()
{
// TODO: Add your control notification handler code here
int nPort=m_ctrlComboComPort.GetCurSel()+1; //得到串口号,想想为什么要加1
if(m_SerialPort.InitPort(this, nPort, 9600,'N',8,1,EV_RXFLAG | EV_RXCHAR,512))
{
m_SerialPort.StartMonitoring();
m_bSerialPortOpened=TRUE;
m_unPort=nPort;
}
else
{
AfxMessageBox("没有发现此串口或被占用");
m_bSerialPortOpened=FALSE;
}
GetDlgItem(IDC_BUTTON_OPEN)->EnableWindow(!m_bSerialPortOpened);
GetDlgItem(IDC_BUTTON_CLOSE)->EnableWindow(m_bSerialPortOpened);
}
void CSerialPortTestDlg::OnButtonClose()
{
// TODO: Add your control notification handler code here
m_SerialPort.ClosePort();//关闭串口
m_bSerialPortOpened=FALSE;
GetDlgItem(IDC_BUTTON_OPEN)->EnableWindow(!m_bSerialPortOpened);
GetDlgItem(IDC_BUTTON_CLOSE)->EnableWindow(m_bSerialPortOpened);
}
void CSerialPortTestDlg::OnButtonSend()
{
// TODO: Add your control notification handler code here
if(!m_bSerialPortOpened) //检查串口是否打开
{
AfxMessageBox("串口没有打开");
return;
}
UpdateData(TRUE); //读入编辑框中的数据
CString strSend=""; //要发送的NEMA字符串
//以下读入9个开关的设置状态
for(int i=1;i<=9;i++)
{
if(GetSwitchStatus(i))
strSend+='1';
else
strSend+='0';
}
CString strTemp;
strTemp.Format("%02d",m_unEditPosition);
strSend+=strTemp;
strTemp.Format("%03d",m_unEditVelocity);
strSend+=strTemp;
SendNMEAData(strSend);
}
//该函数用于设置开关的信号灯状态,如开关5开启,
//可设置为 SetSwitchStatus(5,TRUE);
void CSerialPortTestDlg::SetSwitchStatus(UINT unSwtich,BOOL bStatus)
{
if(bStatus)
{
switch(unSwtich) {
case 1:
m_ctrlStaticIconS1.SetIcon(m_hIconRed);
break;
case 2:
m_ctrlStaticIconS2.SetIcon(m_hIconRed);
break;
case 3:
m_ctrlStaticIconS3.SetIcon(m_hIconRed);
break;
case 4:
m_ctrlStaticIconS4.SetIcon(m_hIconRed);
break;
case 5:
m_ctrlStaticIconS5.SetIcon(m_hIconRed);
break;
case 6:
m_ctrlStaticIconS6.SetIcon(m_hIconRed);
break;
case 7:
m_ctrlStaticIconS7.SetIcon(m_hIconRed);
break;
case 8:
m_ctrlStaticIconS8.SetIcon(m_hIconRed);
break;
case 9:
m_ctrlStaticIconS9.SetIcon(m_hIconRed);
break;
default:
break;
}
}
else
{
switch(unSwtich) {
case 1:
m_ctrlStaticIconS1.SetIcon(m_hIconOff);
break;
case 2:
m_ctrlStaticIconS2.SetIcon(m_hIconOff);
break;
case 3:
m_ctrlStaticIconS3.SetIcon(m_hIconOff);
break;
case 4:
m_ctrlStaticIconS4.SetIcon(m_hIconOff);
break;
case 5:
m_ctrlStaticIconS5.SetIcon(m_hIconOff);
break;
case 6:
m_ctrlStaticIconS6.SetIcon(m_hIconOff);
break;
case 7:
m_ctrlStaticIconS7.SetIcon(m_hIconOff);
break;
case 8:
m_ctrlStaticIconS8.SetIcon(m_hIconOff);
break;
case 9:
m_ctrlStaticIconS9.SetIcon(m_hIconOff);
break;
default:
break;
}
}
}
//该函数用于得到设置的开关状态值
BOOL CSerialPortTestDlg::GetSwitchStatus(UINT unSwitch)
{
BOOL bStatus=FALSE;
switch(unSwitch) {
case 1:
bStatus = m_ctrlCheckSwitch1.GetCheck();
break;
case 2:
bStatus = m_ctrlCheckSwitch2.GetCheck();
break;
case 3:
bStatus = m_ctrlCheckSwitch3.GetCheck();
break;
case 4:
bStatus = m_ctrlCheckSwitch4.GetCheck();
break;
case 5:
bStatus = m_ctrlCheckSwitch5.GetCheck();
break;
case 6:
bStatus = m_ctrlCheckSwitch6.GetCheck();
break;
case 7:
bStatus = m_ctrlCheckSwitch7.GetCheck();
break;
case 8:
bStatus = m_ctrlCheckSwitch8.GetCheck();
break;
case 9:
bStatus = m_ctrlCheckSwitch9.GetCheck();
break;
default:
break;
}
return bStatus;
}
void CSerialPortTestDlg::OnButtonOpen2()
{
// TODO: Add your control notification handler code here
int nPort=m_ctrlComboComPort2.GetCurSel()+1; //得到串口号
if(m_SerialPort2.InitPort(this, nPort, 9600,'N',8,1,EV_RXFLAG | EV_RXCHAR,512))
{
m_SerialPort2.StartMonitoring();
m_bSerialPortOpened2=TRUE;
m_unPort2=nPort; //记录打开的串口号
}
else
{
AfxMessageBox("没有发现此串口或被占用");
m_bSerialPortOpened2=FALSE;
}
GetDlgItem(IDC_BUTTON_OPEN2)->EnableWindow(!m_bSerialPortOpened2);
GetDlgItem(IDC_BUTTON_CLOSE2)->EnableWindow(m_bSerialPortOpened2);
}
void CSerialPortTestDlg::OnButtonClose2()
{
// TODO: Add your control notification handler code here
m_SerialPort2.ClosePort();//关闭串口2
m_bSerialPortOpened2=FALSE;
GetDlgItem(IDC_BUTTON_OPEN2)->EnableWindow(!m_bSerialPortOpened2);
GetDlgItem(IDC_BUTTON_CLOSE2)->EnableWindow(m_bSerialPortOpened2);
}
//用于将字符串打包成NMEA通信协议包
void CSerialPortTestDlg::SendNMEAData(CString &strData)
{
char checksum=0,cr=13,ln=10;
char c1,c2; //2个 半Bype 校验值
for(int i=0;i> 4) & 0x0F);
if (c1 < 10) c1+= '0'; else c1 += 'A' - 10;
if (c2 < 10) c2+= '0'; else c2 += 'A' - 10;
CString strNMEAData;
//加上包头,尾和校验值和回车换行符
strNMEAData='$'+strData+"*"+c1+c2+cr+ln;
//以下几行程序关不通用,在自己的程序中注意修改
m_SerialPort.WriteToPort((LPCTSTR)strNMEAData);
m_strEditSendMsg.Format("发送的数据包为:%s",strNMEAData);
UpdateData(FALSE); //在发送显示编辑框中显示发送的数据包
}