<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>
"); //-->

博客專(zhuān)欄

EEPW首頁(yè) > 博客 > 又踩坑了!這次敗給CAN總線(xiàn)了

又踩坑了!這次敗給CAN總線(xiàn)了

發(fā)布人:xiaomaidashu 時(shí)間:2023-10-13 來(lái)源:工程師 發(fā)布文章

Warning: file_get_contents(): SSL: connection timeout in /var/www/html/www.edw.com.cn/www/rootapp/controllersspace/ArticlesmanageController.php on line 270 Warning: file_get_contents(): Failed to enable crypto in /var/www/html/www.edw.com.cn/www/rootapp/controllersspace/ArticlesmanageController.php on line 270 Warning: file_get_contents(https://mmbiz.qpic.cn/mmbiz_png/zcVcDoKYUnZl6JkGyy6tyFnYlC18c27HK6twaSRm6A4sibculYDv7dnicqDrqw4ph9XicrYQokE0QcNpbjcejjvmg/640?wx_fmt=png&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1): failed to open stream: operation failed in /var/www/html/www.edw.com.cn/www/rootapp/controllersspace/ArticlesmanageController.php on line 270

前言

最近負責的一個(gè)項目用的主控芯片是STM32F407IGT6,需要和幾個(gè)電機控制器進(jìn)行通訊,有很多參數需要進(jìn)行監控。
有一個(gè)問(wèn)題一直無(wú)法解決。在開(kāi)啟CAN的接收中斷,接收不到數據,問(wèn)題卡了很久,下面簡(jiǎn)單分享一下解決的過(guò)程和思路。

目錄
  • 背景

  • CAN總線(xiàn)

  • CAN控制器

  • CAN收發(fā)器

  • 調試過(guò)程

    • 硬件排查

    • CAN分析儀

    • 芯片CAN控制器調試

  • 總結

CAN總線(xiàn)

CAN總線(xiàn)是一種串行通信協(xié)議,用于在微控制器和其他設備之間傳輸數據。CAN總線(xiàn)通常用于汽車(chē)、工業(yè)自動(dòng)化和機器人等領(lǐng)域。

CAN總線(xiàn)的硬件通常由以下幾個(gè)部分組成:

  • 控制器區域:包括CAN控制器和CAN收發(fā)器;
  • 總線(xiàn)電纜:用于連接CAN總線(xiàn)上的所有設備;
  • 終端電阻:用于終止總線(xiàn),以減少反射和信號干擾;
  • 外部電源:用于為CAN總線(xiàn)提供電源;

CAN總線(xiàn)的控制器區域通常包括CAN控制器和CAN收發(fā)器。

  • CAN控制器負責處理CAN總線(xiàn)上的數據傳輸,包括數據發(fā)送和接收、錯誤檢測和糾正等;
  • CAN收發(fā)器則負責將CAN控制器的信號轉換為總線(xiàn)上的電信號,并將總線(xiàn)上的電信號轉換為CAN控制器可以理解的信號。
CAN控制器

主板上的芯片STM32F407IGT6中帶有兩路的CAN控制器,分別為CAN1 和 CAN2,具體如下圖所示;

圖片

CAN收發(fā)器

主板上使用的是芯片SN65HVD230,這是TI公司的一款性能強大且具體低功耗功能的CAN收發(fā)器,具體的典型應用電路如下所示;

圖片

調試過(guò)程硬件排查

設備的調試過(guò)程中,首先要確保硬件鏈路上是否正常。最常見(jiàn)的方法就是直接用示波器進(jìn)行檢查。具體如下所示;

圖片

  1. 檢查CAN控制器和CAN收發(fā)器之間是否正常;
  2. 檢查CAN收發(fā)器的差分信號是否正常,這里可能要了解一下CAN總線(xiàn)電平的顯性電平和隱性電平的特點(diǎn),以及CAN底層協(xié)議的細節,會(huì )比較復雜;

個(gè)人比較推薦使用上述步驟檢查硬件鏈路是否存在問(wèn)題,那如何對數據進(jìn)行分析呢?當然可以對著(zhù)示波器的波形一點(diǎn)一點(diǎn)進(jìn)行分析,但是這樣是很低效的,這里我建議使用CAN分析儀進(jìn)行數據抓包,下面我們繼續進(jìn)行介紹。

CAN分析儀

至于數據傳輸是否正確,可以使用CAN盒進(jìn)行數據監聽(tīng),下面是我使用的一款CAN分析儀,如圖;

圖片

將CAN分析儀的CAN_H和CAN_L分別并聯(lián)到CAN收發(fā)器的CAN_H和CAN_L上,然后打開(kāi)CAN分析儀廠(chǎng)家提供的PC軟件,就可以對CAN總線(xiàn)的數據進(jìn)行監聽(tīng);圖片

  1. 將CAN分析儀接入到CAN總線(xiàn);
  2. 將CAN分析儀連接到電腦(這里是USB接口),需要配置相同的波特率;
  3. 打開(kāi)CAN分析儀配套的PC軟件,進(jìn)行數據的收發(fā);圖片
  4. 進(jìn)行到這里,我在項目中遇到的問(wèn)題是,發(fā)送正常,但是STM32F407無(wú)法接收到連續的數據,可以接收到一次數據,后面便無(wú)法再進(jìn)入中斷。這時(shí)候,只能再芯片端進(jìn)行Debug了。
芯片CAN控制器調試

這里的代碼用的HAL庫,庫版本相對來(lái)說(shuō)比較老,是V1.7.10版本的,如下圖所示;


圖片

當時(shí)我把項目升級到最新的HAL庫,發(fā)現CAN部分的驅動(dòng)改動(dòng)比較大,另外,下文都是基于V1.7.10版本的HAL庫。

CAN控制器的初始化代碼如下所示;

void MX_CAN_Init(void)
{
 CAN_FilterConfTypeDef  sFilterConfig;

 /*CAN單元初始化*/
 hCAN.Instance = CANx;             /* CAN外設 */
 hCAN.pTxMsg = &TxMessage;
 hCAN.pRxMsg = &RxMessage;

 hCAN.Init.Prescaler = 6;          /* BTR-BRP 波特率分頻器  定義了時(shí)間單元的時(shí)間長(cháng)度 42/(1+6+7)/6 = 500Kbps */
 hCAN.Init.Mode = CAN_MODE_NORMAL; /* 正常工作模式 */
 hCAN.Init.SJW = CAN_SJW_1TQ;      /* BTR-SJW 重新同步跳躍寬度 1個(gè)時(shí)間單元 */
 hCAN.Init.BS1 = CAN_BS1_6TQ;      /* BTR-TS1 時(shí)間段1 占用了6個(gè)時(shí)間單元 */
 hCAN.Init.BS2 = CAN_BS2_7TQ;      /* BTR-TS1 時(shí)間段2 占用了7個(gè)時(shí)間單元 */
 hCAN.Init.TTCM = DISABLE;         /* MCR-TTCM  關(guān)閉時(shí)間觸發(fā)通信模式使能 */
 hCAN.Init.ABOM = ENABLE;          /* MCR-ABOM  自動(dòng)離線(xiàn)管理 */
 hCAN.Init.AWUM = ENABLE;          /* MCR-AWUM  使用自動(dòng)喚醒模式 */
 hCAN.Init.NART = DISABLE;         /* MCR-NART  禁止報文自動(dòng)重傳   DISABLE-自動(dòng)重傳 */
 hCAN.Init.RFLM = DISABLE;         /* MCR-RFLM  接收FIFO 鎖定模式  DISABLE-溢出時(shí)新報文會(huì )覆蓋原有報文 */
 hCAN.Init.TXFP = DISABLE;         /* MCR-TXFP  發(fā)送FIFO優(yōu)先級 DISABLE-優(yōu)先級取決于報文標示符 */
 HAL_CAN_Init(&hCAN);

 /*CAN過(guò)濾器初始化*/
 sFilterConfig.FilterNumber = 0;                    /* 過(guò)濾器組0 */
 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;  /* 工作在標識符屏蔽位模式 */
 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; /* 過(guò)濾器位寬為單個(gè)32位。*/
 /* 使能報文標示符過(guò)濾器按照標示符的內容進(jìn)行比對過(guò)濾,擴展ID不是如下的就拋棄掉,是的話(huà),會(huì )存入FIFO0。 */
 sFilterConfig.FilterIdHigh         = 0x0000; //(((uint32_t)0x1314<<3)&0xFFFF0000)>>16;    /* 要過(guò)濾的ID高位 */
 sFilterConfig.FilterIdLow          = 0x0000; //(((uint32_t)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; /* 要過(guò)濾的ID低位 */
 sFilterConfig.FilterMaskIdHigh     = 0x0000;   /* 過(guò)濾器高16位每位必須匹配 */
 sFilterConfig.FilterMaskIdLow      = 0x0000;   /* 過(guò)濾器低16位每位必須匹配 */
 sFilterConfig.FilterFIFOAssignment = 0;           /* 過(guò)濾器被關(guān)聯(lián)到FIFO 0 */
 sFilterConfig.FilterActivation = ENABLE;          /* 使能過(guò)濾器 */ 
 sFilterConfig.BankNumber = 14;
 HAL_CAN_ConfigFilter(&hCAN, &sFilterConfig);
  
}

根據注釋?zhuān)梢源蟾趴炊?,另外再?jiǎn)單分析一下關(guān)鍵的幾點(diǎn);

  • 波特率設置為 500Kbps;
  • 對報文不進(jìn)行過(guò)濾,可以接收任何擴展ID的數據;

