705浏览
查看: 705|回复: 0

[进阶] CH32V305 模拟 Ch372的例子

[复制链接]
前面介绍过如何使用Arduino 环境进行Ch32V305 的开发,这次带来的是一个CH32V305 Arduino 实现模拟Ch372的例子,参考的是Ch32v307EVT 中的HSDevice的代码。根据Exam中的CH32V30x_List.txt描述,这个CH372例子是模拟自定义USB设备(CH372设备),端点13下传,24上传,端点1下传的数据从端点3上传,不取反,端点2下传的数据从端点4上传,取反。但是,应该是描述存在错误,实际代码不是这样。
首先,改造代码,然后烧写到板子上。使用USBView 查看,端点1 有一个 OUT IN; 端点3OUT,端点4 IN, 端点5OUT, 端点6IN.

  1.           ===>Endpoint Descriptor<===
  2. bLength:                           0x07
  3. bDescriptorType:                   0x05
  4. bEndpointAddress:                  0x01  -> Direction: OUT - EndpointID: 1
  5. bmAttributes:                      0x02  -> Bulk Transfer Type
  6. wMaxPacketSize:                  0x0200 = 0x200 max bytes
  7. bInterval:                         0x00
  8.           ===>Endpoint Descriptor<===
  9. bLength:                           0x07
  10. bDescriptorType:                   0x05
  11. bEndpointAddress:                  0x81  -> Direction: IN - EndpointID: 1
  12. bmAttributes:                      0x02  -> Bulk Transfer Type
  13. wMaxPacketSize:                  0x0200 = 0x200 max bytes
  14. bInterval:                         0x00
  15.           ===>Endpoint Descriptor<===
  16. bLength:                           0x07
  17. bDescriptorType:                   0x05
  18. bEndpointAddress:                  0x03  -> Direction: OUT - EndpointID: 3
  19. bmAttributes:                      0x02  -> Bulk Transfer Type
  20. wMaxPacketSize:                  0x0200 = 0x200 max bytes
  21. bInterval:                         0x00
  22.           ===>Endpoint Descriptor<===
  23. bLength:                           0x07
  24. bDescriptorType:                   0x05
  25. bEndpointAddress:                  0x84  -> Direction: IN - EndpointID: 4
  26. bmAttributes:                      0x02  -> Bulk Transfer Type
  27. wMaxPacketSize:                  0x0200 = 0x200 max bytes
  28. bInterval:                         0x00
  29.           ===>Endpoint Descriptor<===
  30. bLength:                           0x07
  31. bDescriptorType:                   0x05
  32. bEndpointAddress:                  0x05  -> Direction: OUT - EndpointID: 5
  33. bmAttributes:                      0x02  -> Bulk Transfer Type
  34. wMaxPacketSize:                  0x0200 = 0x200 max bytes
  35. bInterval:                         0x00
  36.           ===>Endpoint Descriptor<===
  37. bLength:                           0x07
  38. bDescriptorType:                   0x05
  39. bEndpointAddress:                  0x86  -> Direction: IN - EndpointID: 6
  40. bmAttributes:                      0x02  -> Bulk Transfer Type
  41. wMaxPacketSize:                  0x0200 = 0x200 max bytes
  42. bInterval:                         0x00
复制代码
对应处理的代码在 ch32v30x_usbhs_device.c 文件中。下面对代码进行研读。

