1

USART の動作に問題があり、どなたか助けていただけないでしょうか! USART を 3 つ使用している STM32F303 を使用しています。そのうちの USART1 は、DE ラインが自動的に制御される非同期 RS485 ポートとして構成されています。マイクロコントローラの TX、RX、および DE ピンは TI SN65HVD1792 RS485 トランシーバに接続され、通信用に 4 つのライン (TX+、TX-、RX+、RX-) をユーザに提供します。

ほとんどの場合、まったく問題なく動作する割り込み駆動の USART 通信を使用しています。ただし、RS485 リンクが 2 線式 (TX+/RX+ と TX-/RX- が一緒に接続され、両方に使用される +ve/-ve ペアのワイヤを形成する) として構成されているというエラー状態の処理に問題があります。バス上の複数のデバイスが同時に送信を試みます。これが発生すると、STM32 は、電源が再投入されるまで、すべてのシリアル通信への応答を停止します。

何が起こっているのかを少し詳しく見てみると、stm32f3xx_it.c の USART1_IRQHandler が繰り返し呼び出されていることがわかります - ボードの電源を入れ直すまで何度も何度も。これは、stm32f3xx_hal_uart.c で HAL_UART_IRQHandler(&huart1) を呼び出します。その機能は、どの割り込みが発生したか (パリティ エラー、フレーム エラー、ノイズ エラー、オーバーラン、ストップからのウェイクアップ、rx レジスタが空でない、tx 準備完了、tx 完了) をチェックすることです。適切に対処し、割り込み状態をクリアしてください。ただし、これらの特定の割り込みはいずれもトリガーされたとは認識されません。実行はすべての「if」ステートメントを通過するだけで、関数は終了し、再び実行されます。

認識されたエラー状態がスローされないため、これが発生したことを認識する方法が見つかりません。RS485 バスの競合は、優れたシステム設計によって回避すべきものであることは承知していますが、システムが顧客のインストールにある場合に発生する可能性を排除することはできません。エラー、「clashed」メッセージを無視して続行 - 電源を再投入する必要があることは容認できません。

この状態を認識する/システムが割り込みループに入るのを止める方法について、誰かアイデアはありますか?

前もって感謝します

割り込みルーチンは次のとおりです (HAL ファイル バージョン 1.2.0、日付 13 Nov 15)

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
  /* UART parity error interrupt occurred -------------------------------------*/
  if((__HAL_UART_GET_IT(huart, UART_IT_PE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_PE) != RESET))
  {
    __HAL_UART_CLEAR_IT(huart, UART_CLEAR_PEF);

    huart->ErrorCode |= HAL_UART_ERROR_PE;
    /* Set the UART state ready to be able to start again the process */
    huart->State = HAL_UART_STATE_READY;
  }

  /* UART frame error interrupt occurred --------------------------------------*/
  if((__HAL_UART_GET_IT(huart, UART_IT_FE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET))
  {
    __HAL_UART_CLEAR_IT(huart, UART_CLEAR_FEF);

    huart->ErrorCode |= HAL_UART_ERROR_FE;
    /* Set the UART state ready to be able to start again the process */
    huart->State = HAL_UART_STATE_READY;
  }

  /* UART noise error interrupt occurred --------------------------------------*/
  if((__HAL_UART_GET_IT(huart, UART_IT_NE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET))
  {
    __HAL_UART_CLEAR_IT(huart, UART_CLEAR_NEF);

    huart->ErrorCode |= HAL_UART_ERROR_NE;
    /* Set the UART state ready to be able to start again the process */
    huart->State = HAL_UART_STATE_READY;
  }

  /* UART Over-Run interrupt occurred -----------------------------------------*/
  if((__HAL_UART_GET_IT(huart, UART_IT_ORE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET))
  {
    __HAL_UART_CLEAR_IT(huart, UART_CLEAR_OREF);

    huart->ErrorCode |= HAL_UART_ERROR_ORE;
    /* Set the UART state ready to be able to start again the process */
    huart->State = HAL_UART_STATE_READY;
  }

   /* Call UART Error Call back function if need be --------------------------*/
  if(huart->ErrorCode != HAL_UART_ERROR_NONE)
  {
    HAL_UART_ErrorCallback(huart);
  }

  /* UART wakeup from Stop mode interrupt occurred -------------------------------------*/
  if((__HAL_UART_GET_IT(huart, UART_IT_WUF) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_WUF) != RESET))
  {
    __HAL_UART_CLEAR_IT(huart, UART_CLEAR_WUF);
    /* Set the UART state ready to be able to start again the process */
    huart->State = HAL_UART_STATE_READY;
    HAL_UARTEx_WakeupCallback(huart);
  }

  /* UART in mode Receiver ---------------------------------------------------*/
  if((__HAL_UART_GET_IT(huart, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE) != RESET))
  {
    UART_Receive_IT(huart);
    /* Clear RXNE interrupt flag */
    __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
  }


  /* UART in mode Transmitter ------------------------------------------------*/
 if((__HAL_UART_GET_IT(huart, UART_IT_TXE) != RESET) &&(__HAL_UART_GET_IT_SOURCE(huart, UART_IT_TXE) != RESET))
  {
    UART_Transmit_IT(huart);
  }

  /* UART in mode Transmitter (transmission end) -----------------------------*/
 if((__HAL_UART_GET_IT(huart, UART_IT_TC) != RESET) &&(__HAL_UART_GET_IT_SOURCE(huart, UART_IT_TC) != RESET))
  {
    UART_EndTransmit_IT(huart);
  }

}
4

1 に答える 1

0

最初に行うことは、明示的に使用していないすべての割り込みを無効にすることです。少なくとも、これは犯人の特定に役立つはずです。__HAL_UART_DISABLE_IT()無効にする割り込みを渡すことにより、マクロでこれを行います。

それでもうまくいかない場合は、IRQ によって呼び出される関数TXEによって割り込みが無効になっていることを確認してください。UART_Transmit_IT()これが問題であるかどうかを判断する簡単な方法は、(問題が発生している間) 割り込みを手動で無効にし、IRQ のトリガーが停止するかどうかを確認することです。それ以外の場合は、UART_Transmit_IT()関数を中断して、__HAL_UART_DISABLE_IT(huart, UART_IT_TXE);行が実行されるかどうかを確認できます。終了時に割り込みが適切に無効にされていない場合、TXE引き続きトリガーされ、見ているものと同様の結果が生じます。

于 2016-04-27T15:53:56.963 に答える