Skip to main content
Graduate II
April 16, 2024
Solved

Two STM32 - UART communication

  • April 16, 2024
  • 6 replies
  • 6018 views

Hello,

I've been doing a small project lately and ran into a problem in one part. I have two STM32 microcontrollers and I want to communicate both of them with eachother over UART. One of them is designed to send a fixed array of 6 characters

uint8_t k[6]={3,7,9,12,16,19};

The other microcontroller is simply to receive it. When I send a single byte over the UART it all works without a problem. When I want to send the whole array it only fills the first element.This first element is filled with random numbers from this sent array.

I know for sure there is no problem on the sending side. I checked it on an oscilloscope. The problem lies in the receiving side.

I suspect that the problem lies in the timing, but I don't know how to fix it

In both microcontrollers the baud rate is the same – 9600. The data frame is also the same 8N1.

 

RX device code

 

/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

uint8_t buff[6];

/* USER CODE END 0 */

 

/* USER CODE BEGIN WHILE */

while (1)

  {

 

       HAL_UART_Receive(&huart2, buff, sizeof(buff), 10000);

 

/* USER CODE END WHILE */

 

/* USER CODE BEGIN 3 */

  }

/* USER CODE END 3 */

 

TX device code

/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

uint8_t k[6]={3,7,9,12,16,19};

/* USER CODE END 0 */

 

/* USER CODE BEGIN WHILE */

