S 串口编程 详解3 串口的初始化、打开/关闭
2015-07-14 16:42
253 查看
串口编程 详解3 串口的初始化
程序打开串口,采用两种方法:
1、程序启动,调用OnInitDialog( )函数,打开串口,缺省串口号为COM1,如果COM1不存在或被占用,就给出提示(其实,我觉得在OnInitDialog( )函数中打开串口不大好)
[cpp] view
plaincopy
BOOL CSCOMMDlg::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);//<span style="background-color:rgb(255,255,255); color:rgb(51,51,51); font-family:arial,'courier new',courier,宋体,monospace; font-size:14px; line-height:24px; white-space:pre-wrap">获得系统菜单</span>
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 <span style="color:rgb(69,69,69); font-family:Tahoma,Helvetica,Arial,STHeiti; font-size:14px; line-height:21px">程序显示时,左上角就会显示定义了的图标,生成的EXE程序也显示了这个图标</span>
SetIcon(m_hIcon, FALSE); // Set small icon<span style="color:rgb(69,69,69); font-family:Tahoma,Helvetica,Arial,STHeiti; font-size:14px; line-height:21px">在程序运行的时候,当用Alt+TAB时,会显示定义的这个图标,要不不显示</span>
// TODO: Add extra initialization here
//下面初始化串口的 串口号 波特率 奇偶校验 数据位 停止位
m_bOpenPort=FALSE;
m_nCom=1;
m_nBaud=115200;
m_cParity='N';
m_nDatabits=8;
m_nStopbits=1;
m_dwCommEvents=EV_RXCHAR||EV_RXFLAG;//串口事件
CString strStatus;
if(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,512))//这句是串口的初始化 会在串口的打开和关闭中进行分析
{
m_Port.StartMonitoring(); //启动检测辅助线程
m_ctrlIconOpenoff.SetIcon(m_hIconRed); //打开串口成功 设置ICON图标 为ON
strStatus.Format("STATUS: COM %d OPENED, %d, %c, %d, %d",m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits);
//当前的状态 端口号 奇偶 数据位 停止位
m_ctrlOpenPort.SetWindowText("关闭串口");
m_bOpenPort=TRUE;
}
else
{
AfxMessageBox("没有发现该串口或 已被占用");
m_ctrlIconOpenoff.SetIcon(m_hIconOff); //打开串口失败 设置ICON图标 为OFF
m_bOpenPort=FALSE;
}
m_ctrlPortStatus.SetWindowText(strStatus);
m_ctrlStopDisp.SetWindowText("停止显示");
//端口的初始化
m_ctrlPort.SetCurSel(0);
m_ctrlPort.GetWindowText(m_strPort);
//波特率的初始化
m_ctrlBaud.InsertString(0,_T("4800"));
m_ctrlBaud.InsertString(1,_T("14400"));
m_ctrlBaud.InsertString(2,_T("19200"));
m_ctrlBaud.InsertString(3,_T("38400"));
m_ctrlBaud.InsertString(4,_T("56000"));
m_ctrlBaud.InsertString(5,_T("57600"));
m_ctrlBaud.InsertString(6,_T("115200"));
// m_ctrlBaud.InsertString(7,_T("128000"));
// m_ctrlBaud.InsertString(8,_T("256000"));
m_ctrlBaud.SetCurSel(6);
m_ctrlBaud.GetWindowText(m_strBaud);
//校验初始化
m_ctrlPartity.SetCurSel(0);
m_ctrlPartity.GetWindowText(m_strPartity);
//数据位初始化
m_ctrlDatabits.SetCurSel(0);
m_ctrlDatabits.GetWindowText(m_strDatabits);
//停止位
m_ctrlStopbits.SetCurSel(0);
m_ctrlStopbits.GetWindowText(m_strStopbits);
return TRUE; // return TRUE unless you set the focus to a control
}
代码分析:
串口的打开:(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,512)
以及m_Port.StartMonitoring(); //启动检测辅助线程
当然这里第一次用到ICON控件和COMBOX控件的知识
如: m_ctrlIconOpenoff.SetIcon(m_hIconRed);
m_ctrlBaud.InsertString(6,_T("115200"));
m_ctrlBaud.SetCurSel(6);
m_ctrlBaud.GetWindowText(m_strBaud); //获取当前控件框内的值到m_strBaud
2、打开/关闭串口(IDC_BUTTON_OPENPORT添加响应函数)
[cpp] view
plaincopy
//打开/关闭串口
void CSCOMMDlg::OnButtonOpenport()
{
if(m_bOpenPort)//串口先是打开的,现在点击按钮进行关闭
{
if(m_ctrlAutoSend.GetCheck())
{
m_bOpenPort=!m_bOpenPort;
AfxMessageBox("请先关掉自动发送");
return;
}
m_ctrlOpenPort.SetWindowText("打开串口");
m_Port.ClosePort();//关闭串口
m_ctrlPortStatus.SetWindowText("STATUS: COM Port Close");
m_ctrlIconOpenoff.SetIcon(m_hIconOff);
m_bOpenPort=FALSE;
}
else//打开串口
{
m_ctrlOpenPort.SetWindowText("关闭串口");
CString strStatus;
// BOOL InitPort(CWnd* pPortOwner, UINT portnr = 1, UINT baud = 19200, \
char parity = 'N', UINT databits = 8, UINT stopbits = 1, DWORD dwCommEvents = EV_RXCHAR, UINT writebuffersize = 1024);
if(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,512))
{
m_Port.StartMonitoring();
m_ctrlIconOpenoff.SetIcon(m_hIconRed);
strStatus.Format("STATUS: COM %d OPENED, %d, %c, %d, %d",m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits);
//当前的状态 端口号 奇偶 数据位 停止位
m_bOpenPort=TRUE;
}
else
{
AfxMessageBox("没有发现该串口或 已被占用");
m_ctrlIconOpenoff.SetIcon(m_hIconOff);
m_bOpenPort=FALSE;
}
m_ctrlPortStatus.SetWindowText(strStatus);
}
}
代码分析:现在我们得看InitPort( )里边都是些什么。
[cpp] view
plaincopy
<pre name="code" class="cpp">//SerialPort.cpp</pre>
[cpp] view
plaincopy
// Initialize the port. This can be port 1 to 4.
BOOL CSerialPort::InitPort(CWnd* pPortOwner, // the owner (CWnd) of the port (receives message)
UINT portnr, // portnumber (1..4)
UINT baud, // baudrate
char parity, // parity
UINT databits, // databits
UINT stopbits, // stopbits
DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc
UINT writebuffersize) // size to the writebuffer
{
// assert(portnr > 0 && portnr < 5);
assert(portnr > 0 && portnr < 20);
assert(pPortOwner != NULL);
// if the thread is alive: Kill
if (m_bThreadAlive)
{
do
{
SetEvent(m_hShutdownEvent);
} while (m_bThreadAlive);
TRACE("Thread ended/n");
}
// create events
if (m_ov.hEvent != NULL)
ResetEvent(m_ov.hEvent);
m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hWriteEvent != NULL)
ResetEvent(m_hWriteEvent);
m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hShutdownEvent != NULL)
ResetEvent(m_hShutdownEvent);
m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
// initialize the event objects
m_hEventArray[0] = m_hShutdownEvent; // highest priority
m_hEventArray[1] = m_ov.hEvent;
m_hEventArray[2] = m_hWriteEvent;
// initialize critical section
InitializeCriticalSection(&m_csCommunicationSync);
// set buffersize for writing and save the owner
m_pOwner = pPortOwner;
if (m_szWriteBuffer != NULL)
delete [] m_szWriteBuffer;
m_szWriteBuffer = new char[writebuffersize];
m_nPortNr = portnr;
m_nWriteBufferSize = writebuffersize;
m_dwCommEvents = dwCommEvents;
BOOL bResult = FALSE;
char *szPort = new char[50];
char *szBaud = new char[50];
// now it critical!
EnterCriticalSection(&m_csCommunicationSync);
// if the port is already opened: close it
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
m_hComm = NULL;
}
// prepare port strings
sprintf(szPort, "COM%d", portnr);
sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);
// get a handle to the port
m_hComm = CreateFile(szPort, // communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // Async I/O
0); // template must be 0 for comm devices
if (m_hComm == INVALID_HANDLE_VALUE)
{
// port not found
delete [] szPort;
delete [] szBaud;
return FALSE;
}
// set the timeout values
m_CommTimeouts.ReadIntervalTimeout = 1000;
m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;
m_CommTimeouts.ReadTotalTimeoutConstant = 1000;
m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;
m_CommTimeouts.WriteTotalTimeoutConstant = 1000;
// configure
if (SetCommTimeouts(m_hComm, &m_CommTimeouts))
{
if (SetCommMask(m_hComm, dwCommEvents))
{
if (GetCommState(m_hComm, &m_dcb))
{
m_dcb.EvtChar = 'q';
m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high!
if (BuildCommDCB(szBaud, &m_dcb))
{
if (SetCommState(m_hComm, &m_dcb))
; // normal operation... continue
else
ProcessErrorMessage("SetCommState()");
}
else
ProcessErrorMessage("BuildCommDCB()");
}
else
ProcessErrorMessage("GetCommState()");
}
else
ProcessErrorMessage("SetCommMask()");
}
else
ProcessErrorMessage("SetCommTimeouts()");
delete [] szPort;
delete [] szBaud;
// flush the port
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
// release critical section
LeaveCriticalSection(&m_csCommunicationSync);
TRACE("Initialisation for communicationport %d completed./nUse Startmonitor to communicate./n", portnr);
return TRUE;
}
启动检测辅助线程m_Port.StartMonitoring();
[cpp] view
plaincopy
//SerialPort.cpp
[cpp] view
plaincopy
// start comm watching
BOOL CSerialPort::StartMonitoring()
{
if (!(m_Thread = AfxBeginThread(CommThread, this)))
return FALSE;
TRACE("Thread started/n");
return TRUE;
}
用户界面线程和工作者线程都是由AfxBeginThread创建的。现在,考察该函数:MFC提供了两个重载版的AfxBeginThread.下面只说工作者线程工作者线程的AfxBeginThread的原型如下:
CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc,
LPVOID lParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);//用于创建工作者线程
返回值: 一个指向新线程的线程对象的指针
pfnThreadProc : 线程的入口函数,声明一定要如下: UINT MyThreadFunction(LPVOID pParam),不能设置为NULL;
pParam : 传递入线程的参数,注意它的类型为:LPVOID,所以我们可以传递一个结构体入线程.
程序关闭后要关闭串口并释放所占用的资源。在CSCOMMDlg添加WM_DISTROY消息响应函数OnDestroy( ).该函数即将撤销时调用。
[cpp] view
plaincopy
void CSCOMMDlg::OnDestroy()
{
CDialog::OnDestroy();
m_ctrlAutoSend.SetCheck(0);//强行关闭自动发送
KillTimer(1);
KillTimer(4);
m_Port.ClosePort();//关闭串口
m_strReceiveData.Empty();//清空接收数据字符串
}
其实,要是自己来说设计程序的话,可能就不会考虑到这么全面的(建立后得撤销)
从上面可以看到一个串口打开、撤销代码都有啊
程序打开串口,采用两种方法:
1、程序启动,调用OnInitDialog( )函数,打开串口,缺省串口号为COM1,如果COM1不存在或被占用,就给出提示(其实,我觉得在OnInitDialog( )函数中打开串口不大好)
[cpp] view
plaincopy
BOOL CSCOMMDlg::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);//<span style="background-color:rgb(255,255,255); color:rgb(51,51,51); font-family:arial,'courier new',courier,宋体,monospace; font-size:14px; line-height:24px; white-space:pre-wrap">获得系统菜单</span>
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 <span style="color:rgb(69,69,69); font-family:Tahoma,Helvetica,Arial,STHeiti; font-size:14px; line-height:21px">程序显示时,左上角就会显示定义了的图标,生成的EXE程序也显示了这个图标</span>
SetIcon(m_hIcon, FALSE); // Set small icon<span style="color:rgb(69,69,69); font-family:Tahoma,Helvetica,Arial,STHeiti; font-size:14px; line-height:21px">在程序运行的时候,当用Alt+TAB时,会显示定义的这个图标,要不不显示</span>
// TODO: Add extra initialization here
//下面初始化串口的 串口号 波特率 奇偶校验 数据位 停止位
m_bOpenPort=FALSE;
m_nCom=1;
m_nBaud=115200;
m_cParity='N';
m_nDatabits=8;
m_nStopbits=1;
m_dwCommEvents=EV_RXCHAR||EV_RXFLAG;//串口事件
CString strStatus;
if(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,512))//这句是串口的初始化 会在串口的打开和关闭中进行分析
{
m_Port.StartMonitoring(); //启动检测辅助线程
m_ctrlIconOpenoff.SetIcon(m_hIconRed); //打开串口成功 设置ICON图标 为ON
strStatus.Format("STATUS: COM %d OPENED, %d, %c, %d, %d",m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits);
//当前的状态 端口号 奇偶 数据位 停止位
m_ctrlOpenPort.SetWindowText("关闭串口");
m_bOpenPort=TRUE;
}
else
{
AfxMessageBox("没有发现该串口或 已被占用");
m_ctrlIconOpenoff.SetIcon(m_hIconOff); //打开串口失败 设置ICON图标 为OFF
m_bOpenPort=FALSE;
}
m_ctrlPortStatus.SetWindowText(strStatus);
m_ctrlStopDisp.SetWindowText("停止显示");
//端口的初始化
m_ctrlPort.SetCurSel(0);
m_ctrlPort.GetWindowText(m_strPort);
//波特率的初始化
m_ctrlBaud.InsertString(0,_T("4800"));
m_ctrlBaud.InsertString(1,_T("14400"));
m_ctrlBaud.InsertString(2,_T("19200"));
m_ctrlBaud.InsertString(3,_T("38400"));
m_ctrlBaud.InsertString(4,_T("56000"));
m_ctrlBaud.InsertString(5,_T("57600"));
m_ctrlBaud.InsertString(6,_T("115200"));
// m_ctrlBaud.InsertString(7,_T("128000"));
// m_ctrlBaud.InsertString(8,_T("256000"));
m_ctrlBaud.SetCurSel(6);
m_ctrlBaud.GetWindowText(m_strBaud);
//校验初始化
m_ctrlPartity.SetCurSel(0);
m_ctrlPartity.GetWindowText(m_strPartity);
//数据位初始化
m_ctrlDatabits.SetCurSel(0);
m_ctrlDatabits.GetWindowText(m_strDatabits);
//停止位
m_ctrlStopbits.SetCurSel(0);
m_ctrlStopbits.GetWindowText(m_strStopbits);
return TRUE; // return TRUE unless you set the focus to a control
}
代码分析:
串口的打开:(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,512)
以及m_Port.StartMonitoring(); //启动检测辅助线程
当然这里第一次用到ICON控件和COMBOX控件的知识
如: m_ctrlIconOpenoff.SetIcon(m_hIconRed);
m_ctrlBaud.InsertString(6,_T("115200"));
m_ctrlBaud.SetCurSel(6);
m_ctrlBaud.GetWindowText(m_strBaud); //获取当前控件框内的值到m_strBaud
2、打开/关闭串口(IDC_BUTTON_OPENPORT添加响应函数)
[cpp] view
plaincopy
//打开/关闭串口
void CSCOMMDlg::OnButtonOpenport()
{
if(m_bOpenPort)//串口先是打开的,现在点击按钮进行关闭
{
if(m_ctrlAutoSend.GetCheck())
{
m_bOpenPort=!m_bOpenPort;
AfxMessageBox("请先关掉自动发送");
return;
}
m_ctrlOpenPort.SetWindowText("打开串口");
m_Port.ClosePort();//关闭串口
m_ctrlPortStatus.SetWindowText("STATUS: COM Port Close");
m_ctrlIconOpenoff.SetIcon(m_hIconOff);
m_bOpenPort=FALSE;
}
else//打开串口
{
m_ctrlOpenPort.SetWindowText("关闭串口");
CString strStatus;
// BOOL InitPort(CWnd* pPortOwner, UINT portnr = 1, UINT baud = 19200, \
char parity = 'N', UINT databits = 8, UINT stopbits = 1, DWORD dwCommEvents = EV_RXCHAR, UINT writebuffersize = 1024);
if(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,512))
{
m_Port.StartMonitoring();
m_ctrlIconOpenoff.SetIcon(m_hIconRed);
strStatus.Format("STATUS: COM %d OPENED, %d, %c, %d, %d",m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits);
//当前的状态 端口号 奇偶 数据位 停止位
m_bOpenPort=TRUE;
}
else
{
AfxMessageBox("没有发现该串口或 已被占用");
m_ctrlIconOpenoff.SetIcon(m_hIconOff);
m_bOpenPort=FALSE;
}
m_ctrlPortStatus.SetWindowText(strStatus);
}
}
代码分析:现在我们得看InitPort( )里边都是些什么。
[cpp] view
plaincopy
<pre name="code" class="cpp">//SerialPort.cpp</pre>
[cpp] view
plaincopy
// Initialize the port. This can be port 1 to 4.
BOOL CSerialPort::InitPort(CWnd* pPortOwner, // the owner (CWnd) of the port (receives message)
UINT portnr, // portnumber (1..4)
UINT baud, // baudrate
char parity, // parity
UINT databits, // databits
UINT stopbits, // stopbits
DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc
UINT writebuffersize) // size to the writebuffer
{
// assert(portnr > 0 && portnr < 5);
assert(portnr > 0 && portnr < 20);
assert(pPortOwner != NULL);
// if the thread is alive: Kill
if (m_bThreadAlive)
{
do
{
SetEvent(m_hShutdownEvent);
} while (m_bThreadAlive);
TRACE("Thread ended/n");
}
// create events
if (m_ov.hEvent != NULL)
ResetEvent(m_ov.hEvent);
m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hWriteEvent != NULL)
ResetEvent(m_hWriteEvent);
m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hShutdownEvent != NULL)
ResetEvent(m_hShutdownEvent);
m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
// initialize the event objects
m_hEventArray[0] = m_hShutdownEvent; // highest priority
m_hEventArray[1] = m_ov.hEvent;
m_hEventArray[2] = m_hWriteEvent;
// initialize critical section
InitializeCriticalSection(&m_csCommunicationSync);
// set buffersize for writing and save the owner
m_pOwner = pPortOwner;
if (m_szWriteBuffer != NULL)
delete [] m_szWriteBuffer;
m_szWriteBuffer = new char[writebuffersize];
m_nPortNr = portnr;
m_nWriteBufferSize = writebuffersize;
m_dwCommEvents = dwCommEvents;
BOOL bResult = FALSE;
char *szPort = new char[50];
char *szBaud = new char[50];
// now it critical!
EnterCriticalSection(&m_csCommunicationSync);
// if the port is already opened: close it
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
m_hComm = NULL;
}
// prepare port strings
sprintf(szPort, "COM%d", portnr);
sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);
// get a handle to the port
m_hComm = CreateFile(szPort, // communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // Async I/O
0); // template must be 0 for comm devices
if (m_hComm == INVALID_HANDLE_VALUE)
{
// port not found
delete [] szPort;
delete [] szBaud;
return FALSE;
}
// set the timeout values
m_CommTimeouts.ReadIntervalTimeout = 1000;
m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;
m_CommTimeouts.ReadTotalTimeoutConstant = 1000;
m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;
m_CommTimeouts.WriteTotalTimeoutConstant = 1000;
// configure
if (SetCommTimeouts(m_hComm, &m_CommTimeouts))
{
if (SetCommMask(m_hComm, dwCommEvents))
{
if (GetCommState(m_hComm, &m_dcb))
{
m_dcb.EvtChar = 'q';
m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high!
if (BuildCommDCB(szBaud, &m_dcb))
{
if (SetCommState(m_hComm, &m_dcb))
; // normal operation... continue
else
ProcessErrorMessage("SetCommState()");
}
else
ProcessErrorMessage("BuildCommDCB()");
}
else
ProcessErrorMessage("GetCommState()");
}
else
ProcessErrorMessage("SetCommMask()");
}
else
ProcessErrorMessage("SetCommTimeouts()");
delete [] szPort;
delete [] szBaud;
// flush the port
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
// release critical section
LeaveCriticalSection(&m_csCommunicationSync);
TRACE("Initialisation for communicationport %d completed./nUse Startmonitor to communicate./n", portnr);
return TRUE;
}
启动检测辅助线程m_Port.StartMonitoring();
[cpp] view
plaincopy
//SerialPort.cpp
[cpp] view
plaincopy
// start comm watching
BOOL CSerialPort::StartMonitoring()
{
if (!(m_Thread = AfxBeginThread(CommThread, this)))
return FALSE;
TRACE("Thread started/n");
return TRUE;
}
用户界面线程和工作者线程都是由AfxBeginThread创建的。现在,考察该函数:MFC提供了两个重载版的AfxBeginThread.下面只说工作者线程工作者线程的AfxBeginThread的原型如下:
CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc,
LPVOID lParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);//用于创建工作者线程
返回值: 一个指向新线程的线程对象的指针
pfnThreadProc : 线程的入口函数,声明一定要如下: UINT MyThreadFunction(LPVOID pParam),不能设置为NULL;
pParam : 传递入线程的参数,注意它的类型为:LPVOID,所以我们可以传递一个结构体入线程.
程序关闭后要关闭串口并释放所占用的资源。在CSCOMMDlg添加WM_DISTROY消息响应函数OnDestroy( ).该函数即将撤销时调用。
[cpp] view
plaincopy
void CSCOMMDlg::OnDestroy()
{
CDialog::OnDestroy();
m_ctrlAutoSend.SetCheck(0);//强行关闭自动发送
KillTimer(1);
KillTimer(4);
m_Port.ClosePort();//关闭串口
m_strReceiveData.Empty();//清空接收数据字符串
}
其实,要是自己来说设计程序的话,可能就不会考虑到这么全面的(建立后得撤销)
从上面可以看到一个串口打开、撤销代码都有啊
相关文章推荐
- C/C++/Fortran混合编程浅谈------直接链接方式
- AP算法java实现
- python3入门之列表和元组
- Python之 sort和sorted
- 类加载器--java静态方法静态变量
- POI导出JavaWeb中的table到excel下载
- Python3入门之软件安装
- 获取安卓应用的版本号
- 为什么我的eclipse按住ctrl点布局文件只能到R.java文件?
- android+eclipse 真机调试
- C#调用百度地图API经验分享(三)
- Python入门
- python爬虫程序所需的工具整理
- Spring中IoC的入门实例
- 【VBS】使用Visual Studio调试VBS程序
- spring3.x/4.x 依赖包 详解
- 南通大学学生综合测评的流程及伪代码
- 为什么设计模式在C++社区没有Java社区流行?
- java重载跟重写的用法
- 【Java基础学习笔记】Java中Socket+Swing设计简单通信