雖然不進(jìn)行任何過(guò)濾,但是還是無(wú)法接收到CAN回傳的數據,無(wú)法進(jìn)入的接收中斷;

從STM32F407的編程手冊里了解到;

圖片

不難發(fā)現,CAN1的FIFO0產(chǎn)生接收中斷需要滿(mǎn)足三個(gè)條件中的任意一個(gè);

  • FMPIE0置1 且 FMP0置1;FIFO不為空會(huì )產(chǎn)生中斷
  • FFIE0置1 且 FULL置1;FIFO滿(mǎn),會(huì )產(chǎn)生中斷
  • FOVIE0置1 且 FOVR0置1;FIFO溢出,會(huì )產(chǎn)生中斷

手冊里是這樣描述的,如下圖所示;


圖片

使用仿真器對芯片進(jìn)行調試,設置斷點(diǎn),發(fā)現FMPIE0被清空了,具體如下圖所示;圖片

FMPIE0這一位是FIFO0中有掛起的消息會(huì )產(chǎn)生中斷的中斷使能標志位;


圖片圖片

所以到這里,問(wèn)題有點(diǎn)明朗了,為什么無(wú)法進(jìn)入中斷?是中斷使能位被清空了。

那么下面就是檢查代碼,看看是哪里把中斷給disable了。

