본문 바로가기

개발/통신

CubeIDE STM32 UART 수신 interrupt 처리 및 에러 처리, example source

반응형

CubeIDE 에서 STM32 Uart 통신  관련 주요 부분..

 

 

main.c

===========================================

void MyTaskInit(){
    Serial_Init();
}

void MyTask(){
  Serial_get1();  // 처리 함수
  Serial_get6();
}

int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* Configure the system clock */
  SystemClock_Config();
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_FSMC_Init();
  MX_TIM1_Init();
  MX_TIM2_Init();
  MX_TIM8_Init();
  MX_TIM10_Init();
  MX_USART1_UART_Init();
  MX_USART6_UART_Init();

  MyTaskInit();

  /* USER CODE BEGIN WHILE */
  while (1)
  {
    MyTask();
  }
}

; 생략

;

===========================================

 

Serial.c

===========================================

#define RXBUFSIZE   1024

typedef struct {
  uint32_t head, tail;
  volatile uint32_t nBytes; // 이것은 int 안에서 , 밖에서 다 바뀌므로 , volatile 로 해 줘야..  그런데... 안해도 되는거 같은..
  uint8_t buf[RXBUFSIZE], d;
} QUart, *pQUart;

QUart q1uart;
QUart q6uart;

extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart6;

// printf 문을 쓰기 위해 설정 : __weak 로 설정된  __io_putchar 함수 재 정의
int __io_putchar(int ch)
{
  if(HAL_UART_Transmit(&huart6, (uint8_t *)&ch, 110) != HAL_OK) return -1;
  return ch;
}

void InitUartQueue(pQUart pQueue) {    // 큐 초기화
  pQueue->nBytes = pQueue->head = pQueue->tail = 0;
}

void Serial_Init(void) {  
  InitUartQueue(&q1uart);   // 큐 초기화
  InitUartQueue(&q6uart);
  HAL_UART_Receive_IT(&huart1, &q1uart.d, 1); // 이거 한번 먼저 해줘야    , 1개 들어오면 인터럽트 발생 시켜라
  HAL_UART_Receive_IT(&huart6, &q6uart.d, 1);  
}

static void MinusByte1(pQUart pQueue) {   // 큐에서 1바이트 뺐다고 기록
  pQueue->tail = (pQueue->tail == (RXBUFSIZE - 1)) ? 0 : (pQueue->tail + 1);
  pQueue->nBytes--;
}

void Serial_get6() {   // parsing packet
  uint8_t d;

  while (q6uart.nBytes) {  // 계속 빼줌
    d = q6uart.buf[q6uart.tail]; 
    HAL_UART_Transmit(&huart6, &d, 110);  //    printf("-%c", d);
    MinusByte1(&q6uart);

//  여기서 받은 스트링 처리 하면 된다.
  }
}

void Serial_get1() {   // parsing packet
  uint8_t d;

  while (q1uart.nBytes) {  // 계속 빼줌
    d = q1uart.buf[q1uart.tail]; 
    HAL_UART_Transmit(&huart1, &d, 110);   //    printf("-%c", d);
    MinusByte1(&q1uart);
//  여기서 받은 스트링 처리 하면 된다.
  }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {  // 이거  안네 print 문 넣지 말것.. 동작 잘 안됨.
  pQUart pQ;

  if (huart->Instance == USART1) {
    pQ = &q1uart;

    if (pQ->nBytes < RXBUFSIZE)   // 넘으면 버림.  빨리 빼줘야 함.
    {
      pQ->buf[pQ->head] = pQ->d;  // 1 byte 넣기..
      pQ->head = (pQ->head == (RXBUFSIZE - 1)) ? 0 : (pQ->head + 1);
      pQ->nBytes++;
    }
    HAL_UART_Receive_IT(huart, &(pQ->d), 1);   // 1 byte receive
    } 
    else if (huart->Instance == USART6) {
      pQ = &q6uart;

      if (pQ->nBytes < RXBUFSIZE)   // 넘으면 버림.  빨리 빼줘야 함.
      {
        pQ->buf[pQ->head] = pQ->d;  // 1 byte 넣기..
        pQ->head = (pQ->head == (RXBUFSIZE - 1)) ? 0 : (pQ->head + 1);
        pQ->nBytes++;
      }
      HAL_UART_Receive_IT(huart, &(pQ->d), 1);   // 1 byte receive
    }
  }
}

