S 串口编程 详解3 串口的初始化、打开/关闭

来源:互联网 发布:mac打开移动硬盘空白 编辑:程序博客网 时间:2024/05/19 13:30

串口编程 详解3  串口的初始化

程序打开串口,采用两种方法:

1、程序启动,调用OnInitDialog( )函数,打开串口,缺省串口号为COM1,如果COM1不存在或被占用,就给出提示(其实,我觉得在OnInitDialog( )函数中打开串口不大好)

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);//获得系统菜单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 dialogSetIcon(m_hIcon, TRUE);// Set big icon 程序显示时,左上角就会显示定义了的图标,生成的EXE程序也显示了这个图标SetIcon(m_hIcon, FALSE);// Set small icon在程序运行的时候,当用Alt+TAB时,会显示定义的这个图标,要不不显示// 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图标 为OFFm_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添加响应函数)

//打开/关闭串口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( )里边都是些什么。

//SerialPort.cpp
// 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: Killif (m_bThreadAlive){do{SetEvent(m_hShutdownEvent);} while (m_bThreadAlive);TRACE("Thread ended/n");}// create eventsif (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 objectsm_hEventArray[0] = m_hShutdownEvent; // highest prioritym_hEventArray[1] = m_ov.hEvent;m_hEventArray[2] = m_hWriteEvent;// initialize critical sectionInitializeCriticalSection(&m_csCommunicationSync);// set buffersize for writing and save the ownerm_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 itif (m_hComm != NULL){CloseHandle(m_hComm);m_hComm = NULL;}// prepare port stringssprintf(szPort, "COM%d", portnr);sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);// get a handle to the portm_hComm = CreateFile(szPort,      // communication port string (COMX)GENERIC_READ | GENERIC_WRITE, // read/write types0,        // comm devices must be opened with exclusive accessNULL,       // no security attributesOPEN_EXISTING,     // comm devices must use OPEN_EXISTINGFILE_FLAG_OVERLAPPED,   // Async I/O0);       // template must be 0 for comm devicesif (m_hComm == INVALID_HANDLE_VALUE){// port not founddelete [] szPort;delete [] szBaud;return FALSE;}// set the timeout valuesm_CommTimeouts.ReadIntervalTimeout = 1000;m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;m_CommTimeouts.ReadTotalTimeoutConstant = 1000;m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;m_CommTimeouts.WriteTotalTimeoutConstant = 1000;// configureif (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... continueelseProcessErrorMessage("SetCommState()");}elseProcessErrorMessage("BuildCommDCB()");}elseProcessErrorMessage("GetCommState()");}elseProcessErrorMessage("SetCommMask()");}elseProcessErrorMessage("SetCommTimeouts()");delete [] szPort;delete [] szBaud;// flush the portPurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);// release critical sectionLeaveCriticalSection(&m_csCommunicationSync);TRACE("Initialisation for communicationport %d completed./nUse Startmonitor to communicate./n", portnr);return TRUE;}
启动检测辅助线程m_Port.StartMonitoring();  
//SerialPort.cpp
// start comm watchingBOOL 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( ).该函数即将撤销时调用。
void CSCOMMDlg::OnDestroy() {CDialog::OnDestroy();m_ctrlAutoSend.SetCheck(0);//强行关闭自动发送KillTimer(1);KillTimer(4);m_Port.ClosePort();//关闭串口m_strReceiveData.Empty();//清空接收数据字符串}
其实,要是自己来说设计程序的话,可能就不会考虑到这么全面的(建立后得撤销)
从上面可以看到一个串口打开、撤销代码都有啊






                




原创粉丝点击