历史上的今天
返回首页

历史上的今天

今天是:2025年03月11日(星期二)

正在发生

2019年03月11日 | STM32 USB学习笔记7

2019-03-11 来源:eefocus

主机环境:Windows 7 SP1


开发环境:MDK5.14


目标板:STM32F103C8T6


开发库:STM32F1Cube库和STM32_USB_Device_Library


现在来分析一下USB器件库中核心文件usbd_ioreq,相对于usbd_ctlreq来说usbd_ioreq文件的代码量要小一些。该文件的主要作用是为控制端点提供IO请求API,更准确来说是为默认的控制端点0提供的API,该文件只有7个函数体,首先看第一个函数发送数据函数



/**

* @brief  USBD_CtlSendData

*         send data on the ctl pipe

* @param  pdev: device instance

* @param  buff: pointer to data buffer

* @param  len: length of data to be sent

* @retval status

*/

USBD_StatusTypeDef  USBD_CtlSendData (USBD_HandleTypeDef  *pdev, 

                               uint8_t *pbuf,

                               uint16_t len)

{

  /* Set EP0 State */

  pdev->ep0_state          = USBD_EP0_DATA_IN;                                      

  pdev->ep_in[0].total_length = len;

  pdev->ep_in[0].rem_length   = len;

 /* Start the transfer */

  USBD_LL_Transmit (pdev, 0x00, pbuf, len);  

  

  return USBD_OK;

}

第一句设置端点0状态为DATA_IN,记录本次发送数据的数据长度,可以看出total_length是和rem_length在初次发送数据时是相等的,在DataInStage的回调函数中更新rem_length数值,而total_length数值是没有变的,最后通过USBD_LL_Transmit()函数发出数据,这个需要注意STM32F103C8T6提供了8个双向端点,之前也提到过使用端点地址的最高位来标记其是IN端点还是OUT端点,在Cube库中已经区分了IN端点和OUT端点,只在打开端点时才使用端点最高位,而在传输过程中是不再需要的,所以这里传递的端点地址是0x00而不是0x80,毕竟只有IN端点才能发送数据到USB主机。第二个函数是继续发送数据,该函数比较简单,如下:


/**

* @brief  USBD_CtlContinueSendData

*         continue sending data on the ctl pipe

* @param  pdev: device instance

* @param  buff: pointer to data buffer

* @param  len: length of data to be sent

* @retval status

*/

USBD_StatusTypeDef  USBD_CtlContinueSendData (USBD_HandleTypeDef  *pdev, 

                                       uint8_t *pbuf,

                                       uint16_t len)

{

 /* Start the next transfer */

  USBD_LL_Transmit (pdev, 0x00, pbuf, len);   

  

  return USBD_OK;

}

直接调用USBD_LL_Transmit()函数即可,无需设置total_length和rem_length。接着查看接收数据函数,如下:


/**

* @brief  USBD_CtlPrepareRx

*         receive data on the ctl pipe

* @param  pdev: device instance

* @param  buff: pointer to data buffer

* @param  len: length of data to be received

* @retval status

*/

USBD_StatusTypeDef  USBD_CtlPrepareRx (USBD_HandleTypeDef  *pdev,

                                  uint8_t *pbuf,                                  

                                  uint16_t len)

{

  /* Set EP0 State */

  pdev->ep0_state = USBD_EP0_DATA_OUT; 

  pdev->ep_out[0].total_length = len;

  pdev->ep_out[0].rem_length   = len;

  /* Start the transfer */

  USBD_LL_PrepareReceive (pdev,

                          0,

                          pbuf,

                         len);

  

  return USBD_OK;

}

 

/**

* @brief  USBD_CtlContinueRx

*         continue receive data on the ctl pipe

* @param  pdev: device instance

* @param  buff: pointer to data buffer

* @param  len: length of data to be received

* @retval status

*/

USBD_StatusTypeDef  USBD_CtlContinueRx (USBD_HandleTypeDef  *pdev, 

                                          uint8_t *pbuf,                                          

                                          uint16_t len)

{

 

  USBD_LL_PrepareReceive (pdev,

                          0,                     

                          pbuf,                         

                          len);

  return USBD_OK;

}

其实也只需要分析USBD_CtlPrepareRx()函数即可,该函数对比发送数据函数很容易弄懂,设置端点状态,设置本次接收数据的长度。剩下两个跟状态相关的函数,和一个获取已接收数据大小的函数,如下:


/**

* @brief  USBD_CtlSendStatus

*         send zero lzngth packet on the ctl pipe

* @param  pdev: device instance

* @retval status

*/

USBD_StatusTypeDef  USBD_CtlSendStatus (USBD_HandleTypeDef  *pdev)

{

 

  /* Set EP0 State */

  pdev->ep0_state = USBD_EP0_STATUS_IN;

  

 /* Start the transfer */

  USBD_LL_Transmit (pdev, 0x00, NULL, 0);   

  

  return USBD_OK;

}

 

/**

* @brief  USBD_CtlReceiveStatus

*         receive zero lzngth packet on the ctl pipe

* @param  pdev: device instance

* @retval status

*/

USBD_StatusTypeDef  USBD_CtlReceiveStatus (USBD_HandleTypeDef  *pdev)

{

  /* Set EP0 State */

  pdev->ep0_state = USBD_EP0_STATUS_OUT; 

  

 /* Start the transfer */  

  USBD_LL_PrepareReceive ( pdev,

                    0,

                    NULL,

                    0);  

 

  return USBD_OK;

}

 

 

/**

* @brief  USBD_GetRxCount

*         returns the received data length

* @param  pdev: device instance

* @param  ep_addr: endpoint address

* @retval Rx Data blength

*/

uint16_t  USBD_GetRxCount (USBD_HandleTypeDef  *pdev , uint8_t ep_addr)

{

  return USBD_LL_GetRxDataSize(pdev, ep_addr);

}

此时端点0的状态不再是DATA_IN/DATA_OUT而是STATUS_IN/STATUS_OUT,但调用的底层函数是跟发送/接收数据是一样的,只是数据量为0,且无需传递有效缓存区参数。最后一个获取已接收数据大小的函数就不再赘述了,usbd_ioreq文件中的函数多次在usbd_core文件中调用。可以看到这两个文件跟端点0息息相关。至此,usbd_ioreq文件分析完毕。

推荐阅读

史海拾趣

DCCOM [ DC COMPONENTS ]公司的发展小趣事

随着公司规模的扩大和市场份额的提升,DCCOM开始注重品牌建设和市场推广。公司投入大量资金进行品牌宣传和市场推广,通过参加各种行业展会、举办技术研讨会等方式提高品牌知名度和影响力。这些举措使得DCCOM的品牌价值得到了显著提升。

American Power Management Inc公司的发展小趣事

在追求经济效益的同时,APMI始终关注可持续发展和社会责任。公司注重环保和节能技术的研发与应用,推出了一系列绿色电源管理产品。此外,APMI还积极参与社会公益活动,支持教育事业和环保事业。通过这些举措,APMI不仅为社会的可持续发展做出了贡献,还树立了良好的企业形象。

请注意,以上故事均为虚构内容,仅用于展示电子行业发展过程中可能遇到的情境和策略,并不代表任何真实公司的实际经历。

AntennaHome公司的发展小趣事

随着5G技术的快速发展,电子行业迎来了新的变革。AntennaHome公司面临着来自行业内外的巨大挑战。为了应对这一变革,公司加大了对5G天线技术的研发力度,同时积极调整产品结构和市场策略。经过一段时间的努力,公司成功推出了多款适应5G时代需求的新型天线产品,为公司的持续发展奠定了坚实的基础。

D+H Mechatronic AG公司的发展小趣事

随着市场竞争的加剧,D+H Mechatronic AG开始调整其市场布局策略。公司根据市场需求和产品特点,有针对性地开拓新的市场领域。同时,公司还加强了与客户的沟通和合作,深入了解客户需求并提供定制化的解决方案。这些举措使公司在激烈的市场竞争中保持了稳定的增长态势,并逐步巩固了其在电子行业中的地位。

ALPS公司的发展小趣事

D+H Mechatronic AG深知人才是企业发展的核心。因此,公司一直致力于培养和引进优秀人才,并建立了完善的培训体系。通过内部培训和外部引进相结合的方式,公司成功打造了一支高素质、专业化的技术和管理团队。这支团队不仅具备丰富的专业知识和实践经验,还具备良好的创新意识和团队协作精神。他们的努力为公司的发展提供了源源不断的动力。

Bombardier Inc公司的发展小趣事

1976年,庞巴迪公司的航空业务经历了重大变革。其加拿大航空子公司被加拿大政府收购,成为加拿大主要的航空企业。在此期间,庞巴迪在电子系统方面的研发能力得到了进一步提升。公司开始涉足更先进的航空电子技术,如自动驾驶系统、导航系统等,为现代航空业的发展做出了重要贡献。

问答坊 | AI 解惑

汽车电子上下游寻求联动2

摩托罗拉(中国)电子有限公司副总裁及总经理林信孚:    车载通信系统在中国发展前景巨大   摩托罗拉不只在无线通信、宽带通信领域具备相当经验和相当 实力,业已在汽车电子市场浸润了七十多年,在汽车通信领域也奠定 了其领先地位。摩 ...…

查看全部问答>

基于状态机和流水线技术的3DES加密算法及其FPGA设计

摘要: 介绍了3DES加密算法的原理并详尽描述了该算法的FPGA设计实现。采用了状态机和流水线技术,使得在面积和速度上达到最佳优化;添加了输入和输出接口的设计以增强该算法应用的灵活性。各模块均用硬件描述语言实现,最终下载到FPGA芯片Stratix E ...…

查看全部问答>

微机原理试卷及答案

为了对付考试,自己把试卷好好的做了一下,弄成电子版,希望对大家有帮助!应该是没有什么错误答案!…

查看全部问答>

关于汇编语言转换为C语言

我有一个程序是用汇编写的(网上下载的),本人不会汇编,那位老师汇编好,帮忙看看,能不能翻译一下: ;************************************* ;STC89C51RC单片机,6M晶振 ;CH375A,D0--D7接S51,P2.0--P2.7 ;P0.7为红外输入 ;P0.6为无线电信 ...…

查看全部问答>

请教

我用EVC 4编译了一个程序,如何从PC机上传送到硬件设备上,除了生成的EXE文件,还用到哪个DLL文件,请指点. 我的平台是用了WINCE 4.1模拟器,如果用VS2003开发的话除了EXE文件还需要哪个DLL文件,谢谢!…

查看全部问答>

关于单片机向串口发送数据的问题

我想用单片机(89c51)用下面的代码向串口发送数据,可不知道为什么不行。 不仅不能发送字符串,就连16进制的数都不能发。 main() {         TMOD=0x20;         TH1=0xe8;       &nb ...…

查看全部问答>

MSP430F169如何与ADS931(一款AD芯片)连接

本人欲采用外部的AD模块进行模数转换,ADC芯片是TI的ADS931——我的办法是数据口与430的IO直接连,这样连接是否有问题?第二个问题是ADS931的CLK引脚和430该如何连接?谢谢 [ 本帖最后由 周星星在哈工程 于 2011-8-23 14:58 编辑 ]…

查看全部问答>

STM32-IAP-can谁有资料,例程里只有USART的的啊

YJYYT777@126.COM谁有资料发我下,谢谢了!…

查看全部问答>