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

📄 winceserialdlg.cpp

📁 WINCE6下写的一个串口通讯程序
💻 CPP
字号:
// WinCESerialDlg.cpp : implementation file
//

#include "stdafx.h"
#include "WinCESerial.h"
#include "WinCESerialDlg.h"
#include <atlstr.h>
using namespace ATL;


#ifdef _DEBUG
#define new DEBUG_NEW
#endif

HANDLE hPort = INVALID_HANDLE_VALUE;
CString strInChar;

// CWinCESerialDlg dialog

CWinCESerialDlg::CWinCESerialDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CWinCESerialDlg::IDD, pParent)
	, m_iport(0)
	, m_com1state(_T(""))
	, m_com2state(_T(""))
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CWinCESerialDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EDIT_READ, m_ceReadSerial);
	DDX_Control(pDX, IDC_EDIT_SEND, m_ceSendserial);
	DDX_CBIndex(pDX, IDC_COMBO_SERIAL_NAME, m_iport);
	DDX_Text(pDX, IDC_STATIC_COM1_STATE, m_com1state);
	DDX_Text(pDX, IDC_STATIC_COM2_STATE, m_com2state);
}

BEGIN_MESSAGE_MAP(CWinCESerialDlg, CDialog)
#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
	ON_WM_SIZE()
#endif
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BUTTON_SERIAL_OPEN, &CWinCESerialDlg::OnBnClickedButtonSerialOpen)
	ON_BN_CLICKED(IDC_BUTTON_SERIAL_WRITE, &CWinCESerialDlg::OnBnClickedButtonSerialWrite)
	ON_BN_CLICKED(IDC_BUTTON_SERIAL_CLOSE, &CWinCESerialDlg::OnBnClickedButtonSerialClose)
	ON_BN_CLICKED(IDC_BUTTON_CLEAN_DATA, &CWinCESerialDlg::OnBnClickedButtonCleanData)
END_MESSAGE_MAP()


// CWinCESerialDlg message handlers

BOOL CWinCESerialDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 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
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
void CWinCESerialDlg::OnSize(UINT /*nType*/, int /*cx*/, int /*cy*/)
{
	if (AfxIsDRAEnabled())
	{
		DRA::RelayoutDialog(
			AfxGetResourceHandle(), 
			this->m_hWnd, 
			DRA::GetDisplayMode() != DRA::Portrait ? 
			MAKEINTRESOURCE(IDD_WINCESERIAL_DIALOG_WIDE) : 
			MAKEINTRESOURCE(IDD_WINCESERIAL_DIALOG));
	}
}
#endif

BOOL CWinCESerialDlg::InitCommTimeouts()
{
	COMMTIMEOUTS CommTimeouts;
	DWORD dwError;

	// 得到超时参数
	GetCommTimeouts(hPort, &CommTimeouts);

	// 改变COMMTIMEOUTS结构设置
	CommTimeouts.ReadIntervalTimeout = MAXDWORD; 
	CommTimeouts.ReadTotalTimeoutMultiplier = 0; 
	CommTimeouts.ReadTotalTimeoutConstant = 0; 
	CommTimeouts.WriteTotalTimeoutMultiplier = 10; 
	CommTimeouts.WriteTotalTimeoutConstant = 1000; 

	// 设置端口超时值 
	if (!SetCommTimeouts(hPort, &CommTimeouts))
	{
		// 不能设置超时值
		//MessageBox(NULL, TEXT("Unable to set the time-out parameters"), 
		//	TEXT("Error"), MB_OK);
		AfxMessageBox(TEXT("Unable to set the time-out parameters"), 
			MB_OK, MB_ICONERROR);
		dwError = GetLastError();
		return FALSE;
	}

	return TRUE;
} 

BOOL CWinCESerialDlg::InitDCB()
{
	DCB PortDCB;
	DWORD dwError;

	PortDCB.DCBlength = sizeof(DCB); 

	// 得到端口的默认设置信息
	GetCommState(hPort, &PortDCB);

	// 改变DCB结构设置
	PortDCB.BaudRate = 9600;                   // 波特率 
	PortDCB.fBinary = TRUE;                     // Win32不支持非二进制串行传输模式,必须为TRUE 
	PortDCB.fParity = TRUE;                     // 启用奇偶校验 
	PortDCB.fOutxCtsFlow = TRUE;                // 串行端口的输出由CTS线控制
	PortDCB.fOutxDsrFlow = FALSE;               // 关闭串行端口的DSR流控制 
	PortDCB.fDtrControl = DTR_CONTROL_ENABLE;   // 启用DTR线
	PortDCB.fDsrSensitivity = FALSE;            // 如果设为TRUE将忽略任何输入的字节,除非DSR线被启用 
	//PortDCB.fTXContinueOnXoff = TRUE;         // 当为TRUE时,如果接收缓冲区已满且驱动程序已
	// 传送XOFF字符,将使驱动程序停止传输字符

	PortDCB.fTXContinueOnXoff = FALSE;
	PortDCB.fOutX = FALSE;                      // 设为TRUE指定XON/XOFF控制被用于控制串行输出 
	PortDCB.fInX = FALSE;                       // 设为TRUE指定XON/XOFF控制被用于控制串行输入 
	PortDCB.fErrorChar = FALSE;                 // WINCE串行驱动程序的默认执行将忽略这个字段 
	PortDCB.fNull = FALSE;                      // 设为TRUE将使串行驱动程序忽略收到的空字节 
	PortDCB.fRtsControl = RTS_CONTROL_ENABLE;   // 启用RTS线 
	PortDCB.fAbortOnError = FALSE;              // WINCE串行驱动程序的默认执行将忽略这个字段
	PortDCB.ByteSize = 8;                       // 每字节的位数 
	PortDCB.Parity = NOPARITY;                  // 无奇偶校验 
	PortDCB.StopBits = ONESTOPBIT;              // 每字节一位停止位 

	// 根据DCB结构配置端口 
	if (!SetCommState(hPort, &PortDCB))
	{
		// 不能配置串行端口
		//MessageBox(NULL, TEXT("Unable to configure the serial port"), 
		//	TEXT("Error"), MB_OK);
		AfxMessageBox(TEXT("Unable to configure the serial port"), 
			MB_OK, MB_ICONERROR);
		dwError = GetLastError();
		return FALSE;
	}
	return TRUE;
}

BOOL CWinCESerialDlg::ClosePort(HANDLE hCommPort)
{
	if (hCommPort != INVALID_HANDLE_VALUE)
	{
		// 设置连接属性为FALSE
		m_bConnected = FALSE;

		// 结束线程中WaitCommEvent的等待
		SetCommMask(hPort, 0);

		// 阻塞至线程停止
		if (hReadThread)
		{
			TerminateThread(hReadThread, 0);
			CloseHandle(hReadThread);
		}

		// 清除端口上指定信号的状态
		EscapeCommFunction(hPort, CLRDTR);
		EscapeCommFunction(hPort, CLRRTS);

		// 清除驱动程序内部的发送和接收队列
		PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR);

		// 关闭串口
		CloseHandle(hCommPort);
		hCommPort = INVALID_HANDLE_VALUE;
		hPort = INVALID_HANDLE_VALUE;

		return TRUE;
	}
	else
	{
		return TRUE;
	}
}

DWORD CWinCESerialDlg::WritePort(TCHAR *buf, DWORD dwCharToWrite)
{
	BOOL fWriteState;
	DWORD dwBytesWritten;

	// 写入数据
	fWriteState = WriteFile(hPort, buf, dwCharToWrite * sizeof(TCHAR), 
		&dwBytesWritten, NULL);
	if (!fWriteState)
	{
		// 不能写数据
		//MessageBox(NULL, TEXT("Can't Write String to Comm"), 
		//	TEXT("Error"), MB_OK);
		AfxMessageBox(TEXT("Can't Write String to Comm"), 
			MB_OK, MB_ICONERROR);
		dwBytesWritten = 0;
	}

	return dwBytesWritten;
}

DWORD WINAPI ReadPortThread(LPVOID lpvoid)
{
	BOOL fReadState;
	DWORD dwCommModemStatus;
	DWORD dwLength;
	COMSTAT ComStat;
	DWORD dwErrorFlags;

	while (hPort != INVALID_HANDLE_VALUE) 
	{
		// 等待串口的事件发生
		WaitCommEvent(hPort, &dwCommModemStatus, 0);
		if (dwCommModemStatus & EV_RXCHAR) 
		{
			ClearCommError(hPort, &dwErrorFlags, &ComStat);
			// cbInQue返回在串行驱动程序输入队列中的字符数
			dwLength = ComStat.cbInQue;

			if (dwLength > 0)
			{
				// 从串口读取数据
				TCHAR *buf = new TCHAR[256];
				fReadState = ReadFile(hPort, buf, dwLength, &dwLength, NULL);
				if (!fReadState)
				{
					// 不能从串口读取数据
					MessageBox(NULL, TEXT("Error in read from serial port"), 
						TEXT("Read Error"), MB_OK);
				}
				else
				{
					// 把数据赋值给全局变量
					strInChar = buf;
					((CEdit *)lpvoid)->SetSel(-1, -1);      	// 自动滚屏
					((CEdit *)lpvoid)->ReplaceSel(strInChar);	// 自动换行

					TRACE(_T("read serial data = %s\n"), strInChar);
				}
				delete[] buf;
			} 
		}
		GetCommModemStatus(hPort, &dwCommModemStatus);
	}
	return 0;
}