繼續調試,發(fā)現在ESR寄存器中,TEC的值一直增加,然后EWGF被值1了;具體如下所示;


圖片

TEC和REC分別是發(fā)送錯誤計數器和接收錯誤計數器;

如 CAN 協(xié)議所述,錯誤管理完全由硬件通過(guò)發(fā)送錯誤計數器( CAN_ESR 寄存器中的 TEC 值)和接收錯誤計數器( CAN_ESR 寄存器中的 REC 值)來(lái)處理,這兩個(gè)計數器根據錯誤 狀況進(jìn)行遞增或遞減。有關(guān) TEC 和 REC 管理的詳細信息,請參見(jiàn) CAN 標準。兩者均可由軟件讀取,用以確定網(wǎng)絡(luò )的穩定性。此外, CAN 硬件還將在 CAN_ESR 寄存器中 提供當前錯誤狀態(tài)的詳細信息。通過(guò) CAN_IER 寄存器( ERRIE 位等),軟件可以非常靈活 地配置在檢測到錯誤時(shí)生成的中斷。

當TEC大于96的時(shí)候,硬件會(huì )將EWGF置1(錯誤警告標志位);在代碼中找到了相應的宏定義;這下問(wèn)題越來(lái)越清晰了。

圖片

全文搜索這個(gè)宏定義,在HAL_CAN_IRQHandler中找到了__HAL_CAN_DISABLE_IT(CAN_IT_FMP0),關(guān)閉了FIFO0的消息掛起中斷, 整體代碼如下;