while (1)

  {

       HAL_UART_Transmit(&huart2, k, sizeof(k), 10);

 

/* USER CODE END WHILE */

 

/* USER CODE BEGIN 3 */

 

Raf_al_0-1713282252041.pngRaf_al_1-1713282260393.png

Raf_al_2-1713282267462.png

 

    This topic has been closed for replies.
    Best answer by Andrew Neil

    @Raf_al wrote:

     Even when I start transmission after 10 minutes after power up it fills only first element of the array.


    Again, how do you start that transmission?

    6 replies

    Graduate II
    April 16, 2024

    Perhaps the issue is not with the code you're choosing to share?

    Make sure boards have a common ground, and the RX/TX pair cross over when connecting from one to the other.

    Settings could be wrong, clocks could be wrong.

    You ignore any error returned by the routine. Watch for framing, noise and similar errors.

    Using HSI or HSE clocks? Is HSE_VALUE correct for your board?

    Send 0x55 'U' patterns from each, scope and check the bit timing is consistent with 9600 baud

    Raf_alAuthor
    Graduate II
    April 17, 2024

    Boards have crossed RX and TX. In both STM I used HSI and for both microcontrolers clock settings are the same.

    I checked the timing for both microcontrolers (I send 0x55 to have this rectangular transmision shape) and bit duration is 104us so it seems like it is ok.

    Also I checked what this HAL_UART_Transmit function returns and sometimes it returns HAL_TIMEOUT and sometimes HAL_OK

    Grounds are OK. I power supply both microcontrollers from the same source.

    Super User
    April 16, 2024

    @Raf_al wrote:

    One of them is designed to send a fixed array of 6 characters

    uint8_t k[6]={3,7,9,12,16,19}


    What do you mean by "characters" there?

    That array isn't going to give you human-readable ASCII text characters!

    If you made them actual characters, you could test your code against a PC terminal; eg,

     

    uint8_t k[6]={ '3', '7', '9', 'A', 'B', 'C' };

     

     

    Please use this button to properly post source code:

    AndrewNeil_0-1713284992874.png

     


    @Raf_al wrote:

    it only fills the first element.This first element is filled with random numbers from this sent array.


    How are you starting the transmission?

    Beware that it's common to get a "junk" character or two when a microcontroller first starts (from reset or power-up) - dues to glitches as the pins go from their default state to their configured states.

    As @Tesla DeLorean suggests, such glitches could well give you Framing errors, etc, which would mess up the reception ...

    Raf_alAuthor
    Graduate II
    April 17, 2024

    That's my mistake. I mean integers not characters. Even when I start transmission after 10 minutes after power up it fills only first element of the array.

    Super User
    April 17, 2024

    @Raf_al wrote:

     Even when I start transmission after 10 minutes after power up it fills only first element of the array.


    Again, how do you start that transmission?

    Raf_alAuthor
    Graduate II
    April 17, 2024

    Basically there is no start for the transmission. TX device is sending this array all the time and RX device is trying to catch this.

    So if I understand this correctly. I need to "align" both devices to start transmit and receive at the same time?

    Super User
    April 17, 2024

    @Raf_al wrote:

    Basically there is no start for the transmission.


    Now I'm confused!

    So what did you mean by, "when I start transmission after 10 minutes after power up" ?

     


    @Raf_al wrote:

    So if I understand this correctly. I need to "align" both devices to start transmit and receive at the same time?


    Well, your receiver code is expecting to receive exactly 6 bytes - so, unless it's ready when the transmitter starts transmitting, it's going to miss some or all of the transmission.

    Raf_alAuthor
    Graduate II
    April 17, 2024



    @Raf_al wrote:

    So if I understand this correctly. I need to "align" both devices to start transmit and receive at the same time?


    Well, your receiver code is expecting to receive exactly 6 bytes - so, unless it's ready when the transmitter starts transmitting, it's going to miss some or all of the transmission.



    OK, tomorrow I will do test, beacuse now I dont have access to those boards. First I will power up receiver and it will be waiting to receive 6 bytes (I will change timeout in receive function to HAL_MAX_DELAY). Then I will change code on TX side a little bit, and after pushing some button I will send those 6 bytes.


     


    @Andrew Neil wrote:

    @Raf_al wrote:

    Basically there is no start for the transmission.


    Now I'm confused!

    So what did you mean by, "when I start transmission after 10 minutes after power up" ?

     


    Better not to admit it :face_with_tears_of_joy::face_with_tears_of_joy:

     

    Graduate II
    April 17, 2024

    Always check the return codes from both ..._Transmit() and ..._Receive().

    I'd suggest adding a delay to the transmitter so it only pops off the 6 bytes once every 3 seconds or so.  A continuous stream of bytes really does you no good at this point.

    Graduate II
    April 17, 2024

    Try using interrupt method instead of polling. 

     

    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    uint8_t buff[6];
    volatile bool dataRdy = false;
    /* USER CODE END 0 */
    
    /**
     * @brief The application entry point.
     * @retval int
     */
    int main(void)
    {
    
     /* USER CODE BEGIN 1 */
    
     /* USER CODE END 1 */
    
     /* MCU Configuration--------------------------------------------------------*/
    
     /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
     HAL_Init();
    
     /* USER CODE BEGIN Init */
    
     /* USER CODE END Init */
    
     /* Configure the system clock */
     SystemClock_Config();
    
     /* USER CODE BEGIN SysInit */
    
     /* USER CODE END SysInit */
    
     /* Initialize all configured peripherals */
     MX_GPIO_Init();
     MX_USART2_UART_Init();
     /* USER CODE BEGIN 2 */
     HAL_UART_Receive_IT(&huart2, buff, sizeof(buff)); // initialize to receive
     /* USER CODE END 2 */
    
     /* Infinite loop */
     /* USER CODE BEGIN WHILE */
     while (1)
     {
    	 if(dataRdy)
    	 {
    		 dataRdy = 0;
    		 if(buff[0] == 3) // check to see if first byte is 3
    		 {
    			 HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); // toggle led if data is valid
    		 }
    	 }
    
    
     /* USER CODE END WHILE */
    
     /* USER CODE BEGIN 3 */
     }
     /* USER CODE END 3 */
    }
    
    
    
    /* USER CODE BEGIN 4 */
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
    	if(huart == &huart2)
    	{
    		dataRdy = true;
    		HAL_UART_Receive_IT(&huart2, buff, sizeof(buff)); // re-initialize again
    	}
    }
    /* USER CODE END 4 */
    

     

    Add a delay to your transmit

    /* Private user code ---------------------------------------------------------*/
    
    /* USER CODE BEGIN 0 */
    
    uint8_t k[6]={3,7,9,12,16,19};
    
    /* USER CODE END 0 */
    
     
    
    /* USER CODE BEGIN WHILE */
    
    while (1)
    
     {
    
     HAL_UART_Transmit(&huart2, k, sizeof(k), 10);
     HAL_Delay(10);
     
    
    /* USER CODE END WHILE */
    
     
    
    /* USER CODE BEGIN 3 */

     

    Make sure you have NVIC enabled

    KarlYamashita_0-1713386850733.png

     

    Raf_alAuthor
    Graduate II
    April 18, 2024

    So I did what I wrote in my previous post:

     


    @Raf_al wrote:

    OK, tomorrow I will do test, beacuse now I dont have access to those boards. First I will power up receiver and it will be waiting to receive 6 bytes (I will change timeout in receive function to HAL_MAX_DELAY). Then I will change code on TX side a little bit, and after pushing some button I will send those 6 bytes.

     

     


    And it works like a charm. Problem was with timing, probably my receive hit somewhere in the middle of transmit frame.

    Thanks for help.