一個通過CH55X系列單片機接收串口數據轉HID鍵盤上傳程序
1、本例程基于USB單片機CH559、CH558、CH554編寫,所有版權歸WCH所有。
2、本例程實時更新,不另行通知。
- /********************************** (C) COPYRIGHT *******************************
- * File Name :Composite_Dev.C
- * Author : WCH
- * Version : V1.0
- * Date : 2017/01/20
- * Description : CH559模擬USB復合設備,鍵鼠,支持類命令
- *******************************************************************************/
- #include "./Public/CH554.H"
- #include "./Public/DEBUG.H"
- #include <string.h>
- #include <stdio.h>
- #define THIS_ENDP0_SIZE DEFAULT_ENDP0_SIZE
- #define CapsLockLED 0x02
- #define BUFMAX 16
- UINT8X Ep0Buffer[8>(THIS_ENDP0_SIZE+2)?8:(THIS_ENDP0_SIZE+2)] _at_ 0x0000; //端點0 OUT&IN緩沖區,必須是偶地址
- UINT8X Ep1Buffer[64>(MAX_PACKET_SIZE+2)?64:(MAX_PACKET_SIZE+2)] _at_ 0x000a; //端點1 IN緩沖區,必須是偶地址
- UINT8 SetupReq,SetupLen,Ready,Count,FLAG,UsbConfig,LED_VALID;
- PUINT8 pDescr; //USB配置標志
- USB_SETUP_REQ SetupReqBuf; //暫存Setup包
- bit Ep2InKey;
- #define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer)
- #define DEBUG 0
- #pragma NOAREGS
- /*設備描述符*/
- UINT8C DevDesc[18] = {0x12,0x01,0x10,0x01,0x00,0x00,0x00,0x08,
- 0x3d,0x41,0x07,0x21,0x00,0x00,0x00,0x00,
- 0x00,0x01
- };
- UINT8C CfgDesc[59] =
- {
- 0x09,0x02,0x22,0x00,0x01,0x01,0x00,0xA0,0x32, //配置描述符
- 0x09,0x04,0x00,0x00,0x01,0x03,0x01,0x01,0x00, //接口描述符,鍵盤
- 0x09,0x21,0x11,0x01,0x00,0x01,0x22,0x3e,0x00, //HID類描述符
- 0x07,0x05,0x81,0x03,0x08,0x00,0x0a, //端點描述符
- };
- /*字符串描述符*/
- /*HID類報表描述符*/
- UINT8C KeyRepDesc[62] =
- {
- 0x05,0x01,0x09,0x06,0xA1,0x01,0x05,0x07,
- 0x19,0xe0,0x29,0xe7,0x15,0x00,0x25,0x01,
- 0x75,0x01,0x95,0x08,0x81,0x02,0x95,0x01,
- 0x75,0x08,0x81,0x01,0x95,0x03,0x75,0x01,
- 0x05,0x08,0x19,0x01,0x29,0x03,0x91,0x02,
- 0x95,0x05,0x75,0x01,0x91,0x01,0x95,0x06,
- 0x75,0x08,0x26,0xff,0x00,0x05,0x07,0x19,
- 0x00,0x29,0x91,0x81,0x00,0xC0
- };
- /*鍵盤數據*/
- UINT8 HIDKey[8] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
- UINT8 DataBuffer[BUFMAX];
- UINT8 DataLen =0;
- UINT8 RecvPoint =0;
- UINT8 SendPoint =0;
- /*******************************************************************************
- * Function Name : USBDeviceInit()
- * Description : USB設備模式配置,設備模式啟動,收發端點配置,中斷開啟
- * Input : None
- * Output : None
- * Return : None
- *******************************************************************************/
- void USBDeviceInit()
- {
- IE_USB = 0;
- USB_CTRL = 0x00; // 先設定USB設備模式
- UEP0_DMA = Ep0Buffer; //端點0數據傳輸地址
- UEP1_DMA = Ep1Buffer; //端點1數據傳輸地址
- UEP4_1_MOD = ~(bUEP4_RX_EN | bUEP4_TX_EN |bUEP1_RX_EN | bUEP1_BUF_MOD) | bUEP4_TX_EN;//端點1單64字節收發緩沖區,端點0收發
- UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; //OUT事務返回ACK,IN事務返回NAK
- UEP1_CTRL = bUEP_T_TOG | UEP_T_RES_NAK;
-
- USB_DEV_AD = 0x00;
- UDEV_CTRL = bUD_PD_DIS; // 禁止DP/DM下拉電阻
- USB_CTRL = bUC_DEV_PU_EN | bUC_INT_BUSY | bUC_DMA_EN; // 啟動USB設備及DMA,在中斷期間中斷標志未清除前自動返回NAK
- UDEV_CTRL |= bUD_PORT_EN; // 允許USB端口
- USB_INT_FG = 0xFF; // 清中斷標志
- USB_INT_EN = bUIE_SUSPEND | bUIE_TRANSFER | bUIE_BUS_RST;
- IE_USB = 1;
- }
- /*******************************************************************************
- * Function Name : Enp1IntIn()
- * Description : USB設備模式端點1的中斷上傳
- * Input : None
- * Output : None
- * Return : None
- *******************************************************************************/
- void Enp1IntIn( )
- {
- memcpy( Ep1Buffer, HIDKey, sizeof(HIDKey)); //加載上傳數據
- UEP1_T_LEN = sizeof(HIDKey); //上傳數據長度
- UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_ACK; //有數據時上傳數據并應答ACK
- }
- /*******************************************************************************
- * Function Name : DeviceInterrupt()
- * Description : CH559USB中斷處理函數
- *******************************************************************************/
- void DeviceInterrupt( void ) interrupt INT_NO_USB using 1 //USB中斷服務程序,使用寄存器組1
- {
- UINT8 len;
- if(UIF_TRANSFER) //USB傳輸完成標志
- {
- switch (USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP))
- {
- case UIS_TOKEN_IN | 2: //endpoint 2# 中斷端點上傳
- UEP2_T_LEN = 0; //預使用發送長度一定要清空
- // UEP1_CTRL ^= bUEP_T_TOG; //如果不設置自動翻轉則需要手動翻轉
- UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_NAK; //默認應答NAK
- break;
- case UIS_TOKEN_IN | 1: //endpoint 1# 中斷端點上傳
- UEP1_T_LEN = 0; //預使用發送長度一定要清空
- // UEP2_CTRL ^= bUEP_T_TOG; //如果不設置自動翻轉則需要手動翻轉
- UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_NAK; //默認應答NAK
- FLAG = 1; /*傳輸完成標志*/
- break;
- case UIS_TOKEN_SETUP | 0: //SETUP事務
- len = USB_RX_LEN;
- if(len == (sizeof(USB_SETUP_REQ)))
- {
- SetupLen = UsbSetupBuf->wLengthL;
- if(UsbSetupBuf->wLengthH || SetupLen > 0x7F )
- {
- SetupLen = 0x7F; // 限制總長度
- }
- len = 0; // 默認為成功并且上傳0長度
- SetupReq = UsbSetupBuf->bRequest;
- if ( ( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )/* HID類命令 */
- {
- switch( SetupReq )
- {
- case 0x01://GetReport
- break;
- case 0x02://GetIdle
- break;
- case 0x03://GetProtocol
- break;
- case 0x09://SetReport
- break;
- case 0x0A://SetIdle
- break;
- case 0x0B://SetProtocol
- break;
- default:
- len = 0xFF; /*命令不支持*/
- break;
- }
- }
- else
- {//標準請求
- switch(SetupReq) //請求碼
- {
- case USB_GET_DESCRIPTOR:
- switch(UsbSetupBuf->wValueH)
- {
- case 1: //設備描述符
- pDescr = DevDesc; //把設備描述符送到要發送的緩沖區
- len = sizeof(DevDesc);
- break;
- case 2: //配置描述符
- pDescr = CfgDesc; //把設備描述符送到要發送的緩沖區
- len = sizeof(CfgDesc);
- break;
- case 0x22: //報表描述符
- if(UsbSetupBuf->wIndexL == 0) //接口0報表描述符
- {
- pDescr = KeyRepDesc; //數據準備上傳
- len = sizeof(KeyRepDesc);
- Ready = 1; //如果有更多接口,該標準位應該在最后一個接口配置完成后有效
- IE_UART1 = 1;//開啟串口中斷
-
- }
- else
- {
- len = 0xff; //本程序只有2個接口,這句話正常不可能執行
- }
- break;
- default:
- len = 0xff; //不支持的命令或者出錯
- break;
- }
- if ( SetupLen > len )
- {
- SetupLen = len; //限制總長度
- }
- len = SetupLen >= 8 ? 8 : SetupLen; //本次傳輸長度
- memcpy(Ep0Buffer,pDescr,len); //加載上傳數據
- SetupLen -= len;
- pDescr += len;
- break;
- case USB_SET_ADDRESS:
- SetupLen = UsbSetupBuf->wValueL; //暫存USB設備地址
- break;
- case USB_GET_CONFIGURATION:
- Ep0Buffer[0] = UsbConfig;
- if ( SetupLen >= 1 )
- {
- len = 1;
- }
- break;
- case USB_SET_CONFIGURATION:
- UsbConfig = UsbSetupBuf->wValueL;
- break;
- case 0x0A:
- break;
- case USB_CLEAR_FEATURE: //Clear Feature
- if ( ( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )// 端點
- {
- switch( UsbSetupBuf->wIndexL )
- {
- case 0x82:
- UEP2_CTRL = UEP2_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK;
- break;
- case 0x81:
- UEP1_CTRL = UEP1_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK;
- break;
- case 0x01:
- UEP1_CTRL = UEP1_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK;
- break;
- default:
- len = 0xFF; // 不支持的端點
- break;
- }
- }
- else
- {
- len = 0xFF; // 不是端點不支持
- }
- break;
- case USB_SET_FEATURE: /* Set Feature */
- if( ( UsbSetupBuf->bRequestType & 0x1F ) == 0x00 ) /* 設置設備 */
- {
- if( ( ( ( UINT16 )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x01 )
- {
- if( CfgDesc[ 7 ] & 0x20 )
- {
- /* 設置喚醒使能標志 */
- }
- else
- {
- len = 0xFF; /* 操作失敗 */
- }
- }
- else
- {
- len = 0xFF; /* 操作失敗 */
- }
- }
- else if( ( UsbSetupBuf->bRequestType & 0x1F ) == 0x02 ) /* 設置端點 */
- {
- if( ( ( ( UINT16 )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x00 )
- {
- switch( ( ( UINT16 )UsbSetupBuf->wIndexH << 8 ) | UsbSetupBuf->wIndexL )
- {
- case 0x82:
- UEP2_CTRL = UEP2_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;/* 設置端點2 IN STALL */
- break;
- case 0x02:
- UEP2_CTRL = UEP2_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;/* 設置端點2 OUT Stall */
- break;
- case 0x81:
- UEP1_CTRL = UEP1_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;/* 設置端點1 IN STALL */
- break;
- default:
- len = 0xFF; //操作失敗
- break;
- }
- }
- else
- {
- len = 0xFF; //操作失敗
- }
- }
- else
- {
- len = 0xFF; //操作失敗
- }
- break;
- case USB_GET_STATUS:
- Ep0Buffer[0] = 0x00;
- Ep0Buffer[1] = 0x00;
- if ( SetupLen >= 2 )
- {
- len = 2;
- }
- else
- {
- len = SetupLen;
- }
- break;
- default:
- len = 0xff; //操作失敗
- break;
- }
- }
- }
- else
- {
- len = 0xff; //包長度錯誤
- }
- if(len == 0xff)
- {
- SetupReq = 0xFF;
- UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_STALL | UEP_T_RES_STALL;//STALL
- }
- else if(len <= 8) //上傳數據或者狀態階段返回0長度包
- {
- UEP0_T_LEN = len;
- UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK;//默認數據包是DATA1,返回應答ACK
- }
- else
- {
- UEP0_T_LEN = 0; //雖然尚未到狀態階段,但是提前預置上傳0長度數據包以防主機提前進入狀態階段
- UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK;//默認數據包是DATA1,返回應答ACK
- }
- break;
- case UIS_TOKEN_IN | 0: //endpoint0 IN
- switch(SetupReq)
- {
- case USB_GET_DESCRIPTOR:
- len = SetupLen >= 8 ? 8 : SetupLen; //本次傳輸長度
- memcpy( Ep0Buffer, pDescr, len ); //加載上傳數據
- SetupLen -= len;
- pDescr += len;
- UEP0_T_LEN = len;
- UEP0_CTRL ^= bUEP_T_TOG; //同步標志位翻轉
- break;
- case USB_SET_ADDRESS:
- USB_DEV_AD = USB_DEV_AD & bUDA_GP_BIT | SetupLen;
- UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
- break;
- default:
- UEP0_T_LEN = 0; //狀態階段完成中斷或者是強制上傳0長度數據包結束控制傳輸
- UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
- break;
- }
- break;
- case UIS_TOKEN_OUT | 0: // endpoint0 OUT
- len = USB_RX_LEN;
- if((SetupReq == 0x09)&& (len == 1))
- {
- LED_VALID = Ep0Buffer[0];
- }
- else if((SetupReq == 0x09) && (len == 8)){//SetReport
- }
- UEP0_T_LEN = 0; //雖然尚未到狀態階段,但是提前預置上傳0長度數據包以防主機提前進入狀態階段
- UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_ACK;//默認數據包是DATA0,返回應答ACK
- break;
- default:
- break;
- }
- UIF_TRANSFER = 0; //寫0清空中斷
- }
- if(UIF_BUS_RST) //設備模式USB總線復位中斷
- {
- UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
- UEP1_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK;
- UEP2_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
- USB_DEV_AD = 0x00;
- UIF_SUSPEND = 0;
- UIF_TRANSFER = 0;
- UIF_BUS_RST = 0; //清中斷標志
- }
- if (UIF_SUSPEND) //USB總線掛起/喚醒完成
- {
- UIF_SUSPEND = 0;
- }
- else { //意外的中斷,不可能發生的情況
- USB_INT_FG = 0xFF; //清中斷標志
- }
- }
- /*******************************************************************************
- * Function Name : QueryUART1Interrupt(void)
- * Description : UART1中斷服務程序
- *******************************************************************************/
- void QueryUART1Interrupt( void ) interrupt INT_NO_UART1 using 2 //UART1中斷服務程序,使用寄存器組1
- {
- if(U1RI)
- {
- U1RI = 0;
- DataBuffer[RecvPoint++] = SBUF1;
- DataLen++;
- if(RecvPoint==BUFMAX) RecvPoint=0;
- }
- U1TI = 0;
- }
- /*******************************************************************************
- * Function Name : KeyCodeCorrespond()
- * Description : 鍵碼比對表,由數值對應鍵盤值。
- * Input : UINT8 keyCode
- * Output : None
- * Return : None
- *******************************************************************************/
- void KeyCodeCorrespond(UINT8 keyCode)
- {
- HIDKey[0] = 0;
- if((keyCode>='a')&&(keyCode<='z')){ //鍵值a-z
-
- if(LED_VALID&0x02)
- {
- FLAG = 0;
- HIDKey[2] = 0x39;
- Enp1IntIn();
- while(FLAG == 0);
- FLAG = 0;
- memset(&HIDKey[0],0,8);
- Enp1IntIn();
- while(FLAG == 0);
- }
- keyCode -= 0x5D;
- HIDKey[2] = keyCode;
-
- }
- else if((keyCode>='A')&&(keyCode<='Z')){
- if((LED_VALID&0x02) == 0)
- {
- FLAG = 0;
- HIDKey[2] = 0x39;
- Enp1IntIn();
- while(FLAG == 0);
- FLAG = 0;
- memset(&HIDKey[0],0,8);
- Enp1IntIn();
- while(FLAG == 0);
- }
-
-
- keyCode -= 0x3D;
- HIDKey[2] = keyCode;
- // HIDKey[0] = 0x02; //shift+
-
- }
- else if((keyCode>='1')&&(keyCode<='9')){
- keyCode -= 0x13; //字母區數字鍵
- HIDKey[2] = keyCode;
- }
- else if(keyCode=='0'){
- HIDKey[2] = 0x27;
- }
- else if(keyCode <= 0x2f){
- if(keyCode == 0x20){
- HIDKey[2] = 0x2C; //空格
- }
- else if(keyCode == 0x21){//'!'
- HIDKey[2] = 0x1E;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x22){//'"'
- HIDKey[2] = 0x34;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x23){//'#'
- HIDKey[2] = 0x20;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x24){//'
- HIDKey[2] = 0x21;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x25){//'%'
- HIDKey[2] = 0x22;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x26){//'&'
- HIDKey[2] = 0x24;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x27){//'%'
- HIDKey[2] = 0x34;
- }
- else if(keyCode == 0x28){/*(*/
- HIDKey[2] = 0x26;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x29){/*)*/
- HIDKey[2] = 0x27;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x2a){/***/
- HIDKey[2] = 0x25;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x2b){/*+*/
- HIDKey[2] = 0x2e;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x2c){/*,*/
- HIDKey[2] = 0x36;
- }
- else if(keyCode == 0x2d){/*-*/
- HIDKey[2] = 0x2d;
- }
- else if(keyCode == 0x2e){/*,*/
- HIDKey[2] = 0x37;
- }
- else if(keyCode == 0x2f){/*/*/
- HIDKey[2] = 0x38;
- }
- }
- else if(keyCode <= 0x3f){
- if(keyCode == 0x3a){/*:*/
- HIDKey[2] = 0x33;
- HIDKey[0] |= 0x02; //shift+
- }
- else if(keyCode == 0x3b){/*;*/
- HIDKey[2] = 0x33;
- }
- else if(keyCode == 0x3c){/*<*/
- HIDKey[2] = 0x36;
- HIDKey[0] |= 0x02; //shift+
- }
- else if(keyCode == 0x3d){/*=*/
- HIDKey[2] = 0x2e;
- }
- else if(keyCode == 0x3e){/*>*/
- HIDKey[2] = 0x37;
- HIDKey[0] |= 0x02; //shift+
- }
- else if(keyCode == 0x3f){/*?*/
- HIDKey[2] = 0x38;
- HIDKey[0] |= 0x02; //shift+
- }
- }
- else if(keyCode == 0x40){/*@*/
- HIDKey[2] = 0x1f;
- HIDKey[0] = 0x02; //shift+
- }
- else if((keyCode >= 0x5b)&&(keyCode <= 0x60)){
- if(keyCode == 0x5b){/*[*/
- HIDKey[2] = 0x2f;
- }
- else if(keyCode == 0x5c){/*\*/
- HIDKey[2] = 0x31;
- }
- else if(keyCode == 0x5d){/*:*/
- HIDKey[2] = 0x30;
- }
- else if(keyCode == 0x5e){/*:*/
- HIDKey[2] = 0x23;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x5f){/*:*/
- HIDKey[2] = 0x2d;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x60){/*`*/
- HIDKey[2] = 0x35;
- }
- }
- else if((keyCode >= 0x7b)&&(keyCode <= 0x7f)){
- if(keyCode == 0x7b){/*{*/
- HIDKey[2] = 0x2f;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x7c){/*|*/
- HIDKey[2] = 0x31;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x7d){/*}*/
- HIDKey[2] = 0x30;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x7e){/*~*/
- HIDKey[2] = 0x35;
- HIDKey[0] = 0x02; //shift+
- }
- else if(keyCode == 0x7f){/*{*/
- HIDKey[2] = 0x4c;
- }
- }
- else if((keyCode >= 0x80)&&(keyCode <= 0x87)){/*left ctl*/
- keyCode &= 0x0f;
- HIDKey[0] = (1<<keyCode); //
- }
- else if((keyCode >= 0xd7)&&(keyCode <= 0xda)){/**/
- keyCode -= 0x88;
- HIDKey[2] = keyCode;
- }
- else if((keyCode >= 0xb0)&&(keyCode <= 0xb3)){/**/
- keyCode -= 0x88;
- HIDKey[2] = keyCode;
- }
- else if((keyCode >= 0xd1)&&(keyCode <= 0xd5)){/**/
- keyCode -= 0x88;
- HIDKey[2] = keyCode;
- }
- else if((keyCode >= 0xC1)&&(keyCode <= 0xCD)){/**/
- keyCode -= 0x88;
- HIDKey[2] = keyCode;
- }
- }
- void HIDValueHandle()
- {
- DataLen--;
- KeyCodeCorrespond(DataBuffer[SendPoint]);
-
- SendPoint++;
- if(SendPoint>=BUFMAX) SendPoint=0;
- FLAG = 0;
- Enp1IntIn();
- while(FLAG == 0);
- FLAG = 0;
- memset(&HIDKey[0],0,8);
- Enp1IntIn();
- while(FLAG == 0);
-
- }
- main()
- {
- CfgFsys( ); //CH559時鐘選擇配置
- mDelaymS(5); //修改主頻等待內部晶振穩定,必加
- mInitSTDIO( ); //串口0初始化
- printf("start\n");
- USBDeviceInit(); //USB設備模式初始化
- UART1Setup();
- EA = 1; //允許單片機中斷
- IP_EX = bIP_UART1;//串口優先等級高
- UEP1_T_LEN = 0; //預使用發送長度一定要清空
- FLAG = 0;
- Ready = 0;
- LED_VALID = 1; //給一個默認值
- while(1)
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
全部資料51hei下載地址:
CH554串口接收數據轉USB鍵值上傳201808.zip
(135.46 KB, 下載次數: 102)
2018-12-3 13:02 上傳
點擊文件名下載附件
CH55X模擬鍵盤
|