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

本文详细介绍了串口编程中串口的初始化过程,包括串口的打开、配置和关闭等操作,并通过具体代码示例展示了如何使用C++进行串口编程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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

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

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

[cpp]  view plain copy
  1. BOOL CSCOMMDlg::OnInitDialog()  
  2. {  
  3.     CDialog::OnInitDialog();  
  4.     // Add "About..." menu item to system menu.  
  5.   
  6.     // IDM_ABOUTBOX must be in the system command range.  
  7.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
  8.     ASSERT(IDM_ABOUTBOX < 0xF000);  
  9.   
  10.     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>  
  11.     if (pSysMenu != NULL)  
  12.     {  
  13.         CString strAboutMenu;  
  14.         strAboutMenu.LoadString(IDS_ABOUTBOX);  
  15.         if (!strAboutMenu.IsEmpty())  
  16.         {  
  17.             pSysMenu->AppendMenu(MF_SEPARATOR);  
  18.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
  19.         }  
  20.     }  
  21.     // Set the icon for this dialog.  The framework does this automatically  
  22.     //  when the application's main window is not a dialog  
  23.     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>  
  24.     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>  
  25.     // TODO: Add extra initialization here  
  26.       
  27.     //下面初始化串口的 串口号  波特率  奇偶校验  数据位   停止位  
  28.     m_bOpenPort=FALSE;  
  29.     m_nCom=1;  
  30.     m_nBaud=115200;  
  31.     m_cParity='N';  
  32.     m_nDatabits=8;  
  33.     m_nStopbits=1;  
  34.     m_dwCommEvents=EV_RXCHAR||EV_RXFLAG;//串口事件  
  35.   
  36.     CString strStatus;  
  37.     if(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,512))//这句是串口的初始化 会在串口的打开和关闭中进行分析  
  38.     {  
  39.         m_Port.StartMonitoring();  //启动检测辅助线程  
  40.         m_ctrlIconOpenoff.SetIcon(m_hIconRed); //打开串口成功 设置ICON图标 为ON   
  41.         strStatus.Format("STATUS: COM %d OPENED, %d, %c, %d, %d",m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits);  
  42.         //当前的状态                  端口号     奇偶 数据位  停止位  
  43.         m_ctrlOpenPort.SetWindowText("关闭串口");  
  44.             m_bOpenPort=TRUE;  
  45.     }  
  46.     else  
  47.     {  
  48.         AfxMessageBox("没有发现该串口或 已被占用");  
  49.         m_ctrlIconOpenoff.SetIcon(m_hIconOff);  //打开串口失败 设置ICON图标 为OFF  
  50.         m_bOpenPort=FALSE;  
  51.     }  
  52.         m_ctrlPortStatus.SetWindowText(strStatus);  
  53.   
  54.         m_ctrlStopDisp.SetWindowText("停止显示");  
  55.           
  56.         //端口的初始化  
  57.         m_ctrlPort.SetCurSel(0);  
  58.         m_ctrlPort.GetWindowText(m_strPort);  
  59.         //波特率的初始化  
  60.         m_ctrlBaud.InsertString(0,_T("4800"));  
  61.         m_ctrlBaud.InsertString(1,_T("14400"));  
  62.         m_ctrlBaud.InsertString(2,_T("19200"));  
  63.         m_ctrlBaud.InsertString(3,_T("38400"));  
  64.         m_ctrlBaud.InsertString(4,_T("56000"));  
  65.         m_ctrlBaud.InsertString(5,_T("57600"));  
  66.         m_ctrlBaud.InsertString(6,_T("115200"));  
  67.     //  m_ctrlBaud.InsertString(7,_T("128000"));  
  68.     //  m_ctrlBaud.InsertString(8,_T("256000"));  
  69.         m_ctrlBaud.SetCurSel(6);  
  70.         m_ctrlBaud.GetWindowText(m_strBaud);  
  71.         //校验初始化  
  72.         m_ctrlPartity.SetCurSel(0);  
  73.         m_ctrlPartity.GetWindowText(m_strPartity);  
  74.         //数据位初始化  
  75.         m_ctrlDatabits.SetCurSel(0);  
  76.         m_ctrlDatabits.GetWindowText(m_strDatabits);  
  77.         //停止位  
  78.         m_ctrlStopbits.SetCurSel(0);  
  79.         m_ctrlStopbits.GetWindowText(m_strStopbits);  
  80.       
  81.     return TRUE;  // return TRUE  unless you set the focus to a control  
  82. }  

代码分析:

