Skip to main content
Graduate
March 13, 2024
Question

HAL_UART_Receive_IT not resetting after HAL_UART_Transmit

  • March 13, 2024
  • 1 reply
  • 1169 views

I am trying to implement MODBUS protocol. STM32 receives an initial message of 8 bytes and then send a response of 8 bytes. However, the next message received by the STM32 doesn't trigger the HAL_UART_Receive_IT callback.

 

uint8_t reception_complete = FALSE; // turns true when a MODBUS command is received
uint8_t response[8];
uint8_t response_ready = FALSE;

int main(void)
{	
 while (1)
	{
		// Hang until a MODBUS message is received (8 bytes)
		while(reception_complete != TRUE)
		{
			HAL_UART_Receive_IT(&huart2, &recvd_data, 1);
			if (response_ready == TRUE)
			{
				//send the response back to the master (blocking mode)
				uint16_t resp_len = sizeof(response);
				HAL_UART_Transmit(&huart2, (uint8_t*)response, resp_len, HAL_MAX_DELAY);
				response_ready = FALSE;
			}
	 }
 }
}

 

jlaufer_0-1710358749228.png

 

    This topic has been closed for replies.

    1 reply

    Graduate II
    March 13, 2024

    Don't create these false interdependencies...

    HAL_UART_Transmit() blocks.

    Have your receive callback light off the next HAL_UART_Receive_IT() so you don't miss it, but first move the received data into a holding buffer that's not going to be overwritten by the inbound data should more of that arrive in the mean time while you're ignoring it. ie >resp_len byte times..

     

    jlauferAuthor
    Graduate
    March 13, 2024

    That's actually how I had it originally but changed it because I thought maybe calling HAL_UART_Transmit() from HAL_UART_Receive_IT() could have been causing the issue. 

     

    I put it back to how it was with the exact same result. I placed breakpoints and I can see that execution is making it to the HAL_UART_Receive_IT(&huart2, &recvd_data, 1); but it just isn't jumping to the Interrupt after HAL_UART_Transmit() is called.

     

    //MODBUS params
    uint8_t data_buffer[100];
    uint8_t recvd_data; //will hold bytes received on RX pin
    uint8_t reception_complete = FALSE; // turns true when a MODBUS command is received
    uint8_t char_count = 0; // counts up number of bytes received
    uint8_t slave_address = 200;
    uint8_t modbus_code = 0;
    uint8_t response[8];
    
    //values
    uint8_t motor1_spd_reg = 0;
    uint16_t registers[100];
    uint8_t reg_changed[100];
    
    int main(void)
    {
    	HAL_Init();
    
    	SystemClock_Config(SYS_CLOCK_FREQ_48_MHZ);
    
    	uint32_t clk_freq = Get_PCLK1TIM();
    
    	UART2_Init();
    
    	while (1)
    	{
    		HAL_UART_Receive_IT(&huart2, &recvd_data, 1);
    
    		// Check and see if there has been any updates to the register values
    		if (reg_changed[motor1_spd_reg])
    		{
    			// pulse = clk_spd * (1 /(2*freq))
    			uint32_t pulse_freq = registers[motor1_spd_reg];
    			uint32_t pulse = clk_freq * (1 / (2 * pulse_freq));
    			//based on the frequency given by the user
    			TIMER2_CH1_Init(pulse);
    			//Start the timer
    			if(HAL_TIM_OC_Start_IT(&htimer2, TIM_CHANNEL_1) != HAL_OK)
    			{
    				Error_handler();
    			}
    			reg_changed[motor1_spd_reg] = FALSE;
    		}
    	}
    }
    
    void UART2_Init(void)
    {
    	huart2.Instance = USART2;
    	huart2.Init.BaudRate = 115200;
    	huart2.Init.WordLength = UART_WORDLENGTH_8B;
    	huart2.Init.StopBits = UART_STOPBITS_1;
    	huart2.Init.Parity = UART_PARITY_NONE;
    	huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    	huart2.Init.Mode = UART_MODE_TX_RX;
    	if (HAL_UART_Init(&huart2) != HAL_OK)
    	{
    		Error_handler();
    	}
    }
    
    // count number of received bits and after enough, read MODBUS message
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
    	data_buffer[char_count] = recvd_data;
    	if(char_count == 1)
    	{
    		modbus_code = recvd_data;
    	}
    	if (modbus_code < 7 && char_count == 7)
    	{
    		//8 bytes
    		reception_complete = TRUE;
    		Decode_MODBUS();
    	} else
    	{
    		if (modbus_code >= 7 && char_count >= 6)
    		{
    			// For MODBUS messages with codes 7 and up, the 6th byte indicates how many bytes are left in the message
    			if (char_count == data_buffer[4] + 8)
    			{
    				reception_complete = TRUE;
    				Decode_MODBUS();
    			}
    		}
    	}
    	if (reception_complete == FALSE)
    	{
    		char_count++;
    	}
    	else
    	{
    		char_count = 0;
    		reception_complete = FALSE;
    	}
    }
    
    /***********************************STANDARD MODBUS FUNTIONS ********************************************/
    void Decode_MODBUS(void)
    {
    	if (data_buffer[0] == slave_address)
    	{
    		// The response begins as an echo
    		for (uint8_t i = 0; i<7; i++)
    		{
    			 response[i] = data_buffer[i];
    		}
    
    		response[7] = Calculate_checkSum();
    
    		// Different actions depending on the MODBUS code (2nd byte)
    		if (data_buffer[2] == 0)
    		{
    			//write GPIO
    			GPIO_TypeDef *GPIOx;
    			if (data_buffer[4] == 0)
    				GPIOx = GPIOA;
    			if (data_buffer[4] == 1)
    				GPIOx = GPIOB;
    			if (data_buffer[4] == 2)
    				GPIOx = GPIOC;
    			if (data_buffer[4] == 3)
    				GPIOx = GPIOD;
    
    			uint8_t pinstate;
    			if (data_buffer[5] == PIN_HIGH)
    			{
    				pinstate = GPIO_PIN_SET;
    			}
    			if (data_buffer[5] == PIN_LOW)
    			{
    				pinstate = GPIO_PIN_RESET;
    			}
    
    			HAL_GPIO_WritePin(GPIOx, data_buffer[3], pinstate);
    		}
    		if (data_buffer[2] == 1)
    		{
    			//read GPIO
    			GPIO_TypeDef *GPIOx;
    			if (data_buffer[4] == 0)
    				GPIOx = GPIOA;
    			if (data_buffer[4] == 1)
    				GPIOx = GPIOB;
    			if (data_buffer[4] == 2)
    				GPIOx = GPIOC;
    			if (data_buffer[4] == 3)
    				GPIOx = GPIOD;
    
    			response[5] = HAL_GPIO_ReadPin(GPIOx, data_buffer[3]);
    		}
    		if (data_buffer[2] == 2)
    		{
    			//write value
    			uint8_t reg_num = data_buffer[3];
    			uint8_t data1 = data_buffer[4];
    			uint8_t data2 = data_buffer[5];
    			registers[reg_num] = data2 * 256 + data1;
    
    		}
    		if (data_buffer[2] == 3)
    		{
    			//read value
    			uint8_t reg_num = data_buffer[3];
    			response[4] = registers[reg_num] / 256;
    			response[5] = registers[reg_num] - (data_buffer[3] * 256);
    			reg_changed[reg_num] = TRUE;
    		}
    		if (data_buffer[2] == 4)
    		{
    			//set pin mode
    			GPIO_TypeDef *GPIOx;
    			if (data_buffer[4] == 0)
    				GPIOx = GPIOA;
    			if (data_buffer[4] == 1)
    				GPIOx = GPIOB;
    			if (data_buffer[4] == 2)
    				GPIOx = GPIOC;
    			if (data_buffer[4] == 3)
    				GPIOx = GPIOD;
    			if (data_buffer[4] == 4)
    				GPIOx = GPIOF;
    
    			GPIO_Init(GPIOx, data_buffer[3], data_buffer[5]);
    
    		}
    		if (data_buffer[2] == 6)
    		{
    			//read analog data
    		}
    
    		//send the response back to the master (blocking mode)
    		uint16_t resp_len = sizeof(response);
    		HAL_UART_Transmit(&huart2, (uint8_t*)response, resp_len, HAL_MAX_DELAY);
    
    	} else {
    		//nothing will happen (message is discarded)
    	}
    }