[DemoCode下载] USB虚拟串口

[复制链接]
1168|3
 楼主| gaoyang9992006 发表于 2024-4-21 20:39 | 显示全部楼层 |阅读模式
EC_M032_USBD_VCOM_And_HID_MMKey_V1.00.zip (1.63 MB, 下载次数: 3)
USB接口模拟虚拟串口与键盘。
  1. /******************************************************************************
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
  4. * $Revision: 12 $
  5. * $Date: 18/07/18 3:38p $
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]    Demonstrate how to implement a composite device.(VCOM and HID MMkey)
  7. *
  8. * @note
  9. * SPDX-License-Identifier: Apache-2.0
  10. * Copyright (C) 2021 Nuvoton Technology Corp. All rights reserved.
  11. *****************************************************************************/
  12. #include <stdio.h>
  13. #include "NuMicro.h"
  14. #include "VCOM_and_HID_keyboard.h"

  15. #define CRYSTAL_LESS        1    /* CRYSTAL_LESS must be 1 if USB clock source is HIRC */
  16. #define TRIM_INIT           (SYS_BASE+0x118)

  17. int IsDebugFifoEmpty(void);

  18. /*--------------------------------------------------------------------------*/
  19. STR_VCOM_LINE_CODING gLineCoding = {115200, 0, 0, 8};   /* Baud rate : 115200    */
  20. /* Stop bit     */
  21. /* parity       */
  22. /* data bits    */
  23. uint16_t gCtrlSignal = 0;     /* BIT0: DTR(Data Terminal Ready) , BIT1: RTS(Request To Send) */

  24. extern uint8_t volatile g_u8Suspend;
  25. /*--------------------------------------------------------------------------*/
  26. #define RX_BUFSIZE           512 /* RX buffer size */
  27. #define TX_BUFSIZE           512 /* RX buffer size */
  28. #define TX_FIFO_SIZE         16  /* TX Hardware FIFO size */

  29. /*---------------------------------------------------------------------------------------------------------*/
  30. /* Global variables                                                                                        */
  31. /*---------------------------------------------------------------------------------------------------------*/
  32. /* UART0 */
  33. volatile uint8_t comRbuf[RX_BUFSIZE];
  34. volatile uint16_t comRbytes = 0;
  35. volatile uint16_t comRhead = 0;
  36. volatile uint16_t comRtail = 0;

  37. volatile uint8_t comTbuf[TX_BUFSIZE];
  38. volatile uint16_t comTbytes = 0;
  39. volatile uint16_t comThead = 0;
  40. volatile uint16_t comTtail = 0;

  41. uint8_t gRxBuf[64] = {0};
  42. uint8_t *gpu8RxBuf = 0;
  43. uint32_t gu32RxSize = 0;
  44. uint32_t gu32TxSize = 0;

  45. volatile int8_t gi8BulkOutReady = 0;

  46. void SYS_Init(void)
  47. {
  48.     /* Unlock protected registers */
  49.     SYS_UnlockReg();

  50.     /* Enable HIRC clock */
  51.     CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);

  52.     /* Waiting for HIRC clock ready */
  53.     CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

  54.     /* Switch HCLK clock source to HIRC and HCLK source divide 1 */
  55.     CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1));

  56.     /* Switch UART0 clock source to HIRC */
  57.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));

  58.     /* Enable UART0 clock */
  59.     CLK_EnableModuleClock(UART0_MODULE);

  60.     /* Switch USB clock source to HIRC & USB Clock = HIRC / 1 */
  61.     CLK_SetModuleClock(USBD_MODULE, CLK_CLKSEL0_USBDSEL_HIRC, CLK_CLKDIV0_USB(1));

  62.     /* Enable USB clock */
  63.     CLK_EnableModuleClock(USBD_MODULE);

  64.     /* Update System Core Clock */
  65.     SystemCoreClockUpdate();

  66.     /* Set PB multi-function pins for UART0 RXD=PB.12 and TXD=PB.13 */
  67.     SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk))
  68.                     |(SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);

  69.     UART_ENABLE_INT(UART0, (UART_INTEN_RDAIEN_Msk | UART_INTEN_THREIEN_Msk | UART_INTEN_RXTOIEN_Msk));

  70.     /* Lock protected registers */
  71.     SYS_LockReg();
  72. }


  73. void PowerDown()
  74. {
  75.     /* Unlock protected registers */
  76.     SYS_UnlockReg();

  77.     printf("Enter power down ...\n");
  78.     while(!IsDebugFifoEmpty());

  79.     /* Wakeup Enable */
  80.     USBD_ENABLE_INT(USBD_INTEN_WKEN_Msk);

  81.     CLK_PowerDown();

  82.     /* Clear PWR_DOWN_EN if it is not clear by itself */
  83.     if(CLK->PWRCTL & CLK_PWRCTL_PDEN_Msk)
  84.         CLK->PWRCTL ^= CLK_PWRCTL_PDEN_Msk;

  85.     printf("device wakeup!\n");

  86.     /* Lock protected registers */
  87.     SYS_LockReg();
  88. }

  89. /*---------------------------------------------------------------------------------------------------------*/
  90. /* UART Callback function                                                                                  */
  91. /*---------------------------------------------------------------------------------------------------------*/
  92. void UART02_IRQHandler(void)
  93. {
  94.     uint8_t bInChar;
  95.     int32_t size;
  96.     uint32_t u32IntStatus;

  97.     u32IntStatus = UART0->INTSTS;

  98.     if((u32IntStatus & UART_INTSTS_RDAIF_Msk) || (u32IntStatus & UART_INTSTS_RXTOIF_Msk))
  99.     {
  100.         /* Receiver FIFO threshold level is reached or Rx time out */

  101.         /* Get all the input characters */
  102.         while (UART_GET_RX_EMPTY(UART0) == 0)
  103.         {
  104.             /* Get the character from UART Buffer */
  105.             bInChar = UART0->DAT;

  106.             /* Check if buffer full */
  107.             if(comRbytes < RX_BUFSIZE)
  108.             {
  109.                 /* Enqueue the character */
  110.                 comRbuf[comRtail++] = bInChar;
  111.                 if(comRtail >= RX_BUFSIZE)
  112.                     comRtail = 0;
  113.                 comRbytes++;
  114.             }
  115.             else
  116.             {
  117.                 /* FIFO over run */
  118.             }
  119.         }
  120.     }

  121.     if(u32IntStatus & UART_INTSTS_THREIF_Msk)
  122.     {
  123.         if(comTbytes && (UART0->INTEN & UART_INTEN_THREIEN_Msk))
  124.         {
  125.             /* Fill the Tx FIFO */
  126.             size = comTbytes;
  127.             if(size >= TX_FIFO_SIZE)
  128.             {
  129.                 size = TX_FIFO_SIZE;
  130.             }

  131.             while(size)
  132.             {
  133.                 bInChar = comTbuf[comThead++];
  134.                 UART0->DAT = bInChar;
  135.                 if(comThead >= TX_BUFSIZE)
  136.                     comThead = 0;
  137.                 comTbytes--;
  138.                 size--;
  139.             }
  140.         }
  141.         else
  142.         {
  143.             /* No more data, just stop Tx (Stop work) */
  144.             UART_DISABLE_INT(UART0, UART_INTEN_THREIEN_Msk);
  145.         }
  146.     }
  147. }

  148. void VCOM_TransferData(void)
  149. {
  150.     int32_t i, i32Len;

  151.     /* Check whether USB is ready for next packet or not*/
  152.     if(gu32TxSize == 0)
  153.     {
  154.         /* Check whether we have new COM Rx data to send to USB or not */
  155.         if(comRbytes)
  156.         {
  157.             i32Len = comRbytes;
  158.             if(i32Len > EP2_MAX_PKT_SIZE)
  159.                 i32Len = EP2_MAX_PKT_SIZE;

  160.             for(i = 0; i < i32Len; i++)
  161.             {
  162.                 gRxBuf[i] = comRbuf[comRhead++];
  163.                 if(comRhead >= RX_BUFSIZE)
  164.                     comRhead = 0;
  165.             }

  166.             __set_PRIMASK(1);
  167.             comRbytes -= i32Len;
  168.             __set_PRIMASK(0);

  169.             gu32TxSize = i32Len;
  170.             USBD_MemCopy((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP2)), (uint8_t *)gRxBuf, i32Len);
  171.             USBD_SET_PAYLOAD_LEN(EP2, i32Len);
  172.         }
  173.         else
  174.         {
  175.             /* Prepare a zero packet if previous packet size is EP2_MAX_PKT_SIZE and
  176.                no more data to send at this moment to note Host the transfer has been done */
  177.             i32Len = USBD_GET_PAYLOAD_LEN(EP2);
  178.             if(i32Len == EP2_MAX_PKT_SIZE)
  179.                 USBD_SET_PAYLOAD_LEN(EP2, 0);
  180.         }
  181.     }

  182.     /* Process the Bulk out data when bulk out data is ready. */
  183.     if(gi8BulkOutReady && (gu32RxSize <= TX_BUFSIZE - comTbytes))
  184.     {
  185.         for(i = 0; i < gu32RxSize; i++)
  186.         {
  187.             comTbuf[comTtail++] = gpu8RxBuf[i];
  188.             if(comTtail >= TX_BUFSIZE)
  189.                 comTtail = 0;
  190.         }

  191.         __set_PRIMASK(1);
  192.         comTbytes += gu32RxSize;
  193.         __set_PRIMASK(0);

  194.         gu32RxSize = 0;
  195.         gi8BulkOutReady = 0; /* Clear bulk out ready flag */

  196.         /* Ready to get next BULK out */
  197.         USBD_SET_PAYLOAD_LEN(EP3, EP3_MAX_PKT_SIZE);
  198.     }

  199.     /* Process the software Tx FIFO */
  200.     if(comTbytes)
  201.     {
  202.         /* Check if Tx is working */
  203.         if((UART0->INTEN & UART_INTEN_THREIEN_Msk) == 0)
  204.         {
  205.             /* Send one bytes out */
  206.             UART0->DAT = comTbuf[comThead++];
  207.             if(comThead >= TX_BUFSIZE)
  208.                 comThead = 0;

  209.             comTbytes--;

  210.             /* Enable Tx Empty Interrupt. (Trigger first one) */
  211.             UART_ENABLE_INT(UART0, UART_INTEN_THREIEN_Msk);
  212.         }
  213.     }
  214. }


  215. /*---------------------------------------------------------------------------------------------------------*/
  216. /*  Main Function                                                                                          */
  217. /*---------------------------------------------------------------------------------------------------------*/
  218. int32_t main(void)
  219. {
  220. #if CRYSTAL_LESS
  221.     uint32_t u32TrimInit;
  222. #endif

  223.     /* Unlock protected registers */
  224.     SYS_UnlockReg();

  225.     /* Init System, peripheral clock and multi-function I/O */
  226.     SYS_Init();

  227.     /* Init UART0 to 115200-8n1 for print message */
  228.     UART_Open(UART0, 115200);

  229.     printf("\n\n");
  230.     printf("+--------------------------------------------------------------+\n");
  231.     printf("|     NuMicro USB Virtual COM and HID Media Key Sample Code    |\n");
  232.     printf("+--------------------------------------------------------------+\n");
  233.     printf("Use PD0 to report key - Brightness + when PD0 = 0\n");
  234.     printf("Use PD1 to report key - Brightness - when PD1 = 0\n");
  235.     printf("Use PD2 to report key - Volume + when PD2 = 0\n");
  236.     printf("Use PD3 to report key - Volume - when PD3 = 0\n");
  237.     printf("Use PD4 to report key - Keyboard Brightness + when PD4 = 0\n");
  238.     printf("Use PD5 to report key - Keyboard Brightness - when PD5 = 0\n");
  239.     printf("Use PD6 to report key - Mute when PD6 = 0\n");

  240.     /* Set PD.0 ~ PD.6 as Quasi-bidirectional mode */
  241.     GPIO_SetMode(PD, (BIT0|BIT1|BIT2|BIT3|BIT4|BIT5|BIT6), GPIO_MODE_QUASI);

  242.     /* Open USB controller */
  243.     USBD_Open(&gsInfo, HID_ClassRequest, NULL);

  244.     /* Endpoint configuration */
  245.     HID_Init();

  246.     /* Start USB device */
  247.     USBD_Start();

  248.     g_u8EP5Ready=1;

  249.     NVIC_EnableIRQ(USBD_IRQn);

  250.     NVIC_EnableIRQ(UART02_IRQn);

  251. #if CRYSTAL_LESS
  252.     /* Backup default trim */
  253.     u32TrimInit = M32(TRIM_INIT);
  254. #endif

  255.     /* Clear SOF */
  256.     USBD->INTSTS = USBD_INTSTS_SOFIF_Msk;

  257.     while(1)
  258.     {
  259. #if CRYSTAL_LESS
  260.         /* Start USB trim if it is not enabled. */
  261.         if((SYS->HIRCTRIMCTL & SYS_HIRCTRIMCTL_FREQSEL_Msk) != 1)
  262.         {
  263.             /* Start USB trim only when SOF */
  264.             if(USBD->INTSTS & USBD_INTSTS_SOFIF_Msk)
  265.             {
  266.                 /* Clear SOF */
  267.                 USBD->INTSTS = USBD_INTSTS_SOFIF_Msk;

  268.                 /* Re-enable crystal-less */
  269.                 SYS->HIRCTRIMCTL = 0x01;
  270.                 SYS->HIRCTRIMCTL |= SYS_HIRCTRIMCTL_REFCKSEL_Msk;
  271.             }
  272.         }

  273.         /* Disable USB Trim when error */
  274.         if(SYS->HIRCTRIMSTS & (SYS_HIRCTRIMSTS_CLKERIF_Msk | SYS_HIRCTRIMSTS_TFAILIF_Msk))
  275.         {
  276.             /* Init TRIM */
  277.             M32(TRIM_INIT) = u32TrimInit;

  278.             /* Disable crystal-less */
  279.             SYS->HIRCTRIMCTL = 0;

  280.             /* Clear error flags */
  281.             SYS->HIRCTRIMSTS = SYS_HIRCTRIMSTS_CLKERIF_Msk | SYS_HIRCTRIMSTS_TFAILIF_Msk;

  282.             /* Clear SOF */
  283.             USBD->INTSTS = USBD_INTSTS_SOFIF_Msk;
  284.         }
  285. #endif
  286.         /* Enter power down when USB suspend */
  287.         if(g_u8Suspend)
  288.             PowerDown();

  289.         VCOM_TransferData();

  290.         HID_UpdateKbData();
  291.     }
  292. }



  293. /*** (C) COPYRIGHT 2021 Nuvoton Technology Corp. ***/



 楼主| gaoyang9992006 发表于 2024-4-21 20:40 | 显示全部楼层
123266250923e24c7.png
这个应用很不错,可以做很多电脑外设的应用。
LLGTR 发表于 2024-4-24 23:11 | 显示全部楼层
是同时模拟了虚拟串口和键盘吗?
lidi911 发表于 2024-4-24 23:53 来自手机 | 显示全部楼层
可以做个游戏模拟器玩玩
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:如果你觉得我的分享或者答复还可以,请给我点赞,谢谢。

2053

主题

16420

帖子

222

粉丝
快速回复 在线客服 返回列表 返回顶部