历史上的今天
返回首页

历史上的今天

今天是:2025年07月29日(星期二)

正在发生

2019年07月29日 | 单片机-stm32-使用cdc类实现vcp(虚拟串口)

2019-07-29 来源:eefocus

本文所述内容基于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


https://images2015.cnblogs.com/blog/964489/201609/964489-20160905212643629-492023453.png?imageView2/2/w/550


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


其中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 irn";

 

    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函数了


推荐阅读

史海拾趣

Displaytech公司的发展小趣事

Displaytech公司成立于1989年,作为一家LCD模块供应商在香港崭露头角。当时,液晶显示技术正逐渐崭露头角,Displaytech凭借其敏锐的市场洞察力和技术实力,迅速在市场中占据了一席之地。公司初期专注于小型到中型LCD的制造,为工业、消费和医疗行业的客户提供高质量的产品和技术支持。

Euroquartz公司的发展小趣事

Euroquartz自创立之初,就将产品质量和客户满意度置于公司运营的核心。为了确保这一点,公司引入了完整的AS9100 Rev D质量体系,并通过了相应的认证。这一体系要求Euroquartz在制造程序和可追溯性方面保持完整的记录,审批机关会定期进行审核,确保品质始终如一。这种对品质的执着追求,为Euroquartz赢得了客户的信赖,也为公司的发展奠定了坚实的基础。

General Cable公司的发展小趣事
根据应用需求,将YN5103的数据和控制引脚连接到相应的输入或输出设备。例如,数据引脚可能连接到微控制器或其他数据源,控制引脚可能用于接收外部控制信号。
Amphenol Aerospace公司的发展小趣事
在编码电路中,可能需要通过调整相关元件(如电阻、电容等)的参数来精确设置时钟频率,进而实现所需的载波频率。
American Micro Products Inc公司的发展小趣事

随着产品线的不断丰富,AMP开始积极寻求市场拓展的机会。公司通过与国内外知名企业的战略合作,成功将产品打入更广阔的市场。同时,AMP还积极参加各类行业展会和论坛,与业界同仁交流学习,不断提升自身的市场竞争力。

Avic公司的发展小趣事

随着Avic公司在航空电子技术领域的不断发展和创新,其产品在国内外市场上的竞争力日益增强。公司成功拓展了国内外市场,市场份额稳步增长。这不仅体现了公司在航空电子领域的实力,也为中国航空工业的整体发展做出了积极贡献。

这五个故事虽然不能完全涵盖Avic公司在电子行业发展的所有细节,但希望能通过概括性的描述,为您展现该公司在这一领域的重要发展历程和取得的成就。需要注意的是,这些故事是基于公开资料和已知事实进行描述的,旨在客观呈现事实,而非进行主观评价。

问答坊 | AI 解惑

关于SD卡的MBR问题

有的SD卡的第0 sector是MBR, 有的SD卡的第0 sector是DBR,请问如何区分两者?…

查看全部问答>

InterruptInitialize 出错问题~!

我在注册中断的时候碰到一个奇怪的问题。 先用 if(!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &EINT_IRQ, sizeof(UINT32), &EINT_SYSINTR, sizeof(UINT32), NULL)) {    RETAILMSG(1, (TEXT(\"[kbd] ERROR:  Failed to ...…

查看全部问答>

承接WinCE外包项目

本人有丰富的WindowCE应用开发经验,现承接Windows CE/Mobile平台上的应用外包项目,质量保证。有意者请与我联系: QQ:17632892 MSN:kerlw@hotmail.com…

查看全部问答>

请教UART控制器中Modem功能的测试(急)

请教各位达人: 我想测试一下芯片中UART的Modem功能,请问应该如何测试?测试环境应该如何搭建啊?是不是需要通过串口和Modem相连?AT指令怎么测试?是通过串口发给Modem吗? 谢谢! …

查看全部问答>

数据库和嵌入式

我们学校就要分方向了。。。有数据库和嵌入式。。。 请各位大虾指点下。。这两个方向的应用方面和现今社会需求那方面的人才要些。。。。 清大虾们给我点小小的建议。。。谢谢!!!!!!!…

查看全部问答>

触摸品伪驱动的开发

我需要实现全屏手写的功能,目前为止得到的方法就是要自己写一个触摸屏的驱动,因为系统本身就有一个touch.dll,所以我其实只是做了一个包装,把touch.dll的函数用GetProcAddress得到后在调用,只是修改了TouchPanelEnable函数,可是编译出来的dll ...…

查看全部问答>

请教linux下读写 gpio端口控制寄存器的方法

我用的是s3c2410的开发板,linux操作系统,我知道在arm下读写io要用/dev/port,但是 相应io的控制寄存器如何读写,是否也是用port文件,同样的方法? 下面直接读取的方法应该不行吧:     先用gpio(1-5)试试,这其中对应的引脚是GPG0 ...…

查看全部问答>

紧急求助

我想问一下,如果直接输出3.3V,那么是不是就可以直接用纽扣电池,不需要再用TPS70633芯片转换了呀…

查看全部问答>

快比赛了

本帖最后由 paulhyde 于 2014-9-15 09:06 编辑 就快要比赛了,可是却不知道该干什么了。不知道大家现在都在干什么啊?今天看了部电影,可之后突然感觉,心里很是放心不下啊  …

查看全部问答>

这套号称最低成本的方案,哪些兄弟再用啊

本帖最后由 jameswangsynnex 于 2015-3-3 19:59 编辑 有7月初参加过茁壮和富士通的高清机顶盒推广活动的兄弟举举手,MB86H61+iPanel3.0大家都有用起来了吗?300块的整转成本实现了吗?话说今年的高清整体转移启动年来着,都快年底了,目前动静不是 ...…

查看全部问答>