您的位置:首页 > 编程语言

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();//清空接收数据字符串

}

其实,要是自己来说设计程序的话,可能就不会考虑到这么全面的(建立后得撤销)
从上面可以看到一个串口打开、撤销代码都有啊
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: