历史上的今天

今天是:2024年11月10日(星期日)

2020年11月10日 | USB通讯的执行过程 - STM32 USB设计

发布者:caoda143 来源: eefocus关键字:USB通讯  执行过程  STM32  USB设计 手机看文章 扫描二维码
随时随地手机看文章

  首先,我们来看看usb的工作过程。


  当usb设备接入到主机时,主机开始枚举usb设备,并向usb设备发出指令要求获取usb设备的相关描述信息,其中包括设备描述(device descriptor)、配置描述(configuration descriptor)、接口描述(interface descriptor)、端点描述(endpoint descriptor)等。这些信息是通过端点0(endpoint 0)传送到主机的。获取各种描述信息后,操作系统会为其配置相应的资源。这样主机就可以与设备之间进行通信了。


  usb通讯有四种通讯方式控制(control)、中断(interrupt)、批量(bulk)和同步( synchronous)。usb通讯是通过管道(pipe)实现的。管道是一个抽象的概念,指的是主机与设备之间通讯的虚拟链路。不如说一个usb通讯 主机A和设备B,其中有bulk in(批量输入)、bulk out(批量输出)、control out(控制输出)三种通讯方式,那么A与B之间的通讯管道就有三个。(这里明确一个概念,在usb通信中数据流向都是相对设备来说的,in表示设备向主 机传送数据,out表示表示主机箱设备传输数据)。在设备一端,每个管道对应一个端点,端点配置相关的寄存器和缓冲区。在通讯之前需对端点进行相关设置。 在通信中,只需向缓冲写或读数据,并置位相关比特位即可。


  下面具体从usb的中断输入输出来讲述基于keil C mdk开发环境的stm32的USB接口单片机程序设计。值得一提的是,st或相关公司给我们提供许多封装函数和相关例子,我们可以根据其中的例子并进行修改即可实现我们自己需要的usb通讯程序。


  1.usb描述符配置

  从上面的讲述可以看出,usb描述符是usb通讯的前提。主机必须先了解设备后才能与其进行通讯。在st提供的例子中,描述符都在usb_des.c文件进行定义,下面就其中的Joystick例子说明usb描述负的配置。


  1.1设备描述符

  const u8 Joystick_DeviceDescriptor[JOYSTICK_SIZ_DEVICE_DESC] =

  {

  0x12, /*本描述长度*/

  USB_DEVICE_DESCRIPTOR_TYPE, /*指明为设备描述符*/

  0x00,

  0x02,

  0x00,

  0x00,

  0x00,

  0x40, /*最大数据包大小为64字节(对于端点0而言)*/

  0x84, /*生产商ID*/

  0x19,

  0x06, /*产品ID*/

  0x04,

  0x00,

  0x02,

  1,

  2,

  3,

  0x01 /*配置描述符数目*/

  }


  设备描述符两个重要参数是生产商ID和产品ID,主机将根据以上两个ID为设备选择相应驱动程序。在我们的应用中,我们一般只需修改例子中的这儿两个参数即可完成设备描述符的设置。


  1.2配置描述符

  const u8 Joystick_ConfigDescriptor[JOYSTICK_SIZ_CONFIG_DESC] =

  {

  0x09,

  USB_CONFIGURATION_DESCRIPTOR_TYPE,

  JOYSTICK_SIZ_CONFIG_DESC,

  0x00,

  0x01, /*接口数目*/

  0x01, /*Set_Configuration命令所需要的参数值*/

  0x00, /*描述该配置的字符串的索引值*/

  0xE0, /*供电模式的选择,bus供电、自供电、支持wakeup*/

  0x32, /*最大供电电流*/

  /************** 接口1配置****************/

  0x09,

  USB_INTERFACE_DESCRIPTOR_TYPE,

  0x00, /*接口编号*/

  0x00,

  0x02, /*端点数*/

  0x00,

  0x00,

  0x00,

  0, /*接口描述符索引值*/

  /******************** 端点1输出描述********************/

  0x07,

  USB_ENDPOINT_DESCRIPTOR_TYPE,

  0x81, /*端点地址,b.7表示方向(1为in,0为out)b.0-b.3为端点标号*/

  0x03, /*端点数据传输方式*/

  0x08, /*最大数据包大小*/

  0x00,

  0x20,

  /******************** 端点1输入描述********************/

  0x07,

  USB_ENDPOINT_DESCRIPTOR_TYPE,

  0x01, /*端点地址*/

  0x03, /*端点数据传输方式*/

  0x40, /*最大数据包大小*/

  0x00,

  0x20,

  }


  配置描述符中包括了接口、端点的配置。如果设备为HID设备,在配置描述符中还应加入HID描述,具体描述可以参照Joystick例子的配置。


  还有一些其他配置可以参可相关资料与例子加以理解。


2、USB通讯的执行过程。

  首先,当主机数据传送到USB设备,USB怎样接收命令和数据呢?USB首先会产生一个中断,这个中断在stm32fxxx_it.c文件的 USB_HP_CAN_TX_IRQHandler和USB_LP_CAN_RX0_IRQHandler中定义,一般使用 USB_LP_CAN_RX0_IRQHandler。在这个函数中继续调用USB_Istr()函数,这个函数是usb通讯的关键。它接收到主机命令, 指派调度相应函数进行处理。对于这一点,详细过程我现在还不是很明白。如果以后搞懂了再补述。


  当USB设备接入主机时,主机要枚举该USB设备,他将要求USB设备提供自身相关信息,这是通过endpoint0实现的。endpoint0是 一个特殊的端点,每一个接口(interface)必须有endpoint0。一般情况下,我们需要使用多个端点(如前所述,配置描述符定义了端点的数 目、类型、传输数据大小等)。在使用端点前需对端点进行初始化。这个过程在usb_prop.c文件中的xxx_reset()函数定义。如我定义端点1 的两种传输方式:

  /* Initialize Endpoint 1 */

  SetEPType(ENDP1, EP_INTERRUPT);

  SetEPRxAddr(ENDP1, ENDP1_RXADDR);

  SetEPRxCount(ENDP1, 8);

  SetEPRxStatus(ENDP1, EP_RX_VALID);

  /* Initialize Endpoint 1 */

  SetEPType(ENDP1, EP_INTERRUPT);

  SetEPTxAddr(ENDP1, ENDP1_TXADDR);

  SetEPTxCount(ENDP1, 64);

  SetEPTxStatus(ENDP1, EP_TX_NAK);

  在定义完端点后,我们就可以使用端点进行数据传输了。

  向主机输入数据(in):IN传输过程是

  1.向缓冲区填入数据;

  2.设定USB数据计数器:

  3.设置USB输出有效。

  XXX_send()

  {

  /*copy mouse position info in ENDP1 Tx Packet Memory Area*/

  UserToPMABufferCopy(sendBuffer, ENDP1_TXADDR, 2); /*sendBuffer为要输出的数据,ENDP1_TXADDR端点1的向外传输缓冲区,2为数据大小byte为单位*/

  SetEPTxCount(ENDP1, 2);

  /* enable endpoint for transmission */

  SetEPTxValid(ENDP1);

  }

  注意一般情况下,端点的输入输出缓冲区地址没有定义,须在usb_conf.h中定义具体定义可以参考端点0的定义。

  读从主机输出的数据(out):out传输过程是

  1.定义out回调函数;

  2.从缓冲区读出数据:

  3.设置USB输入有效。

  void EP1_OUT_Callback(void)

  {

  u8 DataLen;

  DataLen = GetEPRxCount(ENDP1);

  PMAToUserBufferCopy(rcvData, ENDP1_RXADDR, DataLen);

  SetEPRxValid(ENDP1);

  }


  注意在一般情况下,EPX_OUT_Callback()回调函数的申明为空执行函数。需将usb_conf.h中#define EPX_IN_Callback NOP_Process隐掉。再在合适的地方从新定义void EP1_OUT_Callback(void)(合适的位置是指定义之后运行不会出现EP1_OUT_Callback为申明的错误就行)。


  总结,在此将stm32芯片的usb通讯进行了简单的阐述。本人水平有限,以上难免会有错误,希望大家积极留言,共同探讨,共同进步。这篇文章是断 断续续写的,给大家带来不便,在此向大家道歉了。不管怎样希望这篇文章能够对那些还在对stm32usb编程初步摸索的朋友有一点帮助。


关键字:USB通讯  执行过程  STM32  USB设计 引用地址:USB通讯的执行过程 - STM32 USB设计

上一篇:基于STM32的USB枚举过程学习笔记
下一篇:深入解析STM32_USB-FS-Device_Lib库V0.2

推荐阅读

        集微网消息(文/小如)11月8日,在无锡金秋经贸会上,滨湖签约项目58个,覆盖集成电路设计、信息技术、智能制造等领域,总投资达695.52亿元。        据中国江苏网报道,此次成功签约落户的项目,产业结构不断优化的主线尤为突出。签约项目包括,360物联网安全运营总部、奥迪中国研发中心等项目、联东U谷产业园、天基通讯、英恒电...
(文章来源:中科罗伯特机器人学院) 工业机器人技术的研究是大量学科相互交融促进并快速发展的过程,通过人机协作、人工智能和仿生结构等多种技术的创新,才铸就了现在我们所看到的工业机器人。但工业机器人的技术从未停止发展的步伐,它正快速拓展到人类生活的每一个地方,这不仅是对人类,也是对机器人来说这都是一个全新的挑战。机器人的发展为我们...
芯片是信息技术产业链中的重要基石,也是我国落后于国际水平的技术领域之一。发展自主可控的芯片技术,并打破 Intel、高通、Arm等巨头在芯片技术上的垄断,已成为当下亟待解决的问题。作为软硬件的接口的处理器指令集,是构建芯片生态和发展芯片技术的核心部分,其重要性不言而喻。在此背景下,RISC-V有望成为新的选择。尽管具有通用、开放与免费的先期优...
为了使用32.768 kHz 钟表晶体作为器件的时钟源,必须将熔丝位CKSEL 设置为“1001” 以选择低频晶体振荡器。晶体的连接方式如 Figure 19 所示。通过对熔丝位CKOPT 的编 程,用户可以使能XTAL1 和XTAL2 的内部电容,从而去除外部电容。内部电容的标称数 值为36 pF。选择了这个振荡器之后,启动时间由熔丝位SUT 确定,如Table 10 所示。Note:...

史海拾趣

问答坊 | AI 解惑

问题: 输入电压为50V,输出电压为12V,工作电流为800MA的电源电路如何设计???

输入电压为50V,输出电压为12V,工作电流为800MA的电源电路如何设计,有现成的芯片吗?请赐教. …

查看全部问答∨

精确控制DDS输出信号幅度的一种新方法

DDS技术作为一种先进的直接数字频率合成技术,用数字控制的方法从一个频率基准源产生多种频率,具有高可靠性、高集成度、高频率分辨率及频率变化快、控制灵活等特点,在通信与仪表领域得到了广泛的应用。采用DDS芯片制作的信号源,输出信号的频率和 ...…

查看全部问答∨

哥们发几个液晶的资料

哥们发几个液晶的资料,需要的朋友可以看看,不要芯币,真的不要啊.从本年5月11日起,我发资料就已经不再收取芯币了.我说话算话.我可不像像某些人,一个小资料就要好几个芯币!都是贫民出身,谁不知道没钱的苦和挣钱的难啊..大家说是吧?...... [ 本帖最后 ...…

查看全部问答∨

PXA270 BVDMAIN的BSP问题!

这个BVDMAIN的BSP好像是4.2下面移植过来的吧,我在使用的时候遇到很多问题。 USB鼠标,部分能够支持,绝大部分不能使用。 SD卡,经常不能识别 请问有人遇到过这样的问题吗? 帮忙解决一下啊,谢谢…

查看全部问答∨

有谁能够把这个问题说明白?

我们都知道,在下载WINCE镜像的时候,是由eboot来驱动网卡通过网络下载,然而,当下载的镜像启动后,需要向这个目标平台下载 EVC应用程序运行时是否还是利用eboot来下载的?…

查看全部问答∨

单片机读写U盘,USBHOST代码

由于无法上传附件,所以请有需要此代码的朋友加我的 QQ1023003927 …

查看全部问答∨

100分,COM口 怎么向三菱PLC发命令啊?

COM口 怎么向三菱PLC发命令啊?我设置好了D8120=0806,d但按照里面的格式来用com精灵向plc发指令,好像都没有反应,想大侠们提供完整的步骤。发16进制要加0x吗?怎么写那些要发送的命令呢…

查看全部问答∨

wince5 模拟器上能否使用sqlce?

sqlce如何使用?我安装了sql ce3.5,里面自带一个Northwind.sdf,可以用vs2008打开。 那我如何自己创建一个后缀名为.sdf的数据库呢? 在模拟器中如果能够使用sqlce,怎么使用?…

查看全部问答∨

sdk:按钮自绘

自己createwindow一个按钮,指定了BS_OWNERDRAW属性,为什么wm_drawitem却不响应?…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved