zoukankan      html  css  js  c++  java
  • USB驱动之CDC类的介绍与应用20160905

    USB的协议其实是很复杂的,如果要深入学习估计要一两年才能熟悉透。本文主要是讲如何使用官方已经写好的库进行二次开发,以达到我们自己使用的目的。我们知道USB可以用来接U盘,声卡,读卡器,鼠标键盘等等,这里主要是讲USB接口用来当虚拟串口使用,这个VCP(虚拟串口)是通过USB的CDC(通信设备类)类来实现的,本文是基于CPU是STM32F4的USB来讲解的:

    1.安装和使用STM32 CubeMx软件:

        该软件是STM官方提供的图形化配置底层驱动的软件,可生成工程与代码,可去官方下载安装:

    1)安装后如下界面:

     

    2)接下来再点击菜单栏中的help选择安装库:

     

    我们使用的是F4的底层库,该库为HAL库,不再是以前STM32的标准库,大约到2014年左右,ST在标准库的基础上又推出了HAL库。实际上,HAL库和标准库本质上是一样的,都是提供底层硬件操作API,而且在使用上也是大同小异。有过标准库基础的同学对HAL库的使用也很容易入手。个人认为ST官方之所以这几年大力推广HAL库,是因为HAL的结构更加容易整合STM32Cube,而STM32CubeMX是ST这几年极力推荐的程序生成开发工具。所以这两年新出的STM32芯片,ST直接只提供HAL库。在新型的STM32芯片中,用HAL库逐步淘汰标准库。

    3)选择自己的mcu型号,选择好后双击打开:

     

    4)配置RCC,USB等:

     

    5)配置时钟树,根据自己硬件情况:

     

    6)点击工具栏的生成代码工具,注意填写的堆栈空间要大一点,防止空间不够的意外:

     

    点击OK后生成工程代码,可以下载测试验证,接下我们来分析生成的代码,并修改成自己想要的:

    2.分析与修改代码:

    1)生成的代码我们首先来看,初始化USB功能的

     

    点击其中的Init

     

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

     

    函数在如下文件中:

     

    2)我们修改这个文件:

    首先在里面定义个串口属性的结构体:

    USBD_CDC_LineCodingTypeDef linecoding =

      {

        USB_VIRTUAL_COM_BAUDRATE, /* baud rate*/

        0x00,   /* stop bits-1*/

        0x00,   /* parity - none*/

        0x08    /* nb. of bits 8*/

      };

    然后修改CDC_Control_FS函数:

    {

      /* USER CODE BEGIN 5 */

      switch (cmd)

      {

      case CDC_SEND_ENCAPSULATED_COMMAND:

      break;

     case CDC_GET_ENCAPSULATED_RESPONSE:

      break;

     case CDC_SET_COMM_FEATURE:

      break;

      case CDC_GET_COMM_FEATURE:

      break;

     case CDC_CLEAR_COMM_FEATURE:

     break;

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

      /* 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];

          /* Add your code here */

        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;    

         /* Add your code here */

        break;

     case CDC_SET_CONTROL_LINE_STATE:

     break;

     case CDC_SEND_BREAK:

      break;   

     default:

        break;

      }

    return (USBD_OK);

      /* USER CODE END 5 */

    }

    3)基本配置完毕,接下来就是发送和接收的,发送主要调用CDC_Transmit_FS函数:

     

    示例:

     

    很简单吧,由于我们的USB是从端,PC是主端,这里发送最后是写入到一个BUF里,PC会主动过来查询并读取.

    继续看接收,接收的我们在CDC_Receive_FS函数加入自己的代码即可

     

    示例:

     

    到此,我们就完成了USB的配置,发送,接收等,最后看下效果:

    PC装上stm的官方USB VCP驱动,然后连上电脑:

     

    通信结果OK:

     

  • 相关阅读:
    在列表中添加序号列
    在C#中使用正则表达式
    Git
    Linux 配置Java环境
    讯飞语义理解 JAVA SDK
    分屏显示
    Gdiplus
    重启进程
    MFC 常用功能属性
    MFC 打印
  • 原文地址:https://www.cnblogs.com/yuweifeng/p/5843688.html
Copyright © 2011-2022 走看看