当前位置: 首页 > news >正文

北京海淀公司网站icp备案发布悬赏任务的推广平台

北京海淀公司网站icp备案,发布悬赏任务的推广平台,长春市做网站,网络视频会议系统目录 1.官方的描述2.HAL的流程把接收到的数据从PMA拷贝到用户自己定义的空间中 3.处理接收到的数据4.最后再次开启准备接收工作 1.官方的描述 2.HAL的流程 以上的官方说法我们暂时按下不表。 如果接收到数据,会激活中断进入到USB_LP_CAN1_RX0_IRQHandler&#xff0…

目录

  • 1.官方的描述
  • 2.HAL的流程
    • 把接收到的数据从PMA拷贝到用户自己定义的空间中
  • 3.处理接收到的数据
  • 4.最后再次开启准备接收工作

1.官方的描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.HAL的流程

以上的官方说法我们暂时按下不表。
如果接收到数据,会激活中断进入到USB_LP_CAN1_RX0_IRQHandler()->HAL_PCD_IRQHandler()
因为所有的中断事件共用一个中断函数,所以第一步要进行中断类型检测,中断的信息都写在了ISTR寄存器中,判断代码如下:

  if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_CTR)){/* servicing of the endpoint correct transfer interrupt *//* clear of the CTR flag into the sub */(void)PCD_EP_ISR_Handler(hpcd);}

下一步自然而然的就是执行这个函数:

 (void)PCD_EP_ISR_Handler(hpcd);

既然进入中断了,我们还是要验证一下ISTR的正确传输中断有没有置位

 while ((hpcd->Instance->ISTR & USB_ISTR_CTR) != 0U)

在这里插入图片描述
技术手册提示:可以通过DIR和EPID来判断是哪个端点,接下来的代码也是符合这个步骤的,下面的步骤是判断了哪个端点,暂时没有判断方向,一些逻辑执行完毕后,就会判断方向了,详细看后面的代码。

wIstr = hpcd->Instance->ISTR;/* extract highest priority endpoint number */
epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);if (epindex == 0U)
{
}else if (epindex == 1U){//我们真正使用的端点}

下一步拿到端点寄存器的数据,看看CTR_RX有没有接收到数据
如果接收到第一步就是把标志位清除掉

下面的图片,发现正确接收标志位置1,CTRM置位,就会产生中断,CTRM位说,如果中断状态寄存器置1就会产生中断,这里面就说明任何端点正确接收置1后,中断状态寄存器也置1,这是一个联动反应

  wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);if ((wEPVal & USB_EP_CTR_RX) != 0U){/* clear int flag */PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);

在这里插入图片描述
紧接着,HAL库把OUT_ep结构体拿过来,这里面记录了所有规定的端点信息,在初始化阶段把这部分信息预先储存到结构体里面的。

ep = &hpcd->OUT_ep[epindex];/* OUT Single Buffering */if (ep->doublebuffer == 0U){count = (uint16_t)PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);if (count != 0U){USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);}}

其中 count = (uint16_t)PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);这条语句,

//先拿到对应端点缓冲表USB_COUNTn_RX的数据
#define PCD_EP_RX_CNT(USBx, bEpNum) ((uint16_t *)((((uint32_t)(USBx)->BTABLE\+ ((uint32_t)(bEpNum) * 8U) + 6U) * PMA_ACCESS) + ((uint32_t)(USBx) + 0x400U)))
//把USB_COUNTn_RX中的高于9位的信息删除掉,只保留COUNTn_RX(实际接收到的数据)
#define PCD_GET_EP_RX_CNT(USBx, bEpNum)        ((uint32_t)(*PCD_EP_RX_CNT((USBx), (bEpNum))) & 0x3ffU)

在这里插入图片描述
到了对关键的一步,就数据从缓冲区里面,拷贝到用户的自定义区

if (count != 0U){USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);}

注意一下参数:从上面看,最后接收到的数据,其实是放在对应端点结构体的xfter_buff里面的
在这里插入图片描述

把接收到的数据从PMA拷贝到用户自己定义的空间中

/*** @brief Copy data from packet memory area (PMA) to user memory buffer* @param   USBx USB peripheral instance register address.* @param   pbUsrBuf pointer to user memory area.* @param   wPMABufAddr address into PMA.* @param   wNBytes no. of bytes to be copied.* @retval None*/
/*** @brief Copy data from packet memory area (PMA) to user memory buffer* @param   USBx USB peripheral instance register address.* @param   pbUsrBuf pointer to user memory area.* @param   wPMABufAddr address into PMA.* @param   wNBytes no. of bytes to be copied.* @retval None*/
void USB_ReadPMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
{// 计算需要处理的16位数据单元的数量(每个单元包含2个字节),比如接收了64字节,>>1,变成了32字节uint32_t n = (uint32_t)wNBytes >> 1;// 计算USB外设的基地址uint32_t BaseAddr = (uint32_t)USBx;// 用于循环计数和临时存储数据的变量uint32_t i, temp;// 定义一个指向PMA中16位数据的指针__IO uint16_t *pdwVal;// 定义一个指向用户缓冲区的指针uint8_t *pBuf = pbUsrBuf;// 计算PMA中目标数据的起始地址pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));// 循环处理每个16位数据单元for (i = n; i != 0U; i--){// 从PMA中读取一个16位数据temp = *(__IO uint16_t *)pdwVal;pdwVal++;// 将16位数据的低8位存储到用户缓冲区*pBuf = (uint8_t)((temp >> 0) & 0xFFU);pBuf++;// 将16位数据的高8位存储到用户缓冲区*pBuf = (uint8_t)((temp >> 8) & 0xFFU);pBuf++;// 如果PMA访问的步长大于1,则跳过一个额外的单元(可能是因为硬件设计)
#if PMA_ACCESS > 1UpdwVal++;
#endif}// 如果剩余的字节数不是2的倍数(即还有1个字节未处理)if ((wNBytes % 2U) != 0U){// 从PMA中读取最后一个字节temp = *pdwVal;*pBuf = (uint8_t)((temp >> 0) & 0xFFU);}
}
#endif /* defined (USB) */