BOOL CWinCESerialDlg::OpenPort(LPTSTR lpszPortName)
{
	DWORD dwError, dwThreadID;

	if (hPort != INVALID_HANDLE_VALUE)
	{
		return FALSE;
	}

	// 打开串口
	if (m_iport=0)
	{
		lpszPortName ==_T("COM1");
	}
	else lpszPortName ==_T("COM2");
	
	hPort = CreateFile(lpszPortName, GENERIC_READ | GENERIC_WRITE, 
		0, NULL, OPEN_EXISTING, 0, NULL);
	if (hPort == INVALID_HANDLE_VALUE) // 如果打开端口出错, 返回FALSE
	{
		// 不能打开端口
		CString strError;
		strError.Format(_T("Unable to open %s, Error No.=%d"), 
			lpszPortName, GetLastError());
		//MessageBox(NULL, strError, TEXT("Error"), MB_OK);
		AfxMessageBox(strError, MB_OK, MB_ICONERROR);
		return FALSE;
	}

	// 指定端口监测的事件集
	SetCommMask(hPort, EV_RXCHAR);

	// 分配设备缓冲区
	SetupComm(hPort, 512, 512);

	// 初始化缓冲区中的信息
	PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR);

	// 配置串行端口
	if (!InitDCB())
		return FALSE;

	// 设置端口超时值
	if (!InitCommTimeouts())
		return FALSE;

	// 设置端口上指定信号的状态
	// SETDTR: 发送DTR (data-terminal-ready)信号
	// SETRTS: 发送RTS (request-to-send)信号
	EscapeCommFunction(hPort, SETDTR);
	EscapeCommFunction(hPort, SETRTS);

	// 创建一个从串口读取数据的线程
	if (hReadThread = CreateThread(NULL, 0, ReadPortThread, m_ceReadSerial, 0, &dwThreadID))
	{
	}
	else
	{
		// 不能创建线程
		//MessageBox(NULL, TEXT("Unable to create the read thread"), 
		//	TEXT("Error"), MB_OK);
		AfxMessageBox(TEXT("Unable to create the read thread"), 
			MB_OK, MB_ICONERROR);
		dwError = GetLastError();
		return FALSE;
	}
	m_bConnected = TRUE;
	return TRUE;

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
	if (m_iport = 0 && hPort != INVALID_HANDLE_VALUE)
	{
		m_com1state == _T("ON");
		m_com2state == _T("OFF");

		if (m_iport == 1 && hPort != INVALID_HANDLE_VALUE)
		{
			m_com1state == _T("OFF");
			m_com2state == _T("ON");
		}
	else 
		m_com1state == _T("OFF");
		m_com2state == _T("OFF");
	}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

}


void CWinCESerialDlg::OnBnClickedButtonSerialOpen()
{
	// TODO: Add your control notification handler code here
	OpenPort(_T("COM1:"));
}

void CWinCESerialDlg::OnBnClickedButtonSerialWrite()
{
	// TODO: Add your control notification handler code here
		/*
		TCHAR tcBuf[64];
				int len = 0;
				
				wsprintf(tcBuf, _T("Test serial"));
				len = _tcslen(tcBuf);
				TRACE(_T("len = %d.\n"), len);
				
				WritePort(tcBuf, len);*/
	 
		CString strSend = _T(""); 
		m_ceSendserial.GetWindowText(strSend);  //m_SendDataEdit:Edit控件的CEdit对象 
		WritePort((LPTSTR)(LPCTSTR)strSend,strSend.GetLength());
}

void CWinCESerialDlg::OnBnClickedButtonSerialClose()
{
	// TODO: Add your control notification handler code here
	if (hPort != INVALID_HANDLE_VALUE)
		ClosePort(hPort);
}


void CWinCESerialDlg::OnBnClickedButtonCleanData()
{
	// TODO: Add your control notification handler code here
	//m_ceSendserial = _T("");
	//m_ceReadSerial = _T("");
	//UpdateData(false);

	m_ceSendserial.SetWindowText(_T("")); 
	m_ceReadSerial.SetWindowText(_T(""));
}

⌨️ 快捷键说明

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