본문 바로가기

WCH/CH32V035

CH32X035 SSM - USB HID 테스트( 파이썬 pywinusb 를 이용한 HID 테스트)

CH32x035 의 USB Custom HID 테스트 해 보자.

참고 소스코드는 https://github.com/openwch/ch32x035/tree/main/EVT/EXAM/USB/USBFS/DEVICE/CompatibilityHID 를 수정하여 작성하였다.

 

WCH에서 제공하는 USB HID코드는 UART에서 받은 데이터를 HID로 전송하도록 되어 있는데 스위치 누르면 HID 데이터 전송하고 PC에서 받은 HID레포트 데이터를 출력 하도록 코드를 수정 하였다.

int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    SystemCoreClockUpdate();
    Delay_Init();
    USART_Printf_Init(115200);
    GPIO_INIT();
    Led1Off();

    printf("SystemClk:%d\r\n", SystemCoreClock);
    printf("ChipID:%08x\r\n", DBGMCU_GetCHIPID() );

    /* Variables init */
    Var_Init( );

    /* UART2 init */
    //UART2_Init();
    //UART2_DMA_Init();

    TIM3_Init();
    /* Usb Init */
    USBFS_RCC_Init( );
    USBFS_Device_Init( ENABLE , PWR_VDD_SupplyVoltage());
    while(1)
    {
        if(!GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_3))
        {
            printf("Press SW\r\n");
            SendReport();
            Delay_Ms(200);
        }

		//USB 인식 되어 있으면
        if(USBFS_DevEnumStatus)
        {
            //UART2_Rx_Service();
            //UART2_Tx_Service();
            HID_Rx_Service();
        }
    }
}

 

 

 

펌웨어 다운로드 하고 USB장치를 인식 시키면 HID장치가 인식되는 것을 확인 할 수 있다.

 

 

데이터 수신시 USBFS_IRQHandler() 함수에서 처리되고 HID_SET_REPORT에서 HID_Set_Report_Flag를 확인하면 된다.

