zoukankan      html  css  js  c++  java
  • 串口类的编写

    CSerial类只有2个文件,分别是CSerial.cpp和CSerial.h。

    CSerial.h内容如下:

    1 /***************************************************
    2 *作 者:温子祺
    3 *联系方式:wenziqi@hotmail.com
    4 *说 明:CSerial.h
    5 提供外部调用的函数
    6 Open(),Close(),Send()
    7 接收数据时通过消息来实现
    8 ***************************************************/
    9 #ifndef __CSERIAL_H__
    10  #define __CSERIAL_H__
    11  #pragma once
    12
    13  class CSerial
    14 {
    15  public:
    16 CSerial(void);
    17 virtual~CSerial(void);
    18
    19 BOOL Open(CWnd *pPortOwner,
    20 UINT portnr,
    21 UINT baud,
    22 UINT parity,
    23 UINT databits,
    24 UINT stopbits,
    25 UINT rxdmsg);
    26
    27 BOOL Close(void);
    28
    29 UINT Send(UCHAR *pbuf,UINT len);
    30
    31  protected:
    32
    33 BOOL Ready(void) const;
    34 BOOL CreateThreadAndEvent(void);
    35  static
    36 DWORD RecvThread(LPVOID lpArg);
    37
    38 private:
    39 CWnd * m_pOwner;
    40 BOOL m_bInit;
    41
    42 HANDLE m_hSerial;
    43 HANDLE m_hRecvEvent;
    44 HANDLE m_hRecvExitEvent;
    45
    46 UINT m_unRxdMsg;
    47 };
    48 #endif

    CSerial.cpp代码如下:

    1 /***************************************************
    2 *作 者:温子祺
    3 *联系方式:wenziqi@hotmail.com
    4 *说 明:CSerial.cpp
    5 提供外部调用的函数
    6 Open(),Close(),Send()
    7 接收数据时通过消息来实现
    8 ***************************************************/
    9 #include "StdAfx.h"
    10 #include "CSerial.h"
    11 #include <assert.h> //使用断言
    12
    13 CSerial::CSerial(void)
    14 {
    15 m_pOwner=NULL;
    16 m_bInit=FALSE;
    17 m_hRecvEvent=NULL;
    18 m_hRecvExitEvent=NULL;
    19 m_hSerial=NULL;
    20 m_bInit=FALSE;
    21 }
    22
    23 CSerial::~CSerial(void)
    24 {
    25 Close();
    26 }
    27
    28 BOOL CSerial::Ready(void)const
    29 {
    30 return m_bInit;
    31 }
    32
    33 BOOL CSerial::Close(void)
    34 {
    35
    36 if (m_hSerial)
    37 {
    38 CloseHandle(m_hSerial);
    39 m_hSerial=NULL;
    40 }
    41
    42 if (m_hRecvEvent)
    43 {
    44 CloseHandle(m_hRecvEvent);
    45 m_hRecvEvent=NULL;
    46 }
    47
    48 if (m_hRecvExitEvent)
    49 {
    50 SetEvent(m_hRecvExitEvent); //退出线程
    51 Sleep(10);
    52 CloseHandle(m_hRecvExitEvent);
    53 m_hRecvExitEvent=NULL;
    54 }
    55
    56 if (m_bInit)
    57 {
    58 m_bInit=FALSE;
    59 }
    60
    61 if (m_pOwner)
    62 {
    63 m_pOwner=NULL;
    64 }
    65
    66 return TRUE;
    67 }
    68
    69 BOOL CSerial::Open(CWnd *pPortOwner,
    70 UINT portnr,
    71 UINT baud,
    72 UINT parity,
    73 UINT databits,
    74 UINT stopbits,
    75 UINT rxdmsg)
    76 {
    77 assert(NULL != pPortOwner);
    78
    79 m_pOwner = pPortOwner;
    80
    81 if (Ready())
    82 {
    83 Close();
    84 }
    85
    86 COMMTIMEOUTS CommTimeOuts;
    87 DCB dcb;
    88
    89 LPSTR sz= new CHAR[64];
    90 LPWSTR wsz= new WCHAR[64];
    91
    92 // 打开串口
    93 //wprintf_s(wsz,64,"COM%d",portnr);//用wprintf无效
    94 sprintf_s(sz,64,"COM%d",portnr);
    95 MultiByteToWideChar(CP_ACP,
    96 0,
    97 sz,
    98 64,
    99 wsz,
    100 64);
    101
    102 m_hSerial = CreateFile(wsz,
    103 GENERIC_READ | GENERIC_WRITE,
    104 0,
    105 0,
    106 OPEN_EXISTING,
    107 0,
    108 0);
    109
    110 delete []sz;
    111 delete []wsz;
    112
    113 if(m_hSerial == INVALID_HANDLE_VALUE)
    114 {
    115 return FALSE;
    116 }
    117
    118 GetCommState(m_hSerial, &dcb); /* 读取串口的DCB */
    119 dcb.BaudRate = baud; //波特率
    120 dcb.ByteSize = databits; //数据位
    121 dcb.Parity = parity; //校验位
    122 dcb.StopBits = stopbits; //停止位
    123
    124 dcb.fParity = FALSE; /* 禁止奇偶校验 */
    125 dcb.fBinary = TRUE;
    126 dcb.fDtrControl = 0; /* 禁止流量控制 */
    127 dcb.fRtsControl = 0;
    128 dcb.fOutX = 0;
    129 dcb.fInX = 0;
    130 dcb.fTXContinueOnXoff = 0;
    131 dcb.EvtChar='q'; // 这个一定要,否则大于127的数值会接收不了啊
    132
    133 //设置状态参数
    134 SetCommMask(m_hSerial, EV_RXFLAG|EV_RXCHAR); /* 串口事件:接收到一个字符 */
    135 SetupComm(m_hSerial, 1024, 1024); /* 设置接收与发送的缓冲区大小 */
    136
    137 if(!SetCommState(m_hSerial, &dcb)) /* 设置串口的DCB */
    138 {
    139 return FALSE;
    140 }
    141
    142 //设置超时参数
    143 GetCommTimeouts(m_hSerial, &CommTimeOuts);
    144 CommTimeOuts.ReadIntervalTimeout = 100; /* 接收字符间最大时间间隔 */
    145 CommTimeOuts.ReadTotalTimeoutMultiplier = 1;
    146 CommTimeOuts.ReadTotalTimeoutConstant = 100; /* 读数据总超时常量 */
    147 CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
    148 CommTimeOuts.WriteTotalTimeoutConstant = 0;
    149
    150 if(!SetCommTimeouts(m_hSerial, &CommTimeOuts))
    151 {
    152 return FALSE;
    153 }
    154
    155 PurgeComm(m_hSerial, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); /* 清除收/发缓冲区 */
    156
    157 if (!CreateThreadAndEvent())
    158 {
    159 return FALSE;
    160 }
    161
    162 m_unRxdMsg=rxdmsg;
    163
    164 m_bInit = TRUE;
    165
    166 return TRUE;
    167 }
    168 BOOL CSerial::CreateThreadAndEvent(void)
    169 {
    170 m_hRecvExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* 创建串口接收线程退出事件*/
    171
    172 if (NULL==m_hRecvExitEvent)
    173 {
    174 return FALSE;
    175 }
    176
    177 ResetEvent(m_hRecvExitEvent); //设置线程没有退出
    178
    179 HANDLE hRecvThread=NULL;
    180 DWORD dwThreadID =0;
    181
    182 // 创建串口接收线程
    183 hRecvThread=CreateThread(0,
    184 0,
    185 (LPTHREAD_START_ROUTINE)RecvThread,
    186 this,
    187 0,
    188 &dwThreadID);
    189
    190 if (NULL==hRecvThread)
    191 {
    192 return FALSE;
    193 }
    194
    195 CloseHandle(hRecvThread);
    196 hRecvThread=NULL;
    197
    198 return TRUE;
    199 }
    200
    201 UINT CSerial::Send(UCHAR *pbuf,UINT len)
    202 {
    203 if (!Ready())
    204 {
    205 //AfxMessageBox(_T("请确保串口已正常打开"));
    206 return 0;
    207 }
    208
    209 BOOL rt=FALSE;
    210
    211 DWORD dwBytesSend=0,dwCnt=0;
    212
    213 while (len>dwCnt)
    214 {
    215 rt=WriteFile(m_hSerial,pbuf+dwCnt,len-dwCnt,&dwBytesSend,NULL);
    216
    217 if (!rt)
    218 {
    219 return FALSE;
    220 }
    221
    222 dwCnt+=dwBytesSend;
    223
    224 if (len > dwCnt)
    225 {
    226 Sleep(100); //有可能I/O挂起
    227 }
    228 }
    229
    230 return (UINT)dwCnt;
    231 }
    232
    233 DWORD CSerial::RecvThread(LPVOID lpArg)
    234 {
    235
    236 assert(NULL != lpArg);
    237
    238 CSerial *pArg=(CSerial *)lpArg;
    239
    240 assert(NULL != pArg);
    241
    242 DWORD dwBytesRecv=0;
    243 DWORD dwError=0;
    244 UCHAR ucDat=0;
    245 COMSTAT ComStat;
    246
    247 memset(&ComStat,0,sizeof(ComStat));
    248
    249 while (1)
    250 {
    251 if (WaitForSingleObject(pArg->m_hRecvExitEvent,0)==WAIT_OBJECT_0)
    252 {
    253 break; //线程退出
    254 }
    255
    256 if (pArg->Ready())
    257 {
    258 ClearCommError(pArg->m_hSerial,&dwError,&ComStat);
    259
    260 if (0 == ComStat.cbInQue)
    261 {
    262 Sleep(1);
    263 continue;
    264 }
    265
    266 if (ReadFile(pArg->m_hSerial,&ucDat,1,&dwBytesRecv,NULL))
    267 {
    268 if (dwBytesRecv)
    269 {
    270 ::SendMessage((pArg->m_pOwner)->m_hWnd,
    271 pArg->m_unRxdMsg,
    272 (WPARAM)ucDat,
    273 NULL);
    274 }
    275 }
    276 }
    277
    278 Sleep(1);
    279
    280 }
    281
    282 Sleep(10); //让线程安全退出
    283
    284 return 0;
    285 }
    286
  • 相关阅读:
    应用监控CAT之cat-client源码阅读(一)
    java中this的N种使用方法
    微软职位内部推荐-Software Engineer II
    微软职位内部推荐-Software Engineer II
    微软职位内部推荐-Software Engineer II
    微软职位内部推荐-Senior Software Engineer
    微软职位内部推荐-Software Engineer II
    微软职位内部推荐-Senior Software Engineer
    微软职位内部推荐-Software Engineer II
    微软职位内部推荐-Software Engineer II
  • 原文地址:https://www.cnblogs.com/wenziqi/p/1769156.html
Copyright © 2011-2022 走看看