⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scommtooldlg.cpp

📁 是一个串口通信程序
💻 CPP
字号:
// SCommToolDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "SCommTool.h"
#include "SCommToolDlg.h"
#include ".\scommtooldlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

bool		g_bGreenRight = false;
bool		g_burnSNReady = false;

bool		g_timerExist = false;	//定时器是否存在

int			g_comState = COM_DEBUG;
int			g_showColor = SHOW_COLOR_DEFAULT;

static CString s_aComPortStr[COM_PORT_END] = 
{
	"COM_1",
	"COM_2"
};

static CString s_aBaudRateStr[BAUD_RATE_END] = 
{
	"1200",
	"2400",
	"4800",
	"9600",
	"19200",
	"38400",
	"57600",
	"115200",
	"230400",
	"460800",
	"921600"
};

static CString s_aDataBitStr[DATA_BIT_END] = 
{
	"5 bit",
	"6 bit",
	"7 bit",
	"8 bit"
};

static CString s_aParityStr[PARI_END] = 
{
	"none",
	"even",
	"odd"
};

static CString s_aStopBitStr[DATA_BIT_END] = 
{
	"1",
	"1.5",
	"2"
};


// 用于应用程序“关于”菜单项的 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()

// CSCommToolDlg 对话框

CSCommToolDlg::CSCommToolDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSCommToolDlg::IDD, pParent)
, m_curListBoxLin(0)
, m_strWXData(0)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CSCommToolDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_COMBO_PORT, m_commPortComBox);
	DDX_Control(pDX, IDC_COMBO_BAUD_RATE, m_commBaudRateComBox);
	DDX_Control(pDX, IDC_COMBO_DATA_BIT, m_commDataBitComBox);
	DDX_Control(pDX, IDC_COMBO_PARITY, m_commParityComBox);
	DDX_Control(pDX, IDC_COMBO_STOP_BIT, m_commStopBitComBox);
	DDX_Control(pDX, IDC_MSCOMM1, m_ctrlComm);
	DDX_Control(pDX, IDC_LIST1, m_ListInfoBox);
	DDX_Text(pDX, IDC_EDIT1, m_strWXData);
	DDV_MinMaxUInt(pDX, m_strWXData, 0, UINT_MAX);
}

BEGIN_MESSAGE_MAP(CSCommToolDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON2, OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, OnBnClickedButton3)
	ON_CBN_SELCHANGE(IDC_COMBO_PORT, OnCbnSelchangeComboPort)
	ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
	ON_WM_TIMER()
//	ON_BN_CLICKED(IDC_CHECK_AUTO_SEND, OnBnClickedCheckAutoSend)
END_MESSAGE_MAP()


// CSCommToolDlg 消息处理程序

BOOL CSCommToolDlg::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: 在此添加额外的初始化代码
	InitialComParam();//初始化串口信息(串口参数配置信息)
	InitialMSCOMM();/*打开串口*/

	((CEdit*)GetDlgItem(IDC_EDIT1))->SetWindowText("");

	return TRUE;  // 除非设置了控件的焦点,否则返回 TRUE
}

void CSCommToolDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CSCommToolDlg::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 CSCommToolDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

/*open or close com*/
void CSCommToolDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	if(m_ctrlComm.get_PortOpen())
	{
		SetDlgItemText(IDC_BUTTON2,"Open Com");
		m_ctrlComm.put_PortOpen(FALSE);//关闭串口
	}	
	else
	{
		SetDlgItemText(IDC_BUTTON2,"Close Com");
		InitialMSCOMM();	/*打开串口*/
	}
}

/*clear list*/
void CSCommToolDlg::OnBnClickedButton3()
{
	m_ListInfoBox.ResetContent();
	m_curListBoxLin = 0;
}

void CSCommToolDlg::InitialComParam()
{
	int i = 0;

	//初始化串口选择控件
	for (i=0; i<COM_PORT_END; i++)
	{
		m_commPortComBox.InsertString(i, s_aComPortStr[i]);
	}

	//初始化波特率选择控件
	for (i=0; i<BAUD_RATE_END; i++)
	{
		m_commBaudRateComBox.InsertString(i, s_aBaudRateStr[i]);
	}

	//初始化数据位选择控件
	for (i=0; i<DATA_BIT_END; i++)
	{
		m_commDataBitComBox.InsertString(i, s_aDataBitStr[i]);
	}

	//初始化奇偶校验选择控件
	for (i=0; i<PARI_END; i++)
	{
		m_commParityComBox.InsertString(i, s_aParityStr[i]);

	}

	//初始化停止位选择控件
	for (i=0; i<STOP_BIT_END; i++)
	{
		m_commStopBitComBox.InsertString(i, s_aStopBitStr[i]);
	}

	m_commPortComBox.SetCurSel(0);
	m_commBaudRateComBox.SetCurSel(7);
	m_commDataBitComBox.SetCurSel(3);
	m_commParityComBox.SetCurSel(0);
	m_commStopBitComBox.SetCurSel(0);
}

