单片机-stm32-使用cdc类实现vcp(虚拟串口)

本文所述内容基于STM32 HAL库完成

安装stm32CubeMx(ver4.26.0)

新建工程,选择stm32f412zg tx

配置RCC->HSE->crystal/Ceramic Resonnator

配置USB_OTG_FS->device only(disable Activate_VBUS)

配置MiddleWares->USB_DEVICE->communication device class(virtual Port com)

配置clock,input frequency设置为8Mhz

单片机-stm32-使用cdc类实现vcp(虚拟串口)_第1张图片

其他参数全部默认,生成代码

其中USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);是关键,主要的功能是把CDC类的功能和我们用户要调用的_fops_FS函数都注册到USB的设备类里,这样在USB内核运行的时候就会调动我们注册进去的函数,点击USBD_Interface_fops_FS进去,这里面的函数指针 指向的函数就是我们需要使用和修改的了

 

 

 

找到CDC_Control_FS所在的文件usbd_cdc_if.c,添加如下代码

 

USBD_CDC_LineCodingTypeDef linecoding =

  {

    115200, /* baud rate*/

    0x00,   /* stop bits-1*/

    0x00,   /* parity - none*/

    0x08    /* nb. of bits 8*/

  };

 

在函数CDC_Control_FS中增加如下代码

 

  /*******************************************************************************/

  /* Line Coding Structure                                                       */

  /*-----------------------------------------------------------------------------*/

  /* Offset | Field       | Size | Value  | Description                          */

  /* 0      | dwDTERate   |   4  | Number |Data terminal rate, in bits per second*/

  /* 4      | bCharFormat |   1  | Number | Stop bits                            */

  /*                                        0 - 1 Stop bit                       */

  /*                                        1 - 1.5 Stop bits                    */

  /*                                        2 - 2 Stop bits                      */

  /* 5      | bParityType |  1   | Number | Parity                               */

  /*                                        0 - None                             */

  /*                                        1 - Odd                              */

  /*                                        2 - Even                             */

  /*                                        3 - Mark                             */

  /*                                        4 - Space                            */

  /* 6      | bDataBits  |   1   | Number Data bits (5, 6, 7, 8 or 16).          */

  /*******************************************************************************/

    case CDC_SET_LINE_CODING:

      linecoding.bitrate    = (uint32_t)(pbuf[0] | (pbuf[1] << 8) |\

        (pbuf[2] << 16) | (pbuf[3] << 24));

      linecoding.format     = pbuf[4];

      linecoding.paritytype = pbuf[5];

      linecoding.datatype   = pbuf[6];

      break;

 

    case CDC_GET_LINE_CODING:

      pbuf[0] = (uint8_t)(linecoding.bitrate);

      pbuf[1] = (uint8_t)(linecoding.bitrate >> 8);

      pbuf[2] = (uint8_t)(linecoding.bitrate >> 16);

      pbuf[3] = (uint8_t)(linecoding.bitrate >> 24);

      pbuf[4] = linecoding.format;

      pbuf[5] = linecoding.paritytype;

      pbuf[6] = linecoding.datatype;

      break;

 

    case CDC_SET_CONTROL_LINE_STATE:

 

    break;

调用CDC_Transmit_FS,即可以实现USB虚拟串口的功能,示例代码如下

int main(void)

{

  /* USER CODE BEGIN 1 */

    char buf_2[]=" who am i\r\n";

    uint8_t cnt=0;

  /* USER CODE END 1 */



  /* MCU Configuration----------------------------------------------------------*/



  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init();



  /* USER CODE BEGIN Init */



  /* USER CODE END Init */



  /* Configure the system clock */

  SystemClock_Config();



  /* USER CODE BEGIN SysInit */



  /* USER CODE END SysInit */



  /* Initialize all configured peripherals */

  MX_GPIO_Init();

  MX_USB_DEVICE_Init();

  /* USER CODE BEGIN 2 */



  /* USER CODE END 2 */



  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {



    /* USER CODE END WHILE */

    //if(cnt<10)

    {

        buf_2[0] = cnt;

        CDC_Transmit_FS(buf_2,strlen(buf_2));

        HAL_Delay(100);

        cnt++;

    }

  /* USER CODE BEGIN 3 */

  }

  /* USER CODE END 3 */

}

 

为了方便使用,可以重载printf函数如下,

#ifdef __GNUC__
/* With GCC, small printf (option LD Linker->Libraries->Small printf
   set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
    /* Place your implementation of fputc here */
    /* e.g. write a character to the USART3 and Loop until the end of transmission */
    //CDC_Transmit_FS((uint8_t *)&ch, 1);
    while(CDC_Transmit_FS((uint8_t*)(&ch),1)!=USBD_OK){}

    return ch;
}

 

然后就可以在函数里方便的调用printf函数了

你可能感兴趣的:(单片机开发)