[HAL] odbiór danych z wykorzystaniem przerwań

Tu możesz pisać o swoich problemach z pisaniem programów w języku C/C++ dla STM.
Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1168
Rejestracja: czwartek 03 wrz 2015, 22:02

[HAL] odbiór danych z wykorzystaniem przerwań

Postautor: Antystatyczny » niedziela 01 maja 2016, 15:12

Witam i proszę o poradę. Generator kodu CubeMX generuje dla modułu USART komplet funkcji, a wśród nich jest HAL_UART_Receive_IT(). Do funkcji tej przekazujemy uchwyt do instancji modułu, adres bufora odbiorczego (nie jest cykliczny) oraz rozmiar tego bufora. Wywołanie tej funkcji powoduje wpisanie do uchwytu adresu bufora, jego rozmiaru, no i nakręca licznik wskazujący ilość miejsca w buforze. Inna funkcja, UART_Receive_IT(), wywoływana jest za każdym razem, gdy nastąpi przerwanie od modułu USART. Wpisuje ona do bufora odebrany znak, dekrementuje licznik wskazujący ilość miejsca w buforze, a gdy osiągnie on wartość zerową, wyłącza przerwanie odbiorcze oraz umożliwia wywołanie callbacka. Niestety nie ma żadnego mechanizmu, który pozwoliłby na użycie bufora cyklicznego (pomijając użycie DMA). Reasumując, Funkcja HAL ustawia wskaźnik na bufor oraz nakręca licznik, a funkcja wewnętrzna używa bufora i dekrementuje licznik, a gdy on się wyzeruje, przerwanie jest wyłączane. Zastanawiam się, w jaki sposób zautomatyzować proces odbioru danych tekstowych przez uart, bo nie mogę non stop wywoływać funkcji HAL_UART_Receive_IT. Poniżej wklejam obie funkcje oraz prototyp uchwytu:

Kod: Zaznacz cały

typedef struct
{
  USART_TypeDef                 *Instance;        /*!< UART registers base address        */

  UART_InitTypeDef              Init;             /*!< UART communication parameters      */

  uint8_t                       *pTxBuffPtr;      /*!< Pointer to UART Tx transfer Buffer */

  uint16_t                      TxXferSize;       /*!< UART Tx Transfer size              */

  uint16_t                      TxXferCount;      /*!< UART Tx Transfer Counter           */

  uint8_t                       *pRxBuffPtr;      /*!< Pointer to UART Rx transfer Buffer */

  uint16_t                      RxXferSize;       /*!< UART Rx Transfer size              */

  uint16_t                      RxXferCount;      /*!< UART Rx Transfer Counter           */ 

  DMA_HandleTypeDef             *hdmatx;          /*!< UART Tx DMA Handle parameters      */

  DMA_HandleTypeDef             *hdmarx;          /*!< UART Rx DMA Handle parameters      */

  HAL_LockTypeDef               Lock;             /*!< Locking object                     */

  __IO HAL_UART_StateTypeDef    State;            /*!< UART communication state           */
 
  __IO uint32_t                 ErrorCode;        /*!< UART Error code                    */

}UART_HandleTypeDef;


Kod: Zaznacz cały

static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
  uint16_t* tmp;
  uint32_t tmp_state = 0;
 
  tmp_state = huart->State;
  if((tmp_state == HAL_UART_STATE_BUSY_RX) || (tmp_state == HAL_UART_STATE_BUSY_TX_RX))
  {
    if(huart->Init.WordLength == UART_WORDLENGTH_9B)
    {
      tmp = (uint16_t*) huart->pRxBuffPtr;
      if(huart->Init.Parity == UART_PARITY_NONE)
      {
        *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
        huart->pRxBuffPtr += 2;
      }
      else
      {
        *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF);
        huart->pRxBuffPtr += 1;
      }
    }
    else
    {
      if(huart->Init.Parity == UART_PARITY_NONE)
      {
        *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
      }
      else
      {
        *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
      }
    }

    if(--huart->RxXferCount == 0)
    {
      __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);

      /* Check if a transmit process is ongoing or not */
      if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
      {
        huart->State = HAL_UART_STATE_BUSY_TX;
      }
      else
      {
        /* Disable the UART Parity Error Interrupt */
        __HAL_UART_DISABLE_IT(huart, UART_IT_PE);

        /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
        __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

        huart->State = HAL_UART_STATE_READY;
      }
      HAL_UART_RxCpltCallback(huart);

      return HAL_OK;
    }
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}


Kod: Zaznacz cały

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  uint32_t tmp_state = 0;
 
  tmp_state = huart->State;
  if((tmp_state == HAL_UART_STATE_READY) || (tmp_state == HAL_UART_STATE_BUSY_TX))
  {
    if((pData == NULL ) || (Size == 0))
    {
      return HAL_ERROR;
    }

    /* Process Locked */
    __HAL_LOCK(huart);

    huart->pRxBuffPtr = pData;
    huart->RxXferSize = Size;
    huart->RxXferCount = Size;

    huart->ErrorCode = HAL_UART_ERROR_NONE;
    /* Check if a transmit process is ongoing or not */
    if(huart->State == HAL_UART_STATE_BUSY_TX)
    {
      huart->State = HAL_UART_STATE_BUSY_TX_RX;
    }
    else
    {
      huart->State = HAL_UART_STATE_BUSY_RX;
    }

    /* Process Unlocked */
    __HAL_UNLOCK(huart);

    /* Enable the UART Parity Error Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_PE);

    /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
    __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);

    /* Enable the UART Data Register not empty Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);

    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}


Nie chodzi mi o przedstawienie gotowca, ale raczej o jakiś zarys pomysłu.

Pozdrawiam
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.

Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1168
Rejestracja: czwartek 03 wrz 2015, 22:02

Re: [HAL] odbiór danych z wykorzystaniem przerwań

Postautor: Antystatyczny » poniedziałek 02 maja 2016, 06:05

Ok, poradziłem sobie. Wystarczy przekazać jednobajtowy bufor do HAL_UART_Receive_IT().
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.


Wróć do „Programowanie STM w C/C++”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 3 gości