void CSCommToolDlg::OnCbnSelchangeComboPort()
{
	// TODO: 在此添加控件通知处理程序代码
}


BEGIN_EVENTSINK_MAP(CSCommToolDlg, CDialog)
	ON_EVENT(CSCommToolDlg, IDC_MSCOMM1, 1, OnComm, VTS_NONE)
END_EVENTSINK_MAP()

void CSCommToolDlg::OnComm()
{
	// TODO: 在此处添加消息处理程序代码
	VARIANT variant_inp;
	COleSafeArray safearray_inp;
	LONG len,k = 0;
	BYTE aRXdata[(4*1020)+5];// XMODEM_SUB_BLOCK_SIZE
	CString tmpString, listBoxString = "";
	static CString		s_recCharBuff;				//接收信息缓存
	static bool			s_errorInfoStart = true;
	
	if(m_ctrlComm.get_CommEvent()==2) //事件值为2表示接收缓冲区内有字符
	{   
		//UpdateData(TRUE);

		variant_inp=m_ctrlComm.get_Input();		//读缓冲区
		safearray_inp=variant_inp;			//VARIANT型变量转换为ColeSafeArray型变量
		len=safearray_inp.GetOneDimSize();	//得到有效数据长度

		for(k=0; k<len; k++)
			safearray_inp.GetElement(&k,aRXdata+k);//转换为BYTE型数组

		if (g_comState == COM_DEBUG)
		{
			switch(aRXdata[0])
			{
			case J_XMODEM_RSN:
				StartAutoSendSN(); /*进入烧写序列号,启动自动烧写序列号*/
				g_comState = COM_SN;
				g_burnSNReady = true;
				s_errorInfoStart = true;
				listBoxString = "";
				break;
			default:
				for(k=0;k<len;k++) //将数组转换为Cstring型变量
				{
					BYTE bt=*(char*)(aRXdata+k); //字符型
					tmpString.Format("%c",bt); //将字符送入临时变量strtemp存放
					listBoxString += tmpString; //加入接收编辑框对应字符串 
				}
			}
		}
		else if (g_comState == COM_SN)
		{
			switch(aRXdata[0])
			{
			case J_XMODEM_RSN:
				g_burnSNReady = true;
				listBoxString = "";
				s_recCharBuff = "";
				if(s_errorInfoStart)
				{
					listBoxString = "请扫描序列号开始烧写序列号.........\n";
					s_errorInfoStart = false;
				}
				break;
			case J_XMODEM_NAK:
				g_burnSNReady = true;
				s_recCharBuff = "";
				listBoxString = "接收序列号失败,自动重新发送\n";
				SentSN();
				break;
			case J_XMODEM_CAN:
				StopAutoSendSN();
				g_burnSNReady = false;
				g_comState = COM_DEBUG;
				s_recCharBuff = "";
				listBoxString = "自动发送次数超出限制,烧写失败!!\n";
				break;
			case J_XMODEM_ACK:
				StopAutoSendSN();
				g_burnSNReady = false;
				g_comState = COM_DEBUG;
				s_recCharBuff = "";
				listBoxString = "序列号烧写成功\n";
				((CEdit*)GetDlgItem(IDC_EDIT1))->SetWindowText("");
				break;
			default:
				for(k=0;k<len;k++) //将数组转换为Cstring型变量
				{
					BYTE bt=*(char*)(aRXdata+k); //字符型
					tmpString.Format("%c",bt); //将字符送入临时变量strtemp存放
					listBoxString += tmpString; //加入接收编辑框对应字符串 
				}
			}
		}

		m_ctrlComm.get_Input();	//清空数据
		if(listBoxString != "")
		{
			s_recCharBuff = UpdateListBoxInfo(s_recCharBuff + listBoxString);
		}
	}
}

CString CSCommToolDlg::UpdateListBoxInfo(CString cInfoStr)
{
	CString cLinStr = "";
	char	*pStrBuff = NULL;
	int		i = 0;
	bool	bLastChar = false;
	
	if(cInfoStr == "")
		return cInfoStr;

	pStrBuff = (char*)malloc(cInfoStr.GetLength());
	memset(pStrBuff, 0, cInfoStr.GetLength());

	for(i=0; i<cInfoStr.GetLength(); i++)
	{
		pStrBuff[i] = cInfoStr.GetAt(i);
	}

	for(i=0 ;(i<cInfoStr.GetLength() && pStrBuff[i]!='\0'); i++)
	{
		if(pStrBuff[i]=='\n')
		{
			m_ListInfoBox.InsertString(m_curListBoxLin++, cLinStr, g_showColor);
			m_ListInfoBox.SetTopIndex(m_curListBoxLin-1);
			g_showColor = SHOW_COLOR_DEFAULT;
			bLastChar = true;
			cLinStr="";
		}
		else if (pStrBuff[i] == J_XMODEM_COLOR_GREEN)
		{
			g_showColor = SHOW_COLOR_GREEN;
		}
		else if (pStrBuff[i] == J_XMODEM_COLOR_RED)
		{
			g_showColor = SHOW_COLOR_RED;
		}
		else
		{
			cLinStr += pStrBuff[i];
			bLastChar = false;
		}
	}

	free(pStrBuff);
	return cLinStr;
}