串口的打开:(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 plain copy
  1. //打开/关闭串口  
  2. void CSCOMMDlg::OnButtonOpenport()   
  3. {  
  4.     if(m_bOpenPort)//串口先是打开的,现在点击按钮进行关闭  
  5.     {  
  6.         if(m_ctrlAutoSend.GetCheck())  
  7.         {  
  8.             m_bOpenPort=!m_bOpenPort;  
  9.             AfxMessageBox("请先关掉自动发送");  
  10.             return;  
  11.         }  
  12.         m_ctrlOpenPort.SetWindowText("打开串口");  
  13.         m_Port.ClosePort();//关闭串口  
  14.         m_ctrlPortStatus.SetWindowText("STATUS: COM Port Close");  
  15.         m_ctrlIconOpenoff.SetIcon(m_hIconOff);  
  16.         m_bOpenPort=FALSE;  
  17.     }  
  18.     else//打开串口  
  19.     {  
  20.         m_ctrlOpenPort.SetWindowText("关闭串口");  
  21.         CString strStatus;  
  22.         //  BOOL  InitPort(CWnd* pPortOwner, UINT portnr = 1, UINT baud = 19200, \  
  23.         char parity = 'N'UINT databits = 8, UINT stopbits = 1, DWORD dwCommEvents = EV_RXCHAR, UINT writebuffersize = 1024);  
  24.         if(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,512))  
  25.         {  
  26.             m_Port.StartMonitoring();  
  27.             m_ctrlIconOpenoff.SetIcon(m_hIconRed);  
  28.             strStatus.Format("STATUS: COM %d OPENED, %d, %c, %d, %d",m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits);  
  29.             //当前的状态                 端口号     奇偶 数据位  停止位  
  30.                 m_bOpenPort=TRUE;  
  31.         }  
  32.         else  
  33.         {  
  34.             AfxMessageBox("没有发现该串口或 已被占用");  
  35.             m_ctrlIconOpenoff.SetIcon(m_hIconOff);  
  36.                 m_bOpenPort=FALSE;  
  37.         }  
  38.         m_ctrlPortStatus.SetWindowText(strStatus);  
  39.     }     
  40. }  

代码分析:现在我们得看InitPort( )里边都是些什么。

[cpp]  view plain copy
  1. <pre name="code" class="cpp">//SerialPort.cpp</pre>  
