• CH372 USB内置固件类的编写


        使用CH372 USB芯片进行USB数据通信时,CH372默认有2种模式,一种是内置固件模式,另外一种是外置固件模式。当设置CH372为内置固件模式时,上位机界面需要调用该USB芯片公司提供的dll,为了使用上的方便,本人将基本的收发数据的功能封装成类库,方便以后调用。

        该类库有两个文件,分别是CCH37x.cpp和CCH37x.h。

    CCH37x.h代码如下:

    1 /***************************************************
    2 *作 者:温子祺
    3 *联系方式:wenziqi@hotmail.com
    4 *说 明:CCH37x.cpp
    5 提供外部调用的函数
    6 Open(),Close(),
    7 EP1Send(),EP1Recv(),
    8 EP2Send(),EP2Recv(),
    9 EP1和EP2接收数据时通过消息来实现
    10 ***************************************************/
    11 #ifndef __CCH37X_H__
    12  #define __CCH37X_H__
    13  #pragma once
    14
    15 #include "CH375DLL.H" // CH372/CH375的动态链接库
    16  #pragma comment(lib,"CH375DLL") //隐式调用库文件
    17
    18
    19  #define USB_INSERT 1
    20  #define USB_DRAW 2
    21
    22  #define EP1_RX 1
    23 #define EP2_RX 2
    24
    25 class CCH37x
    26 {
    27 public:
    28
    29 CCH37x();
    30 virtual ~CCH37x();
    31
    32 BOOL Close(void);
    33 BOOL Open (CWnd *pPortOwner,
    34 ULONG ulIndex,
    35 UINT unEP1RecvSize,
    36 UINT unEP2RecvSize,
    37 UINT unWriteTimeouts,
    38 UINT unReadTimeouts,
    39 UINT unEP1RecvMsg,
    40 UINT unEP2RecvMsg,
    41 UINT unConnectMsg);
    42
    43 UINT EP1Send(UCHAR *pSendBytes,UINT unSendLen);//端点1:向USB发送数据
    44 UINT EP1Recv(UCHAR *pRecvBytes); //端点1:从USB接收数据
    45
    46 UINT EP2Send(UCHAR *pSendBytes,UINT unSendLen);//端点2:向USB发送数据
    47 UINT EP2Recv(UCHAR *pRecvBytes); //端点2:从USB接收数据
    48
    49
    50
    51 protected:
    52
    53 BOOL Ready(void)const; //USB是否已经打开
    54 BOOL SetTimeout(UINT unWriteTimeouts,
    55 UINT unReadTimeouts); //设置超时
    56
    57 void SetCurIndex(ULONG ulIndex); //设置当前索引号
    58 ULONG GetCurIndex(void) const; //获取当前索引号
    59
    60 BOOL CreateThreadAndEvent(void); //创建线程和事件
    61 static
    62 DWORD EP1RecvThread(LPVOID lpArg); //接收线程
    63 static
    64 DWORD EP2RecvThread(LPVOID lpArg); //接收线程
    65
    66 private:
    67
    68 CWnd * m_pOwner;
    69 BOOL m_bInit;
    70 ULONG m_ulIndex;
    71
    72 HANDLE m_hUsbEP1Down; //端点1下传设备打开句柄
    73 HANDLE m_hUsbEP1Up; //端点1上传设备打开句柄
    74 HANDLE m_hUsbEP2Down; //端点2下传设备打开句柄
    75 HANDLE m_hUsbEP2Up; //端点2上传设备打开句柄
    76 HANDLE m_hEP1RecvExitEvent;
    77 HANDLE m_hEP2RecvExitEvent;
    78
    79 UCHAR *m_szEP1RecvBuf;
    80 UINT m_unEP1RecvSize;
    81 UCHAR *m_szEP2RecvBuf;
    82 UINT m_unEP2RecvSize;
    83
    84 UINT m_unEP1RecvMsg;
    85 UINT m_unEP2RecvMsg;
    86
    87 UINT m_unEP1CurRecvLength;
    88 UINT m_unEP2CurRecvLength;
    89 };
    90
    91 #endif

    CCH37x.cpp代码如下:

    1 /***************************************************
    2 *作 者:温子祺
    3 *联系方式:wenziqi@hotmail.com
    4 *说 明:CCH37x.cpp
    5 提供外部调用的函数
    6 Open(),Close(),
    7 EP1Send(),EP1Recv(),
    8 EP2Send(),EP2Recv(),
    9 EP1和EP2接收数据时通过消息来实现
    10 ***************************************************/
    11 #include "StdAfx.h"
    12 #include "CCH37x.h"
    13 #include <assert.h> //使用断言
    14
    15 UINT g_unConnectMsg=0;
    16 CWnd *g_Wnd=NULL;
    17
    18
    19 /**************************************************************************************************
    20 ** 函数名称: CH375NOTIFYROUTINE
    21 ** 功能描述: 回调函数(检测USB插入与拔出)
    22 ** 输 入: iEventStatus-事件状态
    23 ** 输 出: 无
    24 ** 注 意: 设备事件通知回调程序,在此程序里不宜作过多的操作,主要是因为中断服务程序优先级高,
    25 不宜进行USB传输,通常只是发个消息或者置个全局变量通知主程序处理
    26 ***************************************************************************************************/
    27 VOID CALLBACK CH375NOTIFYROUTINE(ULONG iEventStatus)
    28 {
    29
    30 if(iEventStatus==CH375_DEVICE_ARRIVAL)//检测到设备插入事件
    31 {
    32
    33 ::SendMessage(g_Wnd->m_hWnd,g_unConnectMsg,(WPARAM)USB_INSERT,0);
    34 }
    35
    36 if (iEventStatus==CH375_DEVICE_REMOVE)
    37 {
    38 ::SendMessage(g_Wnd->m_hWnd,g_unConnectMsg,(WPARAM)USB_DRAW,0);
    39 }
    40
    41 }
    42
    43 CCH37x::CCH37x(void)
    44 {
    45 m_bInit =FALSE;
    46 m_ulIndex =0;
    47 m_hUsbEP1Down=INVALID_HANDLE_VALUE;
    48 m_hUsbEP1Up =INVALID_HANDLE_VALUE;
    49 m_hUsbEP2Down=INVALID_HANDLE_VALUE;
    50 m_hUsbEP2Up =INVALID_HANDLE_VALUE;
    51 m_hEP1RecvExitEvent=NULL;
    52 m_hEP2RecvExitEvent=NULL;
    53 m_szEP1RecvBuf=NULL;
    54 m_szEP2RecvBuf=NULL;
    55 m_pOwner=NULL;
    56 }
    57
    58 CCH37x::~CCH37x(void)
    59 {
    60 m_bInit =FALSE;
    61 m_ulIndex =0;
    62 m_hUsbEP1Down=INVALID_HANDLE_VALUE;
    63 m_hUsbEP1Up =INVALID_HANDLE_VALUE;
    64 m_hUsbEP2Down=INVALID_HANDLE_VALUE;
    65 m_hUsbEP2Up =INVALID_HANDLE_VALUE;
    66 m_hEP1RecvExitEvent=NULL;
    67 m_hEP2RecvExitEvent=NULL;
    68 m_szEP1RecvBuf=NULL;
    69 m_szEP2RecvBuf=NULL;
    70 m_pOwner=NULL;
    71
    72 }
    73
    74 BOOL CCH37x::Ready(void) const
    75 {
    76 return m_bInit;
    77 }
    78
    79
    80 BOOL CCH37x::Close(void)
    81 {
    82 ULONG ulindex=0;
    83
    84 ulindex=GetCurIndex();
    85
    86 m_bInit=FALSE;
    87
    88 if (m_hUsbEP2Up!= INVALID_HANDLE_VALUE)
    89 {
    90 CH375AbortRead(ulindex);
    91 }
    92
    93 if (m_hUsbEP2Down!= INVALID_HANDLE_VALUE)
    94 {
    95 CH375AbortWrite(ulindex);
    96
    97 }
    98
    99 if (m_hUsbEP1Up!= INVALID_HANDLE_VALUE)
    100 {
    101 CH375AbortInter(ulindex);
    102 }
    103
    104 if (m_hEP1RecvExitEvent)
    105 {
    106 SetEvent(m_hEP1RecvExitEvent); //退出线程
    107 Sleep(10);
    108 CloseHandle(m_hEP1RecvExitEvent);
    109 m_hEP1RecvExitEvent=NULL;
    110 }
    111
    112 if (m_hEP2RecvExitEvent)
    113 {
    114 SetEvent(m_hEP2RecvExitEvent); //退出线程
    115 Sleep(10);
    116 CloseHandle(m_hEP2RecvExitEvent);
    117 m_hEP2RecvExitEvent=NULL;
    118 }
    119
    120
    121 if (m_hUsbEP2Up!= INVALID_HANDLE_VALUE)
    122 {
    123
    124 CloseHandle(m_hUsbEP2Up);
    125 m_hUsbEP2Up=INVALID_HANDLE_VALUE;
    126 }
    127
    128 if (m_hUsbEP2Down!= INVALID_HANDLE_VALUE)
    129 {
    130
    131 CloseHandle(m_hUsbEP2Down);
    132 m_hUsbEP2Down=INVALID_HANDLE_VALUE;
    133 }
    134
    135 if (m_hUsbEP1Up!= INVALID_HANDLE_VALUE)
    136 {
    137
    138 CloseHandle(m_hUsbEP1Up);
    139 m_hUsbEP1Up=INVALID_HANDLE_VALUE;
    140 }
    141
    142 if (m_hUsbEP1Down!= INVALID_HANDLE_VALUE)
    143 {
    144 CloseHandle(m_hUsbEP1Down);
    145 m_hUsbEP1Down=INVALID_HANDLE_VALUE;
    146 }
    147
    148 if (m_szEP1RecvBuf)
    149 {
    150 delete []m_szEP1RecvBuf;
    151 m_szEP1RecvBuf=NULL;
    152 }
    153
    154 if (m_szEP2RecvBuf)
    155 {
    156 delete []m_szEP2RecvBuf;
    157 m_szEP2RecvBuf=NULL;
    158 }
    159
    160
    161
    162 if (m_pOwner)
    163 {
    164 m_pOwner=NULL;
    165 }
    166
    167 CH375CloseDevice(ulindex);//Dll有Bug
    168
    169
    170 return TRUE;
    171 }
    172
    173
    174 BOOL CCH37x::Open(CWnd *pPortOwner,
    175 ULONG ulIndex,
    176 UINT unEP1RecvSize,
    177 UINT unEP2RecvSize,
    178 UINT unWriteTimeouts,
    179 UINT unReadTimeouts,
    180 UINT unEP1RecvMsg,
    181 UINT unEP2RecvMsg,
    182 UINT unConnectMsg)
    183 {
    184 assert(NULL != pPortOwner);
    185
    186 g_Wnd=m_pOwner = pPortOwner;
    187
    188 if (Ready())
    189 {
    190 Close();
    191 }
    192
    193 if (!m_szEP1RecvBuf)
    194 {
    195 m_unEP1RecvSize=unEP1RecvSize;
    196 m_szEP1RecvBuf=new UCHAR[unEP1RecvSize];
    197 }
    198
    199 if (!m_szEP2RecvBuf)
    200 {
    201 m_unEP2RecvSize=unEP2RecvSize;
    202 m_szEP2RecvBuf=new UCHAR[unEP2RecvSize];
    203 }
    204
    205 HANDLE hUsbDev=NULL;
    206
    207 SetCurIndex(ulIndex);
    208
    209 hUsbDev=CH375OpenDevice(ulIndex);
    210
    211 if (hUsbDev==INVALID_HANDLE_VALUE)
    212 {
    213 return FALSE;
    214 }
    215
    216 CH375SetTimeout(ulIndex,unWriteTimeouts,unReadTimeouts);
    217
    218 WCHAR *wcdevName=new WCHAR[256];
    219
    220 MultiByteToWideChar(CP_ACP,
    221 0,
    222 (LPSTR)CH375GetDeviceName(ulIndex),
    223 256, //不能够用sizeof
    224 wcdevName,
    225 256);
    226
    227 m_hUsbEP1Up=CreateFile((LPCWSTR)&wcdevName[0], //打开USB端点1上传句柄
    228 GENERIC_READ | GENERIC_WRITE,
    229 FILE_SHARE_READ | FILE_SHARE_WRITE,
    230 NULL,
    231 OPEN_EXISTING,
    232 FILE_ATTRIBUTE_NORMAL,
    233 NULL);
    234
    235 m_hUsbEP1Down=CreateFile((LPCWSTR)&wcdevName[0], //打开USB端点2下传句柄
    236 GENERIC_READ | GENERIC_WRITE,
    237 FILE_SHARE_READ | FILE_SHARE_WRITE,
    238 NULL,
    239 OPEN_EXISTING,
    240 FILE_ATTRIBUTE_NORMAL,
    241 NULL);
    242
    243
    244
    245 m_hUsbEP2Up=CreateFile((LPCWSTR)&wcdevName[0], //打开USB端点2上传句柄
    246 GENERIC_READ | GENERIC_WRITE,
    247 FILE_SHARE_READ | FILE_SHARE_WRITE,
    248 NULL,
    249 OPEN_EXISTING,
    250 FILE_ATTRIBUTE_NORMAL,
    251 NULL);
    252
    253 m_hUsbEP2Down=CreateFile((LPCWSTR)&wcdevName[0], //打开USB端点2下传句柄
    254 GENERIC_READ | GENERIC_WRITE,
    255 FILE_SHARE_READ | FILE_SHARE_WRITE,
    256 NULL,
    257 OPEN_EXISTING,
    258 FILE_ATTRIBUTE_NORMAL,
    259 NULL);
    260
    261 delete []wcdevName;
    262
    263 if (INVALID_HANDLE_VALUE==m_hUsbEP1Up || INVALID_HANDLE_VALUE==m_hUsbEP1Down\
    264 ||INVALID_HANDLE_VALUE==m_hUsbEP2Up || INVALID_HANDLE_VALUE==m_hUsbEP2Down)
    265 {
    266 return FALSE;
    267 }
    268
    269 if (!CreateThreadAndEvent())
    270 {
    271 return FALSE;
    272 }
    273
    274 m_unEP1RecvMsg=unEP1RecvMsg;
    275 m_unEP2RecvMsg=unEP2RecvMsg;
    276
    277 g_unConnectMsg=unConnectMsg;
    278
    279 CH375SetDeviceNotify(ulIndex,NULL,CH375NOTIFYROUTINE);
    280
    281 m_bInit=TRUE;
    282
    283 return TRUE;
    284 }
    285
    286 UINT CCH37x::EP1Send(UCHAR *pSendBytes,UINT unSendLen)
    287 {
    288 if (!Ready())
    289 {
    290 return 0;
    291 }
    292
    293 if (NULL == pSendBytes || 0==unSendLen)
    294 {
    295 return 0;
    296 }
    297
    298 if (unSendLen>8)
    299 {
    300 unSendLen=8;
    301 }
    302
    303 if (!(CH375WriteAuxData((ULONG)m_hUsbEP1Down,pSendBytes,(PULONG)&unSendLen)))
    304 {
    305 return 0;
    306 }
    307
    308 return unSendLen;
    309 }
    310
    311 UINT CCH37x::EP2Send(UCHAR *pSendBytes,UINT unSendLen)
    312 {
    313 if (!Ready())
    314 {
    315 return 0;
    316 }
    317
    318 if (NULL == pSendBytes || 0==unSendLen)
    319 {
    320 return 0;
    321 }
    322
    323 if (!(CH375WriteData((ULONG)m_hUsbEP2Down,pSendBytes,(PULONG)&unSendLen)))
    324 {
    325 return 0;
    326 }
    327
    328 return unSendLen;
    329 }
    330
    331 BOOL CCH37x::CreateThreadAndEvent(void)
    332 {
    333 m_hEP1RecvExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* 创建串口接收线程退出事件*/
    334
    335 if (NULL==m_hEP1RecvExitEvent)
    336 {
    337 return FALSE;
    338 }
    339
    340 ResetEvent(m_hEP1RecvExitEvent); //设置线程没有退出
    341
    342 m_hEP2RecvExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* 创建串口接收线程退出事件*/
    343
    344 if (NULL==m_hEP2RecvExitEvent)
    345 {
    346 return FALSE;
    347 }
    348
    349 ResetEvent(m_hEP2RecvExitEvent);
    350
    351
    352 HANDLE hRecvThread=NULL;
    353 DWORD dwThreadID =0;
    354
    355 Sleep(2);
    356
    357 // 创建串口接收线程
    358 hRecvThread=CreateThread(0,
    359 0,
    360 (LPTHREAD_START_ROUTINE)EP1RecvThread,
    361 this,
    362 0,
    363 &dwThreadID);
    364
    365 if (NULL==hRecvThread)
    366 {
    367 return FALSE;
    368 }
    369
    370 // 创建串口接收线程
    371 hRecvThread=CreateThread(0,
    372 0,
    373 (LPTHREAD_START_ROUTINE)EP2RecvThread,
    374 this,
    375 0,
    376 &dwThreadID);
    377
    378 if (NULL==hRecvThread)
    379 {
    380 return FALSE;
    381 }
    382 CloseHandle(hRecvThread);
    383 hRecvThread=NULL;
    384
    385 return TRUE;
    386 }
    387 DWORD CCH37x::EP1RecvThread(LPVOID lpArg)
    388 {
    389 assert(NULL != lpArg);
    390
    391 CCH37x *pArg=(CCH37x *)lpArg;
    392
    393 assert(NULL != pArg);
    394
    395 ULONG len=0;
    396
    397
    398 UCHAR *szRecvBuf=new UCHAR[pArg->m_unEP1RecvSize];
    399
    400 while (1)
    401 {
    402 if (WaitForSingleObject(pArg->m_hEP1RecvExitEvent,0)==WAIT_OBJECT_0)
    403 {
    404 break; //线程退出
    405 }
    406
    407 if (pArg->Ready())
    408 {
    409 //memset(szRecvBuf,0,pArg->m_unEP1RecvSize);
    410
    411 len =pArg->m_unEP1RecvSize;
    412
    413 if (CH375ReadInter((ULONG)(pArg->m_hUsbEP1Up),&szRecvBuf[0],&len))//该函数是阻塞的
    414 {
    415 if (len && pArg->m_szEP1RecvBuf)
    416 {
    417 memset(pArg->m_szEP1RecvBuf,0,pArg->m_unEP1RecvSize);
    418 memcpy(pArg->m_szEP1RecvBuf,szRecvBuf,len);
    419 pArg->m_unEP1CurRecvLength=len;
    420
    421 ::SendMessage((pArg->m_pOwner)->m_hWnd,
    422 pArg->m_unEP1RecvMsg,
    423 (WPARAM)EP1_RX,
    424 0);
    425 }
    426
    427
    428 }
    429
    430 }
    431 }
    432
    433 delete []szRecvBuf;
    434
    435 Sleep(10); //让线程安全退出
    436
    437 return 0;
    438 }
    439
    440 DWORD CCH37x::EP2RecvThread(LPVOID lpArg)
    441 {
    442 assert(NULL != lpArg);
    443
    444 CCH37x *pArg=(CCH37x *)lpArg;
    445
    446 assert(NULL != pArg);
    447
    448 ULONG len=0;
    449
    450
    451 UCHAR *szRecvBuf=new UCHAR[pArg->m_unEP2RecvSize];
    452 UINT RxStat=0;
    453
    454 while (1)
    455 {
    456 if (WaitForSingleObject(pArg->m_hEP2RecvExitEvent,0)==WAIT_OBJECT_0)
    457 {
    458 break; //线程退出
    459 }
    460
    461 if (pArg->Ready())
    462 {
    463
    464 //memset(szRecvBuf,0,pArg->m_unEP2RecvSize);
    465
    466 len =pArg->m_unEP2RecvSize;
    467
    468 if (CH375ReadData((ULONG)(pArg->m_hUsbEP2Up),&szRecvBuf[0],&len))
    469 {
    470 if (len && pArg->m_szEP2RecvBuf)
    471 {
    472 memset(pArg->m_szEP2RecvBuf,0,pArg->m_unEP2RecvSize);
    473 memcpy(pArg->m_szEP2RecvBuf,szRecvBuf,len);
    474 RxStat|=EP2_RX;
    475 pArg->m_unEP2CurRecvLength=len;
    476
    477 ::SendMessage((pArg->m_pOwner)->m_hWnd,
    478 pArg->m_unEP2RecvMsg,
    479 (WPARAM)EP2_RX,
    480 0);
    481 }
    482
    483 }
    484
    485 }
    486
    487 Sleep(1);
    488
    489
    490 }
    491
    492 delete []szRecvBuf;
    493
    494 Sleep(10); //让线程安全退出
    495
    496 return 0;
    497 }
    498
    499 UINT CCH37x::EP1Recv(UCHAR *pRecvBytes)
    500 {
    501 if (!Ready())
    502 {
    503 return 0;
    504 }
    505
    506 memcpy(pRecvBytes,m_szEP1RecvBuf,m_unEP1RecvSize);
    507
    508 return m_unEP1CurRecvLength;
    509
    510 }
    511
    512 UINT CCH37x::EP2Recv(UCHAR *pRecvBytes)
    513 {
    514 if (!Ready())
    515 {
    516 return 0;
    517 }
    518
    519 memcpy(pRecvBytes,m_szEP2RecvBuf,m_unEP2RecvSize);
    520
    521 return m_unEP2CurRecvLength;
    522 }
    523
    524 void CCH37x::SetCurIndex(ULONG ulIndex)
    525 {
    526 m_ulIndex=ulIndex;
    527 }
    528
    529 ULONG CCH37x::GetCurIndex() const
    530 {
    531 return m_ulIndex;
    532 }
    533
  • 相关阅读:
    JUC高并发编程(三)之模拟接口压力测试
    JUC高并发编程(二)之多线程下载支付宝对账文件
    JUC高并发编程(一)之请求合并案例
    《Head First设计模式》读书笔记
    图文详解23种设计模式
    Laravel路由匹配
    深夜debug:一个不常遇到的HbuilderX自动化测试运行问题
    高德地图API中折线polyline不能跨越180度经度线的解决方案
    sublime配置java运行环境
    Docker技术入门
  • 原文地址:https://www.cnblogs.com/wenziqi/p/1769174.html
Copyright © 2020-2023  润新知