1
votes

I'm trying to establish communication between two STM32F103 MCU's via UART. I'm using STMCubeMX to build peripheral initalization. I've logicaly named the MCU's as MASTER and SLAVE. Slave UART is configured as Transmit only, while MASTER uart is recieve only. I'm using HAL drivers to program the MCU in AtollicTRUEstudio IDE. I want to send uint32_t value, buffer_USART1_rx is declared as volatile uint8_t buffer_USART1_rx[10]. Basicly SLAVE UART transmit is being triggered by Systick timer every 1 second, while MASTER UART is defined in IT mode, and soon as the interrupt happens it read the transmited value.

I connected the osciloscope probe to the PA10 RX pin of MASTER and i noticed the UART signal is fine and transmiting over the wires. But the value being transmitted is always 0 and breakpoint in HAL_UART_RxCpltCallback is never activated. Since the osciloscope signal is correct, i'm thinking it's a software issue. Image of RX PA10 pin of MASTER stm32

This is from MASTER STM (code is located in main file)

UART initialization:

static void MX_USART1_UART_Init(void)
{

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}
static void MX_NVIC_Init(void)
{

  /* USART1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(USART1_IRQn);

}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
     __NOP();
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    /*UART1 water level from SLAVE */
 if(huart->Instance==USART1)
 {

     water_level=getUSART1();

     /* Water level change triggers LCD refresh */
     if(water_level_prev!=water_level)
     {
         lcd_screen_refresh=true;
     }
     water_level_prev=water_level;

 }
 else
 {
     __NOP();
 }
 /*UART2 target level from NANOPI */
if(huart->Instance==USART2)
 {
    target_level_pi=getUSART2();

    /* Target level change triggers LCD refresh */
    if(target_level_pi!=target_level_prev)
    {
        lcd_screen_refresh=true;
    }

 }
else
{
     __NOP();
}
}

UART deserialize function:

uint32_t getUSART1()
{

    uint32_t num=0;

    num |= buffer_USART1_rx[0] << 24;
    num |= buffer_USART1_rx[1] << 16;
    num |= buffer_USART1_rx[2] << 8;
    num |= buffer_USART1_rx[3];

    return num;
}

In main file initialization of UART in IT mode:

/* Initialize TIM/UART interrupts */
  HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_1);
  HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_2);
  HAL_UART_Receive_IT(&huart1, buffer_USART1_rx, 4);

SLAVE MCU configuration :

// This is in while loop
      if(send_USART==true)
      {
          buffer[0] = test ;
          buffer[1] = test >>8;
          buffer[2] = test >> 16;
          buffer[3] = test >> 24;
          HAL_UART_Transmit(&huart1,buffer,4,2000);

      }
      else
      {
          __NOP();
      }

// Callback
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    send_USART=false;
}

//Systick timer triggers UART transmit every 1 second

void HAL_SYSTICK_Callback()
{
    sys_timer++;
    if(sys_timer>=1000)
    {
        sys_timer=0;
        send_USART=true;

    }
    else
    {
        __NOP();
    }
}

//Global declaration of variables used

/* Timer variables */
uint8_t buffer[10];
volatile uint32_t sys_timer=0;
uint32_t test=10;

/* Boolean variables */
bool send_USART=false;

// UART initialization

/* USART1 init function */
static void MX_USART1_UART_Init(void)
{

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}
static void MX_NVIC_Init(void)
{

  /* USART1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);
  HAL_NVIC_EnableIRQ(USART1_IRQn);
}

I expect the recieved value to be 10. (since i'm serializing "test" variable on SLAVE stm, and sending it on MASTER stm while deserializing it)

1
The code looks OK, except that the slave never calls HAL_UART_TxCpltCallback() because it's not using interrupts, that's why the transmissions follow each other immediately. Reset the flag immediately after HAL_UART_Transmit(). Checklist: - All initialization functions are indeed called - GPIOA and USART1 clocks in RCC are enabled (bits in RCC->APB2ENR) - GPIOA10 is floating input (GPIOA->CRH) - USART1 is not remapped (AFIO->MAPR) - USART1_IRQHandler() function calls HAL_USART_IRQHandler(&huart1), set a breakpoint to see if it's indeed called - contents of USART1->SRfollowed Monica to Codidact
Firstly i've reset the flag immediately and it didn't work at all. When i've moved it to CpltCallback it worked but only once. I'll try to do it like you said here hopefully it will work. Thanks.Robert Sabljo
@berendi Same thing happens, MASTER uart only reads it once and thats it. I'm thinking maybe uart IRQ on master side doesn't get reset.Robert Sabljo
Have you gone through the checklist? What did you find?followed Monica to Codidact
Nevermind i've found the issue, i've posted it below. Thanks for your help anyways, it led me to the solution. Cheers.Robert Sabljo

1 Answers

0
votes

Nevermind, i've found the issue and what was causing it

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
    if(huart1.RxState==HAL_UART_STATE_READY)
    {
        HAL_UART_Receive_IT(&huart1,buffer_USART1_rx,4);
        uart1_received=4; //flag da je primljen podatak
        __HAL_UART_FLUSH_DRREGISTER(&huart1);
        __HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXNE);
    }
    else
    {
        __NOP();
    }
  /* USER CODE END USART1_IRQn 1 */
}

The code for handling was above the HAL_UART_IRQHandler(&huart1); . That's why it only recieved data once. When I copied it below like on the code above, everything works fine.