void USBFS_IRQHandler( void )
{
:

    /* data-out stage processing */
    case USBFS_UIS_TOKEN_OUT:
        switch( intst & ( USBFS_UIS_TOKEN_MASK | USBFS_UIS_ENDP_MASK ) )
        {
            /* end-point 0 data out interrupt */
            case USBFS_UIS_TOKEN_OUT | DEF_UEP0:
                    if( intst & USBFS_UIS_TOG_OK )
                    {
                        if ( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )
                        {
                            if (( USBFS_SetupReqType & USB_REQ_TYP_MASK ) == USB_REQ_TYP_CLASS)
                            {
                                switch( USBFS_SetupReqCode )
                                {
                                    case HID_SET_REPORT:
                                        memcpy(&HID_Report_Buffer[0],USBFS_EP0_Buf,DEF_USBD_UEP0_SIZE);
                                        HID_Set_Report_Flag = SET_REPORT_WAIT_DEAL;
                                        USBFSD->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_NAK;
                                        break;
                                    default:
                                        break;
                                }
                            }
                        }
                        else
                        {
                            /* Standard request end-point 0 Data download */
                            /* Add your code here */
                        }

                    }
                    break;

:

 

 

 

HID 수신 데이터 처리 함수

void HID_Rx_Service()
{
    uint16_t i;
    if (HID_Set_Report_Flag == SET_REPORT_WAIT_DEAL)
    {
        printf("Set Report:\r\n");
        for (i = 0; i < 64; ++i)
        {
            printf("%02x ",HID_Report_Buffer[i]);
        }
        printf("\r\n");
        
        if(pbuf[0])
        {
            Led1On();
        }
        else Led1Off();
        
        HID_Set_Report_Flag = SET_REPORT_DEAL_OVER;
        USBFSD->UEP0_TX_LEN  = 0;
        USBFSD->UEP0_CTRL_H =  USBFS_UEP_T_RES_ACK | USBFS_UEP_T_TOG;
    }
}

 

 

기존에 테스트 했던 HID 프로그램으로 테스트 해보 았다. 정상적으로 잘 구동이된다.

 

 


 

요즘에는 PC프로그램으로 파이썬을 많이 이용하는데 파이썬에서 USB HID를 지원하는 라이브러리가 있어 테스트 해 보았다.

먼저 pywinusb 를 설치 해야 한다.

PS D:\WORK\ARM\CH32V\ch32x035_ssm\chx035_test> pip install pywinusb
Collecting pywinusb
  Downloading pywinusb-0.4.2.zip (61 kB)
     ---------------------------------------- 61.7/61.7 KB 3.4 MB/s eta 0:00:00
  Preparing metadata (setup.py) ... done
Using legacy 'setup.py install' for pywinusb, since package 'wheel' is not installed.
Installing collected packages: pywinusb
  Running setup.py install for pywinusb ... done
Successfully installed pywinusb-0.4.2
WARNING: You are using pip version 22.0.4; however, version 23.3.2 is available.
You should consider upgrading via the 'C:\Users\jhpark\AppData\Local\Programs\Python\Python39\python.exe -m pip install --upgrade pip' command.
PS D:\WORK\ARM\CH32V\ch32x035_ssm\chx035_test>

 

 

 

간단히 CH32X035 의 LED를 On/Off 할수 있는 USB HID 제어 파이썬 코드를 작성해 보았다.

import sys

from PySide2.QtCore import QSize
from PySide2.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget

import pywinusb.hid as hid


class HIDController:
    USB_CFG_VENDOR_ID = 0x1a86   #0x16c0  # 5824 = voti.nl
    USB_CFG_DEVICE_ID = 0xfe07  #0x05DF  # obdev's shared PID for HIDs
    
    filter = None
    hid_device = None
    device = None
    report = None

    last_row_status = None
        
    def __init__(self):
        self.get_Hid_USBDevice()

    def get_Hid_USBDevice(self):
        self.filter = hid.HidDeviceFilter(vendor_id=self.USB_CFG_VENDOR_ID, product_id=self.USB_CFG_DEVICE_ID)
        self.hid_device = self.filter.get_devices()
        self.device = self.hid_device[0]

    def open_device(self):
        if self.device.is_active():
            if not self.device.is_opened():
                self.device.open()
                self.get_report()
                return True
            else:
                print("Device already opened")
                return True
        else:
            print("Device is not active")

        return False

    def close_device(self):
        if self.device.is_active():
            if self.device.is_opened():
                self.device.close()
                return True
            else:
                print("Device already closed")
        else:
            print("Device is not active")

        return True

    def get_report(self):
        if not self.device.is_active():
            self.report = None

        for rep in self.device.find_output_reports() + self.device.find_feature_reports():
            self.report = rep
            
    def write_row_data(self, buffer: list):
        if self.report is not None:
            self.report.send(raw_data=buffer)
            return True
        else:
            print("Cannot write in the report. check if your device is still plugged")
            return False

    
g_tx_data = []

class Window(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.button1 = QPushButton(
            text="Led1On", parent=self
        )
        
        self.button2 = QPushButton(
            text="Led1Off", parent=self
        )
                
        self.button1.setFixedSize(300, 200)
        self.button1.clicked.connect(self.onClick1)
        
        
        self.button2.setFixedSize(300, 200)
        self.button2.clicked.connect(self.onClick2)
        
        layout = QVBoxLayout()
        layout.addWidget(self.button1)
        layout.addWidget(self.button2)
        self.setLayout(layout)
        
        
        global hid_device
        global g_led_status
        global g_tx_data
        
        hid_device = HIDController()
        hid_device.open_device()
        
        g_led_status = 0
        for x in range(65):
            g_tx_data.append(x)
    
    #rc.write_row_data(tx_data)         

    def onClick1(self):
        global hid_device
        global g_tx_data
        
        print("Press bt1")
        
        g_tx_data[2] = 0
        hid_device.write_row_data(g_tx_data)        
        
    def onClick2(self):
        global hid_device
        global g_tx_data
        
        g_tx_data[2] = 1    
        hid_device.write_row_data(g_tx_data)      
            
        print("2 Press")        


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    #sys.exit(app.exec())
    sys.exit(app.exec_())

 

 

실행결과 윈도우에서 HID로 제어 되는것을 확인 할 수 있다.

 

반응형