bool CSCommToolDlg::InitialMSCOMM()
{
	CString comParam = "";

	CString aDataBit[DATA_BIT_END] = 
	{
		"5", "6", "7", "8"
	};

	CString aParityStr[PARI_END] = 
	{
		"n", "e", "o"
	};

	CString aStopBitStr[DATA_BIT_END] = 
	{
		"1", "1.5", "2"
	};

	comParam = s_aBaudRateStr[m_commBaudRateComBox.GetCurSel()] + "," +
		aParityStr[m_commParityComBox.GetCurSel()] + "," +
		aDataBit[m_commDataBitComBox.GetCurSel()] + "," +
		aStopBitStr[m_commStopBitComBox.GetCurSel()];

	if (m_ctrlComm.get_PortOpen())
	{
		m_ctrlComm.put_PortOpen(FALSE);
	}

	m_ctrlComm.put_CommPort(m_commPortComBox.GetCurSel() + 1); //选择com1
	m_ctrlComm.put_InBufferSize(COM_INPUT_BUFFER_SIZE);
	m_ctrlComm.put_OutBufferSize(COM_OUTPUT_BUFFER_SIZE);

	m_ctrlComm.put_PortOpen(true);	/*打开串口*/

	m_ctrlComm.put_InputMode(1);	//Binary mode
	m_ctrlComm.put_Settings(comParam);	//波特率9600,无校验,8个数据位,1个停止位 
	m_ctrlComm.put_RThreshold(1);		//参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件
	m_ctrlComm.put_InputLen(0); //设置当前接收区数据长度为0
	m_ctrlComm.get_Input();		//先预读缓冲区以清除残留数据

	if (!m_ctrlComm.get_PortOpen())
	{			
		MessageBox("串口打开失败!","信息",MB_ICONERROR | MB_OK);
		return false;
	}
	return true;
}


void CSCommToolDlg::OnBnClickedButton1()
{
	(CEdit *)GetDlgItem(IDC_EDIT1)->SetFocus();
	SentSN();
}

/************************************************************************/
/* 发送SN到loader                                                       */
/************************************************************************/
void CSCommToolDlg::SentSN()
{	
	CString SNText = "";
	if (g_burnSNReady)
	{
		GetDlgItemText(IDC_EDIT1, SNText);
		if (!(SNText == ""))
		{
			UpdateData(TRUE);
			if (m_strWXData != 0)
			{
				unsigned int  aHeadBuff[2];
				aHeadBuff[0] = m_strWXData;
				aHeadBuff[1] = ~m_strWXData;

				UartSendOutChar(2*sizeof(int), (unsigned char *)aHeadBuff);
			}
		}
	}
}


void CSCommToolDlg::UartSendOutChar(int size, unsigned char* pBuff)
{
	CByteArray cByteSendDataBlock;

	cByteSendDataBlock.RemoveAll();
	cByteSendDataBlock.SetSize(size);

	for( int i=0; i<size; i++)
	{
		cByteSendDataBlock.SetAt(i, pBuff[i]);
	}
	m_ctrlComm.put_Output(COleVariant(cByteSendDataBlock)) ;
}

BOOL CSCommToolDlg::PreTranslateMessage(MSG* pMsg)
{
	if(pMsg->message == WM_KEYDOWN)   
	{   
		switch(pMsg->wParam)   
		{ 
		case VK_RETURN://屏蔽回车 
			if (GetFocus()->GetDlgCtrlID() == IDC_EDIT1)
			{
				SentSN();
			}
			return   TRUE;   
		case VK_ESCAPE://屏蔽Esc   
			return   TRUE;   
		}   
	}   
	return   CDialog::PreTranslateMessage(pMsg);   
}

void CSCommToolDlg::OnTimer(UINT nIDEvent)
{
	if (nIDEvent == 1)
	{
		if (IsDlgButtonChecked(IDC_CHECK_AUTO_SEND))
		{
			SentSN();
		}
	}

	CDialog::OnTimer(nIDEvent);
}


void CSCommToolDlg::StartAutoSendSN()
{
	if (!g_timerExist)
	{
		SetTimer(1, 1000, NULL);
		g_timerExist = true;
	}
}

void CSCommToolDlg::StopAutoSendSN()
{
	if (g_timerExist)
	{
		KillTimer(1);
		g_timerExist = false;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -