前面介绍过如何使用Arduino 环境进行Ch32V305 的开发,这次带来的是一个CH32V305 Arduino 实现模拟Ch372 的例子,参考的是Ch32v307EVT 中的HSDevice 的代码。根据Exam 中的CH32V30x_List.txt 描述,这个CH372 例子是模拟自定义USB 设备(CH372 设备),端点1 ,3 下传,2 ,4 上传,端点1 下传的数据从端点3 上传,不取反,端点2 下传的数据从端点4 上传,取反。但是,应该是描述存在错误,实际代码不是这样。 首先,改造代码,然后烧写到板子上。使用USBView 查看,端点1 有一个 OUT 和 IN; 端点3是OUT,端点4是 IN, 端点5是OUT, 端点6是IN.
- ===>Endpoint Descriptor<===
- bLength: 0x07
- bDescriptorType: 0x05
- bEndpointAddress: 0x01 -> Direction: OUT - EndpointID: 1
- bmAttributes: 0x02 -> Bulk Transfer Type
- wMaxPacketSize: 0x0200 = 0x200 max bytes
- bInterval: 0x00
-
- ===>Endpoint Descriptor<===
- bLength: 0x07
- bDescriptorType: 0x05
- bEndpointAddress: 0x81 -> Direction: IN - EndpointID: 1
- bmAttributes: 0x02 -> Bulk Transfer Type
- wMaxPacketSize: 0x0200 = 0x200 max bytes
- bInterval: 0x00
-
- ===>Endpoint Descriptor<===
- bLength: 0x07
- bDescriptorType: 0x05
- bEndpointAddress: 0x03 -> Direction: OUT - EndpointID: 3
- bmAttributes: 0x02 -> Bulk Transfer Type
- wMaxPacketSize: 0x0200 = 0x200 max bytes
- bInterval: 0x00
-
- ===>Endpoint Descriptor<===
- bLength: 0x07
- bDescriptorType: 0x05
- bEndpointAddress: 0x84 -> Direction: IN - EndpointID: 4
- bmAttributes: 0x02 -> Bulk Transfer Type
- wMaxPacketSize: 0x0200 = 0x200 max bytes
- bInterval: 0x00
-
- ===>Endpoint Descriptor<===
- bLength: 0x07
- bDescriptorType: 0x05
- bEndpointAddress: 0x05 -> Direction: OUT - EndpointID: 5
- bmAttributes: 0x02 -> Bulk Transfer Type
- wMaxPacketSize: 0x0200 = 0x200 max bytes
- bInterval: 0x00
-
- ===>Endpoint Descriptor<===
- bLength: 0x07
- bDescriptorType: 0x05
- bEndpointAddress: 0x86 -> Direction: IN - EndpointID: 6
- bmAttributes: 0x02 -> Bulk Transfer Type
- wMaxPacketSize: 0x0200 = 0x200 max bytes
- bInterval: 0x00
复制代码
对应处理的代码在 ch32v30x_usbhs_device.c 文件中。下面对代码进行研读。
代码中Ch32端点1 OUT 收到的数据直接放到端点1IN中。
- /* end-point 1 data out interrupt */
- case USBHS_UIS_TOKEN_OUT | DEF_UEP1:
- if ( intst & USBHS_UIS_TOG_OK )
- {
- /* Write In Buffer */
- USBHSD->UEP1_RX_CTRL ^= USBHS_UEP_R_TOG_DATA1;
- RingBuffer_Comm.PackLen[RingBuffer_Comm.LoadPtr] = USBHSD->RX_LEN;
- RingBuffer_Comm.LoadPtr ++;
- if(RingBuffer_Comm.LoadPtr == DEF_Ring_Buffer_Max_Blks)
- {
- RingBuffer_Comm.LoadPtr = 0;
- }
- USBHSD->UEP1_RX_DMA = (uint32_t)(&Data_Buffer[(RingBuffer_Comm.LoadPtr) * DEF_USBD_HS_PACK_SIZE]);
- RingBuffer_Comm.RemainPack ++;
- if(RingBuffer_Comm.RemainPack >= DEF_Ring_Buffer_Max_Blks-DEF_RING_BUFFER_REMINE)
- {
- USBHSD->UEP1_RX_CTRL = ((USBHSD->UEP1_RX_CTRL) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK;
- RingBuffer_Comm.StopFlag = 1;
- }
- }
- break;
复制代码
端点3收到的数据取反后放到端点4上。
- /* end-point 3 data out interrupt */
- case USBHS_UIS_TOKEN_OUT | DEF_UEP3:
- if ( intst & USBHS_UIS_TOG_OK )
- {
- len = (uint16_t)(USBHSD->RX_LEN);
- USBHSD->UEP3_RX_CTRL ^= USBHS_UEP_R_TOG_DATA1;
- USBHSD->UEP3_RX_CTRL = ((USBHSD->UEP3_RX_CTRL) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK;
- for(i=0; i<len; i++)
- {
- USBHS_EP4_Tx_Buf[i] = ~USBHS_EP3_Rx_Buf[i];
- }
- USBHSD->UEP4_TX_LEN = len;
- USBHSD->UEP4_TX_CTRL = (USBHSD->UEP4_TX_CTRL & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_ACK;
- }
- break;
复制代码
类似的端点5收到的数据取反,通过端点6上传 - /* end-point 5 data out interrupt */
- case USBHS_UIS_TOKEN_OUT | DEF_UEP5:
- if ( intst & USBHS_UIS_TOG_OK )
- {
- len = (uint16_t)(USBHSD->RX_LEN);
- USBHSD->UEP5_RX_CTRL ^= USBHS_UEP_R_TOG_DATA1;
- USBHSD->UEP5_RX_CTRL = ((USBHSD->UEP5_RX_CTRL) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK;
- for(i=0; i<len; i++)
- {
- USBHS_EP6_Tx_Buf[i] = ~USBHS_EP5_Rx_Buf[i];
- }
- USBHSD->UEP6_TX_LEN = len;
- USBHSD->UEP6_TX_CTRL = (USBHSD->UEP6_TX_CTRL & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_ACK;
- }
- break;
复制代码
从代码上可以看出,Exam中的描述是存在一些问题的。 之后,再编写一个VC代码,进行速度测试:
代码来自Ch569 的EVT Package, 有部分修改:
- // 2003.09.08, 2003.12.28
- //****************************************
- //** Copyright (C) W.ch 1999-2005 **
- //** Web: http://www.winchiphead.com **
- //****************************************
- //** DLL for USB interface chip CH375 **
- //** C, VC5.0 **
- //****************************************
- //
- // USB总线接口芯片CH375的数据块测试程序 V1.0
- // 南京沁恒电子有限公司 作者: W.ch 2003.12
- // CH375-BLK V1.0
- // 运行环境: Windows 98/ME, Windows 2000/XP
- // support USB chip: CH372/CH375
- //
-
- #include <windows.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <conio.h>
- #include <winioctl.h>
-
- #include "CH375DLL.H"
- #pragma comment(lib,"CH375DLL")
- #define TEST_DATA_LEN 4096
- #define TEST_NUM 1000
- unsigned char mReadBuf[TEST_DATA_LEN];
- unsigned char mWriteBuf[TEST_DATA_LEN];
- //程序入口
- void main (int argc,char **argv )
- {
- unsigned long mLength, mTestCount, mErrCnt,mArg,mFirstTick,mLastTick;
- long long mTotal=0;
- double speed;
- USHORT mCount = 0;
- printf( "\nCH372/CH375 Bulk Data Test Program V1.1 , Copyright (C) W.ch 2004.12\n" );
- printf( "test data correctness \n" );
- mArg = TEST_DATA_LEN;
-
- // 需要使用DLL则需要先加载,没有此句则会自动加载
- printf( "*** CH375OpenDevice: 0# \n" );
- if ( CH375OpenDevice( 0 ) == INVALID_HANDLE_VALUE ) return; /* 使用之前必须打开设备 */
-
- memset(mWriteBuf, 0xFF, sizeof(mWriteBuf));
-
- mErrCnt=0;
-
- printf( "*** CH375ReadData: 1000 times 4M Byte ***\n" );
-
- mTotal = 0.0;
- for ( mTestCount=0; mTestCount < TEST_NUM; ++mTestCount ) // 循环测试
- {
- if(mTestCount == 0)
- {
- mFirstTick=GetTickCount();
- }
- mLength = mArg;
- if (CH375WriteEndP(0, 1, mWriteBuf, &mLength)) // 写入成功
- {
- mTotal += mLength;
- if (mLength == 0)
- {
- Sleep(0); //放弃当前线程的时间片,防止CPU出现100%情况
- }
- }
- else
- { // 写操作失败
- printf("S1-T%0ld-C%ld CH375WriteEndP return error, length=%d\n", mTestCount, mTestCount, mTotal);
- }
-
- mLength = mArg;
- if (CH375ReadEndP(0, 1, mReadBuf, &mLength)) // 接收成功
- {
- mTotal += mLength;
- if(mLength == 0 )
- {
- Sleep(0); //放弃当前线程的时间片,防止CPU出现100%情况
- }
- }
- else
- {
-
- printf( "S1-T%0ld-C%ld CH375ReadData return error, length=%d\n", mTestCount, mTestCount, mTotal );
- }
-
-
-
- }
-
- mLastTick =GetTickCount();
- mLastTick = mLastTick - mFirstTick;
- speed=1000;
- speed=speed*mTotal/mLastTick;
- printf( "*** average speed = %7.1f MBytes/Sec, total=%lld bytes\n", speed/1000/1000, mTotal);
-
- CH375CloseDevice( 0 );
-
- printf( "\nExit.\n" );
- _getch();
-
- }
复制代码
完整的源代码和可执行 EXE, 建议有需要的朋友重新编译。
对应的 Arduino代码,看着是不是非常简单?
- #include "src\\userUsbCh372\\ch32v30x_usbhs_device.h"
-
- void setup() {
- Serial.begin(115200);
- Serial.println("Start");
-
- /* Initialize system configuration */
- SystemCoreClockUpdate( );
- NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2 );
- Delay_Init( );
-
- /* Initialize USBHS interface to communicate with the host */
- USBHS_RCC_Init( );
- USBHS_Device_Init( ENABLE );
- }
-
- uint8_t ret;
-
- void loop() {
- /* Determine if enumeration is complete, perform data transfer if completed */
- if(USBHS_DevEnumStatus)
- {
- /* Data Transfer */
- if(RingBuffer_Comm.RemainPack)
- {
- 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);
- if(ret == 0)
- {
- NVIC_DisableIRQ(USBHS_IRQn);
- RingBuffer_Comm.RemainPack--;
- RingBuffer_Comm.DealPtr++;
- if(RingBuffer_Comm.DealPtr == DEF_Ring_Buffer_Max_Blks)
- {
- RingBuffer_Comm.DealPtr = 0;
- }
- NVIC_EnableIRQ(USBHS_IRQn);
- }
- }
-
- /* Monitor whether the remaining space is available for further downloads */
- if(RingBuffer_Comm.RemainPack < (DEF_Ring_Buffer_Max_Blks - DEF_RING_BUFFER_RESTART))
- {
- if(RingBuffer_Comm.StopFlag)
- {
- RingBuffer_Comm.StopFlag = 0;
- USBHSD->UEP1_RX_CTRL = (USBHSD->UEP1_RX_CTRL & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_ACK;
- }
- }
- }
- }
复制代码
完整的代码:
这个程序的意义是:如果你想做一个高速传输设备,不想走Windows的内置协议,但是又不想自己完整实现驱动,那么可以使用对应的代码实现自身的设备,然后使用WCH 提供的驱动,自行完成 设备固件和Windows应用程序。
|