[cpp]  view plain copy
  1. // Initialize the port. This can be port 1 to 4.  
  2. BOOL CSerialPort::InitPort(CWnd* pPortOwner, // the owner (CWnd) of the port (receives message)  
  3.                            UINT  portnr,  // portnumber (1..4)  
  4.                            UINT  baud,   // baudrate  
  5.                            char  parity,  // parity   
  6.                            UINT  databits,  // databits   
  7.                            UINT  stopbits,  // stopbits   
  8.                            DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc  
  9.                            UINT  writebuffersize) // size to the writebuffer  
  10. {  
  11.     // assert(portnr > 0 && portnr < 5);  
  12.     assert(portnr > 0 && portnr < 20);  
  13.     assert(pPortOwner != NULL);  
  14.     // if the thread is alive: Kill  
  15.     if (m_bThreadAlive)  
  16.     {  
  17.         do  
  18.         {  
  19.             SetEvent(m_hShutdownEvent);  
  20.         } while (m_bThreadAlive);  
  21.         TRACE("Thread ended/n");  
  22.     }  
  23.     // create events  
  24.     if (m_ov.hEvent != NULL)  
  25.         ResetEvent(m_ov.hEvent);  
  26.     m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  
  27.     if (m_hWriteEvent != NULL)  
  28.         ResetEvent(m_hWriteEvent);  
  29.     m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  
  30.       
  31.     if (m_hShutdownEvent != NULL)  
  32.         ResetEvent(m_hShutdownEvent);  
  33.     m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  
  34.     // initialize the event objects  
  35.     m_hEventArray[0] = m_hShutdownEvent; // highest priority  
  36.     m_hEventArray[1] = m_ov.hEvent;  
  37.     m_hEventArray[2] = m_hWriteEvent;  
  38.     // initialize critical section  
  39.     InitializeCriticalSection(&m_csCommunicationSync);  
  40.       
  41.     // set buffersize for writing and save the owner  
  42.     m_pOwner = pPortOwner;  
  43.     if (m_szWriteBuffer != NULL)  
  44.         delete [] m_szWriteBuffer;  
  45.     m_szWriteBuffer = new char[writebuffersize];  
  46.     m_nPortNr = portnr;  
  47.     m_nWriteBufferSize = writebuffersize;  
  48.     m_dwCommEvents = dwCommEvents;  
  49.     BOOL bResult = FALSE;  
  50.     char *szPort = new char[50];  
  51.     char *szBaud = new char[50];  
  52.     // now it critical!  
  53.     EnterCriticalSection(&m_csCommunicationSync);  
  54.     // if the port is already opened: close it  
  55.     if (m_hComm != NULL)  
  56.     {  
  57.         CloseHandle(m_hComm);  
  58.         m_hComm = NULL;  
  59.     }  
  60.     // prepare port strings  
  61.     sprintf(szPort, "COM%d", portnr);  
  62.     sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);  
  63.     // get a handle to the port  
  64.     m_hComm = CreateFile(szPort,      // communication port string (COMX)  
  65.         GENERIC_READ | GENERIC_WRITE, // read/write types  
  66.         0,        // comm devices must be opened with exclusive access  
  67.         NULL,       // no security attributes  
  68.         OPEN_EXISTING,     // comm devices must use OPEN_EXISTING  
  69.         FILE_FLAG_OVERLAPPED,   // Async I/O  
  70.         0);       // template must be 0 for comm devices  
  71.     if (m_hComm == INVALID_HANDLE_VALUE)  
  72.     {  
  73.         // port not found  
  74.         delete [] szPort;  
  75.         delete [] szBaud;  
  76.         return FALSE;  
  77.     }  
  78.     // set the timeout values  
  79.     m_CommTimeouts.ReadIntervalTimeout = 1000;  
  80.     m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;  
  81.     m_CommTimeouts.ReadTotalTimeoutConstant = 1000;  
  82.     m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;  
  83.     m_CommTimeouts.WriteTotalTimeoutConstant = 1000;  
  84.     // configure  
  85.     if (SetCommTimeouts(m_hComm, &m_CommTimeouts))  
  86.     {           
  87.         if (SetCommMask(m_hComm, dwCommEvents))  
  88.         {  
  89.             if (GetCommState(m_hComm, &m_dcb))  
  90.             {  
  91.                 m_dcb.EvtChar = 'q';  
  92.                 m_dcb.fRtsControl = RTS_CONTROL_ENABLE;  // set RTS bit high!  
  93.                 if (BuildCommDCB(szBaud, &m_dcb))  
  94.                 {  
  95.                     if (SetCommState(m_hComm, &m_dcb))  
  96.                         ; // normal operation... continue  
  97.                     else  
  98.                         ProcessErrorMessage("SetCommState()");  
  99.                 }  
  100.                 else  
  101.                     ProcessErrorMessage("BuildCommDCB()");  
  102.             }  
  103.             else  
  104.                 ProcessErrorMessage("GetCommState()");  
  105.         }  
  106.         else  
  107.             ProcessErrorMessage("SetCommMask()");  
  108.     }  
  109.     else  
  110.         ProcessErrorMessage("SetCommTimeouts()");  
  111.     delete [] szPort;  
  112.     delete [] szBaud;  
  113.     // flush the port  
  114.     PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);  
  115.     // release critical section  
  116.     LeaveCriticalSection(&m_csCommunicationSync);  
  117.     TRACE("Initialisation for communicationport %d completed./nUse Startmonitor to communicate./n", portnr);  
  118.     return TRUE;  
  119. }  
启动检测辅助线程m_Port.StartMonitoring();  
[cpp]  view plain copy
  1. //SerialPort.cpp  
[cpp]  view plain copy
  1. // start comm watching  
  2. BOOL CSerialPort::StartMonitoring()  
  3. {  
  4.  if (!(m_Thread = AfxBeginThread(CommThread, this)))  
  5.   return FALSE;  
  6.  TRACE("Thread started/n");  
  7.  return TRUE;   
  8. }  
用户界面线程和工作者线程都是由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 plain copy
  1. void CSCOMMDlg::OnDestroy()   
  2. {  
  3.     CDialog::OnDestroy();  
  4.         m_ctrlAutoSend.SetCheck(0);//强行关闭自动发送  
  5.         KillTimer(1);  
  6.         KillTimer(4);  
  7.         m_Port.ClosePort();//关闭串口  
  8.         m_strReceiveData.Empty();//清空接收数据字符串  
  9. }  
其实,要是自己来说设计程序的话,可能就不会考虑到这么全面的(建立后得撤销)
从上面可以看到一个串口打开、撤销代码都有啊

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值