===========================================

그리고, 자동 생성되는 코드 serial uart 부

 

usart.c

===========================================

UART_HandleTypeDef huart1;
UART_HandleTypeDef huart6;

void MX_USART1_UART_Init(void)   // 초기화 9600n81 로 설정
{
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
}

void MX_USART6_UART_Init(void)
{
  huart6.Instance = USART6;
  huart6.Init.BaudRate = 57600;
  huart6.Init.WordLength = UART_WORDLENGTH_8B;
  huart6.Init.StopBits = UART_STOPBITS_1;
  huart6.Init.Parity = UART_PARITY_NONE;
  huart6.Init.Mode = UART_MODE_TX_RX;
  huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart6.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart6) != HAL_OK)
  {
    Error_Handler();
  }
}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART1)   // PA9, PA10 을 uart 로 쓰겠다 라고 설
  {
    __HAL_RCC_USART1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */

    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 00);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
  }
  else if(uartHandle->Instance==USART6)
  {
    __HAL_RCC_USART6_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**USART6 GPIO Configuration
    PC6     ------> USART6_TX
    PC7     ------> USART6_RX
    */

    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF8_USART6;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    /* USART6 interrupt Init */
    HAL_NVIC_SetPriority(USART6_IRQn, 00);
    HAL_NVIC_EnableIRQ(USART6_IRQn);
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspDeInit 0 */
  /* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();

    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */

    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

    /* USART1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USART1_IRQn);
  }
  else if(uartHandle->Instance==USART6)
  {
    /* Peripheral clock disable */
    __HAL_RCC_USART6_CLK_DISABLE();

    /**USART6 GPIO Configuration
    PC6     ------> USART6_TX
    PC7     ------> USART6_RX
    */

    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_6|GPIO_PIN_7);

    /* USART6 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USART6_IRQn);
  }
}

===========================================

 

 

stm32f2xx_it.c

===========================================

extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart6;

void My_UART_IRQHandler(UART_HandleTypeDef *huart);

void USART1_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart1);
// My_UART_IRQHandler(&huart1);
}

void USART6_IRQHandler(void)
{
// My_UART_IRQHandler(&huart6);
  HAL_UART_IRQHandler(&huart6);
}

===========================================

 

이렇게 하면 송신은 그냥 보내고

수신은 interrupt 로 받는 거를 기본으로 사용 하는 거 이다.

 

===========================================

===========================================

===========================================

 

그런데, 혹시 안되면 수신 IRQHandler 를 변경 하는 다음 사항을 해 보셔요..

 

 

먼저 Serial.c  에 IRQHandler 추가

===========================================

void My_UART_IRQHandler(UART_HandleTypeDef *huart) {  // 최대한 간결하게 Quue 에 넣음.
  pQUart  pQ = (huart->Instance == USART1 ? &q1uart : &q6uart);

  if ((__HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE) != RESET)) {
    if (pQ->nBytes < RXBUFSIZE)   // 넘으면 버림.  빨리 빼줘야 함.
    {
      pQ->buf[pQ->head] = (uint8_t) (huart->Instance->DR & (uint8_t) 0x00FF);  // 1 byte 넣기..
      // HAL_UART_Transmit(&huart6, &c, 1, 10);  // 여기(int 안)에서 이문장 쓰면 이빨 빠짐
      pQ->head = (pQ->head == (RXBUFSIZE - 1)) ? 0 : (pQ->head + 1);
      pQ->nBytes++;
    }
  }

  __HAL_UART_CLEAR_PEFLAG(huart); /* clear event flag */
  // HAL_UART_Receive_IT(&huart6, &g_u8rx6a[0], 1);   // 1 byte receive  하라는거 여기서 필요 없어서 막음.
}

===========================================

 

그리고,  수신 IRQHandler 를 내가 만든 함수를 사용 하도록 변경 입니다.

stm32f2xx_it.c

===========================================

extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart6;

void My_UART_IRQHandler(UART_HandleTypeDef *huart);

void USART1_IRQHandler(void)
{
  //  HAL_UART_IRQHandler(&huart1); 기본 제공 막고
  My_UART_IRQHandler(&huart1);
}

void USART6_IRQHandler(void)
{
  My_UART_IRQHandler(&huart6);
  //  HAL_UART_IRQHandler(&huart6);
}
===========================================

 

stm32_uart.zip
0.67MB

반응형