STM32

F722ZE USART Example

programmer j 2021. 8. 29. 17:34

F722ZE의 USART예제

동작

- 호스트에서 수신한 데이터를 그대로 다시 보내기

- 소스 위치

https://github.com/heecheol-jung/F722ZE_USART_Example

 

1. 공통 설정

1.1. USART설정

 항목
Baud rate 115200
Word length 8 bits
Parity None
Stop bits 1

 

그림1 USART3 공통설정

 

1.2. STM32CubeIDE설정

- 포매터 설정

Window -> Preference -> C/C++ -> Code Style -> Formatter -> Import

-> c_style디렉토리의 My_Formatter.xml선택 -> Apply and Close

 

2. 폴링 예제

- HAL_UART_Receive와 HAL_UART_Transmit 함수 사용

- USART_ISR의 RXNE비트 검사

- main.c

if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE))
{
  HAL_UART_Receive(&huart3, g_app.rx_buf, 1, FW_APP_PROTO_RX_TIMEOUT);
  HAL_UART_Transmit(&huart3, g_app.rx_buf, 1, FW_APP_PROTO_TX_TIMEOUT);
}

 

3. 인터럽트 수신 예제

- HAL_UART_Receive_IT와 수신 큐 사용

- 인터럽트 설정

그림2 인터럽드 설정

- 수신(fw_app.c)

// Callback function for UART data reception.
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart == &huart3)
  {
    fl_q_push(&g_app.q1, g_app.rx_buf1[0]);
    HAL_UART_Receive_IT(&huart3, g_app.rx_buf1, 1);
  }
}

- 송신(main.c)

_rx_count = fl_q_count(&g_app.q1);
if (_rx_count > 0)
{
  for (uint32_t i = 0; i < _rx_count; i++)
  {
    fl_q_pop(&g_app.q1, &_rx_data);
    HAL_UART_Transmit(&huart3, &_rx_data, 1, FW_APP_PROTO_TX_TIMEOUT);
  }
}

 

4. 인터럽트 송/수신 예제

- HAL_UART_Receive_IT, HAL_UART_Transmit_IT, 수신 큐 사용

- 수신(fw_app.c)

// Callback function for UART data reception.
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart == &huart3)
  {
    fl_q_push(&g_app.q1, g_app.rx_buf1[0]);
    HAL_UART_Receive_IT(&huart3, g_app.rx_buf1, 1);
  }
}

- 송신(main.c, fw_app.c)

_rx_count = fl_q_count(&g_app.q1);
if (_rx_count > 0)
{
  for (uint32_t i = 0; i < _rx_count; i++)
  {
    fl_q_pop(&g_app.q1, &_rx_data);
    if (g_app.tx_len1 < FW_APP_TX_BUF_SIZE)
    {
      g_app.tx_buf1[g_app.tx_len1++] = _rx_data;
      if (g_app.tx_len1 == FW_APP_TX_BUF_SIZE)
      {
        fw_app_int_transmit();
      }
    }
  }
  if (g_app.tx_len1 > 0)
  {
    fw_app_int_transmit();
  }
}
FL_DECLARE(void) fw_app_int_transmit(void)
{
  HAL_StatusTypeDef ret;
  uint8_t wait_count = 0;
  ret = HAL_UART_Transmit_IT(&huart3, g_app.tx_buf1, (uint16_t)g_app.tx_len1);
  if (ret == HAL_OK)
  {
    while (1)
    {
      if (huart3.gState == HAL_UART_STATE_READY)
      {
        break;
      }
      HAL_Delay(1);
      wait_count++;
      if (wait_count >= FW_APP_INT_TX_MAX_COUNT)
      {
        break;
      }
    }
  }
  g_app.tx_len1 = 0;
}

 

5. DMA 수신 예제

- HAL_UART_Receive_DMA, DMA의 NDTR레지스터, 수신 큐 사용

- 인터럽트 설정

그림3 DMA수신 인터럽트 설정

- DMA수신 설정

  Mode : Circular

그림4 DMA RX설정

- DMA_SxNDTR를 이용해서 큐의 head위치를 계산하는데 사용

- 수신(fw_app.c)

HAL_UART_Receive_DMA(&huart3, _g_q1_buf, sizeof(_g_q1_buf));

- 송신(main.c)

_rx_count = fl_dma_q_count(&g_app.q1);
if (_rx_count > 0)
{
  for (uint32_t i = 0; i < _rx_count; i++)
  {
    fl_dma_q_pop(&g_app.q1, &_rx_data);
    HAL_UART_Transmit(&huart3, &_rx_data, 1, FW_APP_PROTO_TX_TIMEOUT);
  }
}

 

6. DMA 송/수신 예제

- HAL_UART_Receive_DMA, HAL_UART_Transmit_DMA, DMA의 NDTR레지스터, 수신 큐 사용

- 인터럽트 설정

그림5 DMA 송/수신 인터럽트 설정

- DMA수신 설정

  Mode : Circular

그림6 DMA 수신 설정

- DMA송신 설정

  Mode : Normal

그림7 DMA 송신 설정

- DMA_SxNDTR를 이용해서 큐의 head위치를 계산하는데 사용

- 수신(fw_app.c)

HAL_UART_Receive_DMA(&huart3, _g_q1_buf, sizeof(_g_q1_buf));

-송신(main.c, fw_app.c)

_rx_count = fl_dma_q_count(&g_app.q1);
if (_rx_count > 0)
{
  fl_bool_t tx_ready = FL_FALSE;
  for (uint32_t i = 0; i < _rx_count; i++)
  {
    fl_dma_q_pop(&g_app.q1, &_rx_data);
    if (g_app.tx_len1 < FW_APP_TX_BUF_SIZE)
    {
      g_app.tx_buf1[g_app.tx_len1++] = _rx_data;
      if (g_app.tx_len1 == FW_APP_TX_BUF_SIZE)
      {
        fw_app_dma_transmit();
      }
    }
  }
  if (g_app.tx_len1 > 0)
  {
    fw_app_dma_transmit();
  }
}
FL_DECLARE(void) fw_app_dma_transmit(void)
{
  HAL_StatusTypeDef ret;
  uint8_t wait_count = 0;
  ret = HAL_UART_Transmit_DMA(&huart3, g_app.tx_buf1, (uint16_t)g_app.tx_len1);
  if (ret == HAL_OK)
  {
    while (1)
    {
      if (huart3.gState == HAL_UART_STATE_READY)
      {
        break;
      }
      HAL_Delay(1);
      wait_count++;
      if (wait_count >= FW_APP_DMA_TX_MAX_COUNT)
      {
        break;
      }
    }
  }
  g_app.tx_len1 = 0;
}

 

7. USB CDC예제

- CDC_Receive_FS, CDC_Transmit_FS, 수신큐 사용

- 수신(usbd_cdc_if.c)

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  for (uint32_t i = 0; i < *Len; i++)
  {
    fl_q_push(&g_app.q1, Buf[i]);
  }
  return (USBD_OK);
  /* USER CODE END 6 */
}

- 송신(main.c)

_rx_count = fl_q_count(&g_app.q1);
if (_rx_count > 0)
{
  for (uint32_t i = 0; i < _rx_count; i++)
  {
    fl_q_pop(&g_app.q1, &g_app.tx_buf1[g_app.tx_len1++]);
  }
  CDC_Transmit_FS(g_app.tx_buf1, g_app.tx_len1);
  g_app.tx_len1 = 0;
}

'STM32' 카테고리의 다른 글

F722ZE Parser Example2  (0) 2021.09.12
F722ZE Parser Example  (0) 2021.09.08