/**
  * @brief  Handles CAN interrupt request  
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
  *         the configuration information for the specified CAN.
  * @retval None
  */
void HAL_CAN_IRQHandler(CAN_HandleTypeDef* hcan)
{
  uint32_t tmp1 = 0U, tmp2 = 0U, tmp3 = 0U;
  uint32_t errorcode = HAL_CAN_ERROR_NONE;

  /* Check Overrun flag for FIFO0 */
  tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_FOV0);
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FOV0);
  if(tmp1 && tmp2)
  {
    /* Set CAN error code to FOV0 error */
    errorcode |= HAL_CAN_ERROR_FOV0;

    /* Clear FIFO0 Overrun Flag */
    __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV0);
  }
  /* Check Overrun flag for FIFO1 */
  tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_FOV1);
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FOV1);

  if(tmp1 && tmp2)
  {
    /* Set CAN error code to FOV1 error */
    errorcode |= HAL_CAN_ERROR_FOV1;

    /* Clear FIFO1 Overrun Flag */
    __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV1);
  }

  /* Check End of transmission flag */
  if(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_TME))
  {
    tmp1 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_0);
    tmp2 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_1);
    tmp3 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_2);
    if(tmp1 || tmp2 || tmp3)  
    {
      tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK0);
      tmp2 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK1);
      tmp3 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK2);
      /* Check Transmit success */
      if(tmp1 || tmp2 || tmp3)
      {
        /* Call transmit function */
        CAN_Transmit_IT(hcan);
      }
      else /* Transmit failure */
      {
        /* Set CAN error code to TXFAIL error */
        errorcode |= HAL_CAN_ERROR_TXFAIL;
      }

      /* Clear transmission status flags (RQCPx and TXOKx) */
      SET_BIT(hcan->Instance->TSR, CAN_TSR_RQCP0  | CAN_TSR_RQCP1  | CAN_TSR_RQCP2 | 
                                   CAN_FLAG_TXOK0 | CAN_FLAG_TXOK1 | CAN_FLAG_TXOK2);
    }
  }

  tmp1 = __HAL_CAN_MSG_PENDING(hcan, CAN_FIFO0);
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP0);
  /* Check End of reception flag for FIFO0 */
  if((tmp1 != 0U) && tmp2)
  {
    /* Call receive function */
    CAN_Receive_IT(hcan, CAN_FIFO0);
  }

  tmp1 = __HAL_CAN_MSG_PENDING(hcan, CAN_FIFO1);
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP1);
  /* Check End of reception flag for FIFO1 */
  if((tmp1 != 0U) && tmp2)
  {
    /* Call receive function */
    CAN_Receive_IT(hcan, CAN_FIFO1);
  }

  /* Set error code in handle */
  hcan->ErrorCode |= errorcode;

  tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EWG);
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EWG);
  tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
  /* Check Error Warning Flag */
  if(tmp1 && tmp2 && tmp3)
  {
    /* Set CAN error code to EWG error */
    hcan->ErrorCode |= HAL_CAN_ERROR_EWG;
  }
  
  tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EPV);
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EPV);
  tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR); 
  /* Check Error Passive Flag */
  if(tmp1 && tmp2 && tmp3)
  {
    /* Set CAN error code to EPV error */
    hcan->ErrorCode |= HAL_CAN_ERROR_EPV;
  }
  
  tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_BOF);
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_BOF);
  tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);  
  /* Check Bus-Off Flag */
  if(tmp1 && tmp2 && tmp3)
  {
    /* Set CAN error code to BOF error */
    hcan->ErrorCode |= HAL_CAN_ERROR_BOF;
  }
  
  tmp1 = HAL_IS_BIT_CLR(hcan->Instance->ESR, CAN_ESR_LEC);
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_LEC);
  tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
  /* Check Last error code Flag */
  if((!tmp1) && tmp2 && tmp3)
  {
    tmp1 = (hcan->Instance->ESR) & CAN_ESR_LEC;
    switch(tmp1)
    {
      case(CAN_ESR_LEC_0):
          /* Set CAN error code to STF error */
          hcan->ErrorCode |= HAL_CAN_ERROR_STF;
          break;
      case(CAN_ESR_LEC_1):
          /* Set CAN error code to FOR error */
          hcan->ErrorCode |= HAL_CAN_ERROR_FOR;
          break;
      case(CAN_ESR_LEC_1 | CAN_ESR_LEC_0):
          /* Set CAN error code to ACK error */
          hcan->ErrorCode |= HAL_CAN_ERROR_ACK;
          break;
      case(CAN_ESR_LEC_2):
          /* Set CAN error code to BR error */
          hcan->ErrorCode |= HAL_CAN_ERROR_BR;
          break;
      case(CAN_ESR_LEC_2 | CAN_ESR_LEC_0):
          /* Set CAN error code to BD error */
          hcan->ErrorCode |= HAL_CAN_ERROR_BD;
          break;
      case(CAN_ESR_LEC_2 | CAN_ESR_LEC_1):
          /* Set CAN error code to CRC error */
          hcan->ErrorCode |= HAL_CAN_ERROR_CRC;
          break;
      default:
          break;
    }

    /* Clear Last error code Flag */ 
    hcan->Instance->ESR &= ~(CAN_ESR_LEC);
  }
  
  /* Call the Error call Back in case of Errors */
  if(hcan->ErrorCode != HAL_CAN_ERROR_NONE)
  {
    /* Clear ERRI Flag */ 
    hcan->Instance->MSR = CAN_MSR_ERRI; 
    /* Set the CAN state ready to be able to start again the process */
    hcan->State = HAL_CAN_STATE_READY;

    /* Disable interrupts: */
    /*  - Disable Error warning Interrupt */
    /*  - Disable Error passive Interrupt */
    /*  - Disable Bus-off Interrupt */
    /*  - Disable Last error code Interrupt */
    /*  - Disable Error Interrupt */
    /*  - Disable FIFO 0 message pending Interrupt */
    /*  - Disable FIFO 0 Overrun Interrupt */
    /*  - Disable FIFO 1 message pending Interrupt */
    /*  - Disable FIFO 1 Overrun Interrupt */
    /*  - Disable Transmit mailbox empty Interrupt */
    __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG |
                               CAN_IT_EPV |
                               CAN_IT_BOF |
                               CAN_IT_LEC |
                               CAN_IT_ERR |
                               CAN_IT_FMP0|
                               CAN_IT_FOV0|
                               CAN_IT_FMP1|
                               CAN_IT_FOV1|
                               CAN_IT_TME);

    /* Call Error callback function */
    HAL_CAN_ErrorCallback(hcan);
  }  
}

最后,找到無(wú)法進(jìn)入接收中斷的原因,是CAN總線(xiàn)出現發(fā)送錯誤的情況,從而觸發(fā)了錯誤警告標志位EWGF,進(jìn)而將關(guān)閉了消息掛起中斷。

總結

本文簡(jiǎn)單介紹了在STM32F407上的CAN總線(xiàn)調試過(guò)程,項目中難免會(huì )遇到各種問(wèn)題,解決之后,大家要及時(shí)做好總結和復盤(pán),技術(shù)在于積累和沉淀,相互學(xué)習,共同進(jìn)步。


*博客內容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀(guān)點(diǎn),如有侵權請聯(lián)系工作人員刪除。



關(guān)鍵詞: CAN總線(xiàn)

相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>