代码中Ch32端点1 OUT 收到的数据直接放到端点1IN中。

  1.                     /* end-point 1 data out interrupt */
  2.                     case USBHS_UIS_TOKEN_OUT | DEF_UEP1:
  3.                         if ( intst & USBHS_UIS_TOG_OK )
  4.                         {
  5.                             /* Write In Buffer */
  6.                             USBHSD->UEP1_RX_CTRL ^= USBHS_UEP_R_TOG_DATA1;
  7.                             RingBuffer_Comm.PackLen[RingBuffer_Comm.LoadPtr] = USBHSD->RX_LEN;
  8.                             RingBuffer_Comm.LoadPtr ++;
  9.                             if(RingBuffer_Comm.LoadPtr == DEF_Ring_Buffer_Max_Blks)
  10.                             {
  11.                                 RingBuffer_Comm.LoadPtr = 0;
  12.                             }
  13.                             USBHSD->UEP1_RX_DMA = (uint32_t)(&Data_Buffer[(RingBuffer_Comm.LoadPtr) * DEF_USBD_HS_PACK_SIZE]);
  14.                             RingBuffer_Comm.RemainPack ++;
  15.                             if(RingBuffer_Comm.RemainPack >= DEF_Ring_Buffer_Max_Blks-DEF_RING_BUFFER_REMINE)
  16.                             {
  17.                                 USBHSD->UEP1_RX_CTRL = ((USBHSD->UEP1_RX_CTRL) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK;
  18.                                 RingBuffer_Comm.StopFlag = 1;
  19.                             }
  20.                         }
  21.                         break;
复制代码

端点3收到的数据取反后放到端点4上。

  1.                   /* end-point 3 data out interrupt */
  2.                     case USBHS_UIS_TOKEN_OUT | DEF_UEP3:
  3.                         if ( intst & USBHS_UIS_TOG_OK )
  4.                         {
  5.                             len = (uint16_t)(USBHSD->RX_LEN);
  6.                             USBHSD->UEP3_RX_CTRL ^= USBHS_UEP_R_TOG_DATA1;
  7.                             USBHSD->UEP3_RX_CTRL = ((USBHSD->UEP3_RX_CTRL) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK;
  8.                             for(i=0; i<len; i++)
  9.                             {
  10.                                 USBHS_EP4_Tx_Buf[i] = ~USBHS_EP3_Rx_Buf[i];
  11.                             }
  12.                             USBHSD->UEP4_TX_LEN = len;
  13.                             USBHSD->UEP4_TX_CTRL = (USBHSD->UEP4_TX_CTRL & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_ACK;
  14.                         }
  15.                         break;
复制代码
类似的端点5收到的数据取反,通过端点6上传
  1.                     /* end-point 5 data out interrupt */
  2.                     case USBHS_UIS_TOKEN_OUT | DEF_UEP5:
  3.                         if ( intst & USBHS_UIS_TOG_OK )
  4.                         {
  5.                             len = (uint16_t)(USBHSD->RX_LEN);
  6.                             USBHSD->UEP5_RX_CTRL ^= USBHS_UEP_R_TOG_DATA1;
  7.                             USBHSD->UEP5_RX_CTRL = ((USBHSD->UEP5_RX_CTRL) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK;
  8.                             for(i=0; i<len; i++)
  9.                             {
  10.                                 USBHS_EP6_Tx_Buf[i] = ~USBHS_EP5_Rx_Buf[i];
  11.                             }
  12.                             USBHSD->UEP6_TX_LEN = len;
  13.                             USBHSD->UEP6_TX_CTRL = (USBHSD->UEP6_TX_CTRL & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_ACK;
  14.                         }
  15.                         break;
复制代码


从代码上可以看出,Exam中的描述是存在一些问题的。
之后,再编写一个VC代码,进行速度测试:

CH32V305 模拟 Ch372的例子图1

代码来自Ch569 EVT  Package, 有部分修改:

  1. // 2003.09.08, 2003.12.28
  2. //****************************************
  3. //**  Copyright  (C)  W.ch  1999-2005   **
  4. //**  Web:  http://www.winchiphead.com  **
  5. //****************************************
  6. //**  DLL for USB interface chip CH375  **
  7. //**  C, VC5.0                          **
  8. //****************************************
  9. //
  10. // USB总线接口芯片CH375的数据块测试程序 V1.0
  11. // 南京沁恒电子有限公司  作者: W.ch 2003.12
  12. // CH375-BLK  V1.0
  13. // 运行环境: Windows 98/ME, Windows 2000/XP
  14. // support USB chip: CH372/CH375
  15. //
  16. #include        <windows.h>
  17. #include        <stdlib.h>
  18. #include        <stdio.h>
  19. #include        <conio.h>
  20. #include        <winioctl.h>
  21. #include        "CH375DLL.H"                       
  22. #pragma comment(lib,"CH375DLL")
  23. #define                TEST_DATA_LEN                4096
  24. #define                TEST_NUM                     1000
  25. unsigned char        mReadBuf[TEST_DATA_LEN];
  26. unsigned char        mWriteBuf[TEST_DATA_LEN];
  27. //程序入口
  28. void main (int argc,char **argv )
  29. {
  30.         unsigned long mLength, mTestCount, mErrCnt,mArg,mFirstTick,mLastTick;
  31.         long long mTotal=0;
  32.         double          speed;
  33.         USHORT          mCount = 0;
  34.         printf( "\nCH372/CH375 Bulk Data Test Program V1.1 ,   Copyright (C) W.ch 2004.12\n" );
  35.         printf( "test data correctness \n" );
  36.         mArg = TEST_DATA_LEN;
  37. // 需要使用DLL则需要先加载,没有此句则会自动加载
  38.         printf( "*** CH375OpenDevice: 0# \n" );
  39.         if ( CH375OpenDevice( 0 ) == INVALID_HANDLE_VALUE ) return;  /* 使用之前必须打开设备 */
  40.         memset(mWriteBuf, 0xFF, sizeof(mWriteBuf));
  41.        
  42.         mErrCnt=0;
  43.         printf( "*** CH375ReadData: 1000 times 4M Byte ***\n" );
  44.         mTotal = 0.0;
  45.         for ( mTestCount=0; mTestCount < TEST_NUM; ++mTestCount )  // 循环测试
  46.         {
  47.                 if(mTestCount == 0)
  48.                 {
  49.                         mFirstTick=GetTickCount();
  50.                 }
  51.                 mLength = mArg;
  52.                 if (CH375WriteEndP(0, 1, mWriteBuf, &mLength))  // 写入成功
  53.                 {
  54.                         mTotal += mLength;
  55.                         if (mLength == 0)
  56.                         {
  57.                                 Sleep(0);  //放弃当前线程的时间片,防止CPU出现100%情况
  58.                         }
  59.                 }
  60.                 else
  61.                 {  // 写操作失败
  62.                         printf("S1-T%0ld-C%ld CH375WriteEndP return error, length=%d\n", mTestCount, mTestCount, mTotal);
  63.                 }
  64.                 mLength = mArg;
  65.                 if (CH375ReadEndP(0, 1, mReadBuf, &mLength))  // 接收成功
  66.                 {
  67.                         mTotal += mLength;
  68.                         if(mLength == 0 )
  69.                         {
  70.                                 Sleep(0);  //放弃当前线程的时间片,防止CPU出现100%情况
  71.                         }
  72.                 }
  73.                 else
  74.                 {
  75.                        
  76.                         printf( "S1-T%0ld-C%ld CH375ReadData return error, length=%d\n", mTestCount, mTestCount, mTotal );
  77.                 }
  78.                
  79.         }
  80.        
  81.         mLastTick =GetTickCount();
  82.         mLastTick = mLastTick - mFirstTick;
  83.         speed=1000;
  84.         speed=speed*mTotal/mLastTick;
  85.         printf( "*** average speed = %7.1f MBytes/Sec, total=%lld bytes\n", speed/1000/1000, mTotal);
  86.        
  87.         CH375CloseDevice( 0 );
  88.         printf( "\nExit.\n" );
  89.         _getch();
  90.        
  91. }
复制代码

完整的源代码和可执行 EXE, 建议有需要的朋友重新编译。

对应的 Arduino代码,看着是不是非常简单?

  1. #include "src\\userUsbCh372\\ch32v30x_usbhs_device.h"
  2. void setup() {
  3.   Serial.begin(115200);
  4.   Serial.println("Start");
  5.   /* Initialize system configuration */
  6.   SystemCoreClockUpdate( );
  7.   NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2 );
  8.   Delay_Init( );
  9.   /* Initialize USBHS interface to communicate with the host  */
  10.   USBHS_RCC_Init( );
  11.   USBHS_Device_Init( ENABLE );
  12. }
  13. uint8_t ret;
  14. void loop() {
  15.         /* Determine if enumeration is complete, perform data transfer if completed */
  16.         if(USBHS_DevEnumStatus)
  17.         {
  18.             /* Data Transfer */
  19.             if(RingBuffer_Comm.RemainPack)
  20.             {
  21.                 ret = USBHS_Endp_DataUp(DEF_UEP1, &Data_Buffer[(RingBuffer_Comm.DealPtr) * DEF_USBD_HS_PACK_SIZE], RingBuffer_Comm.PackLen[RingBuffer_Comm.DealPtr], DEF_UEP_DMA_LOAD);
  22.                 if(ret == 0)
  23.                 {
  24.                     NVIC_DisableIRQ(USBHS_IRQn);
  25.                     RingBuffer_Comm.RemainPack--;
  26.                     RingBuffer_Comm.DealPtr++;
  27.                     if(RingBuffer_Comm.DealPtr == DEF_Ring_Buffer_Max_Blks)
  28.                     {
  29.                         RingBuffer_Comm.DealPtr = 0;
  30.                     }
  31.                     NVIC_EnableIRQ(USBHS_IRQn);
  32.                 }
  33.             }
  34.             /* Monitor whether the remaining space is available for further downloads */
  35.             if(RingBuffer_Comm.RemainPack < (DEF_Ring_Buffer_Max_Blks - DEF_RING_BUFFER_RESTART))
  36.             {
  37.                 if(RingBuffer_Comm.StopFlag)
  38.                 {
  39.                     RingBuffer_Comm.StopFlag = 0;
  40.                     USBHSD->UEP1_RX_CTRL = (USBHSD->UEP1_RX_CTRL & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_ACK;
  41.                 }
  42.             }
  43.         }
  44. }
复制代码

完整的代码:


这个程序的意义是:如果你想做一个高速传输设备,不想走Windows的内置协议,但是又不想自己完整实现驱动,那么可以使用对应的代码实现自身的设备,然后使用WCH 提供的驱动,自行完成 设备固件和Windows应用程序。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail