[应用相关] STM32-custom usb

[复制链接]
2404|44
 楼主| 欢乐家园 发表于 2021-2-22 22:20 | 显示全部楼层
在两根”/*——*/“中间的代码是最重要的,我们根据配置描述可知,端点1作为输出端点,端点2作为输入端点,所以在Reset函数中需要对端点进行初始化:端点0在USB枚举阶段作为通讯的端点,要配置成控制端点,收发有效;端点1配置成中断传输端点,端点接收有效,发送无效;端点2配置成中断传输端点,端点发送有效。
 楼主| 欢乐家园 发表于 2021-2-22 22:21 | 显示全部楼层
我们在之前关于数据收发流程中说到,数据接收的流程: USB_LP_CAN1_RX0_IRQHandler—>USB_Istr—->CTR_LP—>EPx_OUT_Callback。所以我们这里首先需要定义USB中断服务程序 USB_LP_CAN1_RX0_IRQHandler,再还要编写端点接收回调函数: EPx_OUT_Callback函数。
 楼主| 欢乐家园 发表于 2021-2-22 22:21 | 显示全部楼层
在hw_config.c中编写USB中断配置函数:
 楼主| 欢乐家园 发表于 2021-2-22 22:22 | 显示全部楼层
  1. C_InitStructure.NVIC_IRQChannel = OTG_FS_WKUP_IRQn;
  2. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  3. NVIC_Init(&NVIC_InitStructure);  
  4. #else
  5. /* Enable the USB interrupt */
  6. NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;  //设置USB中断服务程序
  7. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  8. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  9. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  10. NVIC_Init(&NVIC_InitStructure);

  11. #endif /* STM32F10X_CL */

  12. }


  13.   
 楼主| 欢乐家园 发表于 2021-2-22 22:23 | 显示全部楼层
我们这里只配置 USB_LP_CAN1_RX0_IRQn这个中断,接着在stm32f10x_it.c中编写 USB_LP_CAN1_RX0_IRQHandler()函数:
 楼主| 欢乐家园 发表于 2021-2-22 22:24 | 显示全部楼层
  1. void USB_LP_CAN1_RX0_IRQHandler(void)
  2. {
  3.   USB_Istr();
  4. }


  5.    
 楼主| 欢乐家园 发表于 2021-2-22 22:24 | 显示全部楼层
这个中断服务程序只调用USB_Istr()函数。经过这个函数的处理,最终程序会执行到 EPx_OUT_Callback函数,由于我们使用端点1作为接受数据的端点,所以我在usb_endp.c中编写 EP1_OUT_Callback()函数:
 楼主| 欢乐家园 发表于 2021-2-22 22:25 | 显示全部楼层
  1. /*******************************************************************************
  2. * Function Name  : EP1_OUT_Callback.
  3. * Description    : 端点1输出回调函数
  4. * Input          : None.
  5. * Output         : None.
  6. * Return         : None.
  7. *******************************************************************************/
  8. void EP1_OUT_Callback(void)
  9. {
  10. #ifndef STM32F10X_CL
  11. PMAToUserBufferCopy(USB_Receive_Buffer, ENDP1_RXADDR, REPORT_COUNT); //PMA缓冲区接收到的数据拷贝到用户自定义缓冲区USB_Receive_Buffer中
  12.      SetEPRxStatus(ENDP1, EP_RX_VALID);                                     //设置端点的接收状态为有效,因为端点接收到数据后会端点状态自动设置成停止状态
  13.      USB_Received_Flag=1;                                                 //设置接收到数据标志位
  14. #else
  15. USB_SIL_Read(EP1_OUT,USB_Receive_Buffer);                            //读取输出端点的数据到USB_Receive_Buffer中
  16. USB_Received_Flag=1;                                                 //收到数据的标志
  17. #endif
  18. }


  19.    
 楼主| 欢乐家园 发表于 2021-2-22 22:25 | 显示全部楼层
这个函数起始很简单,从端点缓冲区中读取数据,保存在 USB_Receive_Buffer[]数组中,到时候,可以直接拿这个数组进行数据操作了。
 楼主| 欢乐家园 发表于 2021-2-22 22:26 | 显示全部楼层
我们还有编写一个端点发送函数:USB_SendData()。我在自己建的usb_io.c文件中,编写该函数:
 楼主| 欢乐家园 发表于 2021-2-22 22:27 | 显示全部楼层
  1. /*******************************************************************************
  2. * Function Name  : EP1_IN_Callback.
  3. * Description    : USB向主机发送数据
  4. * Input          : None.
  5. * Output         : None.
  6. * Return         : None.
  7. *******************************************************************************/
  8. uint32_t USB_SendData(uint8_t *data,uint32_t dataNum)
  9. {
  10. #ifndef STM32F10X_CL
  11. //将数据通过USB发送出去
  12. UserToPMABufferCopy(data, ENDP2_TXADDR, dataNum); //拷贝dataNum个数据到PMA中
  13. SetEPTxCount(ENDP2, REPORT_COUNT);                    //从端点2发送64字节数据
  14. SetEPTxValid(ENDP2);                              //使能端点2的发送状态
  15. #else
  16. USB_SIL_Write(EP2_IN, data, dataNum);
  17. #endif
  18. return dataNum;  
  19. }

 楼主| 欢乐家园 发表于 2021-2-22 22:28 | 显示全部楼层
依旧很简单,只要来那个要发送的数据包写入端点的缓冲区中,再使能下短短,数据就看可以发送出去了、
 楼主| 欢乐家园 发表于 2021-2-22 22:29 | 显示全部楼层
最后,我们来编写我们的main函数:
 楼主| 欢乐家园 发表于 2021-2-22 22:30 | 显示全部楼层
  1. /********************************************************
  2. 函数:main()
  3. 描述:程序入口地址
  4. 参数:无
  5. 返回:无
  6. ********************************************************/
  7. int main(void)
  8. {  
  9. uint8_t data[64];
  10. uint32_t i=0,ret=0;
  11. BSP_Init();
  12. printf(” |===============================================|\r\n”);
  13. printf(”                USB CustomHID 程序开始           \r\n”);
  14. printf(“|===============================================|\r\n”);
  15. while(1)
  16. {
  17.      if(USB_Received_Flag)
  18.      {
  19.          USB_Received_Flag=0;
  20.          ret = USB_GetData(data,sizeof(data));         //读取数据
  21.          printf(“usb get data %d byte data\r\n”,ret);    //答应接收到的字节数
  22.          for(i=0;i<ret;i++){
  23.              printf(“0x%02X “,data[i]);        //答应接收到的数据
  24.          }
  25.          printf(“\n\r”);
  26.          USB_SendData(data,sizeof(data));      //发送接收到的数据
  27.      }   
  28. }
  29. }

 楼主| 欢乐家园 发表于 2021-2-22 22:32 | 显示全部楼层
主函数的意思是,USB设备接收到什么数据,就向USB主机发送什么数据,并且在串口打印出收到的数据。
drer 发表于 2021-3-4 07:32 | 显示全部楼层
主要的难题是调试
gwsan 发表于 2021-3-4 07:33 | 显示全部楼层
许多需要注意的点都提出来了
kxsi 发表于 2021-3-4 07:34 | 显示全部楼层
如果不识别 怎么处理呢
nawu 发表于 2021-3-4 07:36 | 显示全部楼层
出问题的时候 如何判定是硬件还是软件引起的问题呢
qcliu 发表于 2021-3-4 07:37 | 显示全部楼层
以前不知道还有这么多需要配置的地方
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部