接收完成标志
可以看到这里有一个判断条件if ((ep->xfer_len == 0U) || (count <= ep->maxpacket)),其中ep->xfer_len == 0U)是给控制传输用的,他需要严格的控制包数,count <= ep->maxpacket是给中断传输用的,只要不大于最大包,就是传输完成(短包)

   /* multi-packet on the NON control OUT endpoint */ep->xfer_count += count;ep->xfer_buff += count;if ((ep->xfer_len == 0U) || (count <= ep->maxpacket)){/* RX COMPLETE */

3.处理接收到的数据

在这里插入图片描述

在这里插入图片描述

	USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev,uint8_t epnum, uint8_t *pdata)
{USBD_EndpointTypeDef *pep;if (epnum == 0U){//一些实现代码}else if ((pdev->pClass->DataOut != NULL) &&(pdev->dev_state == USBD_STATE_CONFIGURED)){pdev->pClass->DataOut(pdev, epnum);}else{/* should never be in this condition */return USBD_FAIL;}return USBD_OK;
}
USBD_ClassTypeDef  USBD_CUSTOM_HID =
{USBD_CUSTOM_HID_Init,USBD_CUSTOM_HID_DeInit,USBD_CUSTOM_HID_Setup,NULL, /*EP0_TxSent*/USBD_CUSTOM_HID_EP0_RxReady, /*EP0_RxReady*/ /* STATUS STAGE IN */USBD_CUSTOM_HID_DataIn, /*DataIn*/USBD_CUSTOM_HID_DataOut,NULL, /*SOF */NULL,NULL,USBD_CUSTOM_HID_GetHSCfgDesc,USBD_CUSTOM_HID_GetFSCfgDesc,USBD_CUSTOM_HID_GetOtherSpeedCfgDesc,USBD_CUSTOM_HID_GetDeviceQualifierDesc,
};

阅读上面代码,发现最终执行了pdev->pClass->DataOut(pdev, epnum);这个函数指针。
下图是在初始化阶段就绑定好的函数指针,可以找到真正执行的函数名字是
USBD_CUSTOM_HID_DataOut->

/**
/*** @brief  USBD_CUSTOM_HID_DataOut*         handle data OUT Stage* @param  pdev: device instance* @param  epnum: endpoint index* @retval status*/
static uint8_t  USBD_CUSTOM_HID_DataOut(USBD_HandleTypeDef *pdev,uint8_t epnum)
{USBD_CUSTOM_HID_HandleTypeDef     *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData;((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->OutEvent(epnum,hhid->Report_buf[0],hhid->Report_buf[1]);USBD_LL_PrepareReceive(pdev, CUSTOM_HID_EPOUT_ADDR, hhid->Report_buf,USBD_CUSTOMHID_OUTREPORT_BUF_SIZE);return USBD_OK;
}

注意这个代码,我们接收到的数据,第一个字节是报告描述符ID号码

((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->OutEvent(epnum,hhid->Report_buf[0],hhid->Report_buf[1]);

最终把数据储存到了USB_Recive_Buffer[i] = hhid->Report_buf[i];
并且调用了这个函数来解析数据HID_RxCpltCallback((uint8_t)epnum,&USB_Recive_Buffer);

/*** @brief  Manage the CUSTOM HID class events* @param  event_idx: Event index* @param  state: Event state* @retval USBD_OK if all operations are OK else USBD_FAIL*/
static int8_t CUSTOM_HID_OutEvent_FS(uint8_t epnum, uint8_t event_idx, uint8_t state)
{/* USER CODE BEGIN 6 */USBD_CUSTOM_HID_HandleTypeDef  *hhid = (USBD_CUSTOM_HID_HandleTypeDef*)hUsbDeviceFS.pClassData;for( uint8_t i  = 0;i <USBD_CUSTOMHID_OUTREPORT_BUF_SIZE;i++){USB_Recive_Buffer[i] = hhid->Report_buf[i];}HID_RxCpltCallback((uint8_t)epnum,&USB_Recive_Buffer);return (USBD_OK);/* USER CODE END 6 */
}

4.最后再次开启准备接收工作

在这里插入图片描述

http://www.cadmedia.cn/news/6966.html

相关文章:

  • 独立做网站需要学什么网络营销技巧
  • 免费域名证书申请seo网站系统
  • 通信工程网站建设企业网络营销策划方案
  • 信息公开网站建设seo 网站优化推广排名教程
  • 有域名怎么免费建站网店网络推广方案
  • 甘肃定西校园文化设计公司seo专业培训中心
  • 2022全国封城名单怎么优化百度关键词
  • seo的形式有哪些搜狗关键词优化软件
  • 网站备案成功后怎么弄今日实时热搜
  • 郑州网站设计多少钱下载百度app下载
  • 北京 网站开发做网络推广有哪些平台
  • 一个设计网站多少钱seo教程视频
  • 网站内外链建设手机端关键词排名免费软件
  • 建筑资料免费下载网站抖音搜索seo排名优化
  • 制作企业网站步骤网络营销的新特点
  • 家居企业网站建设方案百度指数怎么看
  • 金融行业网站建设郑州做网站公司排名
  • 网站策划人员需要做哪些工作抖音矩阵排名软件seo
  • 住房和城乡建设行业证书seo是什么职业做什么的
  • 建设执业资格管理中心网站中级经济师考试
  • 从化高端网站建设搜索引擎下载
  • 广告设计公司介绍范文电子商务沙盘seo关键词
  • 专业装修设计网站成都网站推广哪家专业
  • 怎样做美瞳网站网络销售挣钱吗
  • 科技打破垄断全球的霸权好看的seo网站
  • 泗水网站建设ys178soso搜索引擎
  • 网站建设实习目的网络广告宣传平台
  • 大连网站建设平台搜索引擎推广实训
  • 推广营销海外网站自制网页
  • 漂亮的个人网站百度问答下载安装