UART发送UART后未能获得在STM32 HAL库

问题描述:

我使用STM32F1(STM32F103C8T6),以开发使用FreeRTOS的一个项目线程启动。UART发送UART后未能获得在STM32 HAL库

以下是我的GPIO以及USART1接口配置:

__GPIOA_CLK_ENABLE(); 
    __USART1_CLK_ENABLE(); 

    GPIO_InitTypeDef GPIO_InitStruct; 
    GPIO_InitStruct.Pin = GPIO_PIN_9; 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; 
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 

    GPIO_InitStruct.Pin = GPIO_PIN_10; 
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 
    GPIO_InitStruct.Pull = GPIO_NOPULL; 
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 

    huart1.Instance = USART1; 
    huart1.Init.BaudRate = 9600;//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_RX; 
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; 
    HAL_UART_Init(&huart1); 

    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); 
    HAL_NVIC_EnableIRQ(USART1_IRQn); 

的问题是:为什么UART发送工作之前线程开始,但线程启动后不或线程?我想从线程传输数据。即

int main(void) 
{ 
    Initializations(); 

    //THIS WORKS!! 
    uart_transmit_buffer[0] = 'H'; 
    uart_transmit_buffer[1] = 'R'; 
    uart_transmit_buffer[2] = '#'; 
    uint8_t nums_in_tr_buf = 0; 
    nums_in_tr_buf = sizeof(uart_transmit_buffer)/sizeof(uint8_t); 
    state = HAL_UART_Transmit(&huart1, uart_transmit_buffer, nums_in_tr_buf, 5000); 

    StartAllThreads(); 
    osKernelStart(); 

    for (;;); 
} 

static void A_Random_Thread(void const *argument) 
{ 
     for(;;) 
     { 
     if (conditionsMet()) //Executed once when a proper response received. 
     { 
      //BUT NOT THIS :(!! 
      uart_transmit_buffer[0] = 'H'; 
      uart_transmit_buffer[1] = 'R'; 
      uart_transmit_buffer[2] = '#'; 
      uint8_t nums_in_tr_buf = 0; 
      nums_in_tr_buf = sizeof(uart_transmit_buffer)/sizeof(uint8_t); 
      state = HAL_UART_Transmit(&huart1, uart_transmit_buffer, nums_in_tr_buf, 5000); 
     } 
     } 
} 

我确定没有线程处于死锁状态。问题是UART_HAL_Transmit给出了HAL_BUSY状态。

而且,我有专门的一个线程接收和UART RX解析信息,我怀疑这可能是问题的原因。以下是代码:

static void UART_Receive_Thread(void const *argument) 
{ 
    uint32_t count; 
    (void) argument; 
    int j = 0, word_length = 0; 

    for (;;) 
    { 
      if (uart_line_ready == 0) 
      { 
        HAL_UART_Receive(&huart1, uart_receive_buffer, UART_RX_BUFFER_SIZE, 0xFFFF); 
        if (uart_receive_buffer[0] != 0) 
        { 
          if (uart_receive_buffer[0] != END_OF_WORD_CHAR) 
          { 
            uart_line_buffer[k] = uart_receive_buffer[0]; 
            uart_receive_buffer[0] = 0; 
            k++; 
          } 
          else 
          { 
            uart_receive_buffer[0] = 0; 
            uart_line_ready = 1; 
            word_length = k; 
            k = 0; 
          } 
        } 
      } 
      if (uart_line_ready == 1) 
      { 
        //osThreadSuspend(OLEDThreadHandle); 
        for (j = 0; j <= word_length; j++) 
        { 
          UART_RECEIVED_COMMAND[j] = uart_line_buffer[j]; 
        } 
        for (j = 0; j <= word_length; j++) 
        { 
          uart_line_buffer[j] = 0; 
        } 
        uart_line_ready = 0; 

        RECEIVED_COMMAND = ParseReceivedCommand(UART_RECEIVED_COMMAND); 
        if (RECEIVED_COMMAND != _ID_) 
        { 
          AssignReceivedData (word_length); //Results in uint8_t * RECEIVED_DATA 
        } 
        //osThreadResume(OLEDThreadHandle); 
      } 
      //Should be no delay in order not to miss any data.. 
    } 
} 

另一个原因,我怀疑可能与系统的中断问题(也请注意初始化部分,我配置NVIC):

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

任何帮助或对此问题的指导将受到高度赞赏。提前致谢。

+1

实际上,您并未使用中断,只是在NVIC中启用UART IRQ,但它也必须位于外设。 'HAL_UART_Receive_IT'做到了'HAL_UART_Receive'没有。进行测试,在其中不启动UART接收线程。 –

+0

我的意思是说,没有UART接收线程它的作品。问题是如何克服这个问题?你是否建议使用HAL_UART_Receive_IT而不是HAL_UART_Receive? – mozcelikors

+0

不,这只是一个与IRQ无关的说法。例如,您的线程可能会尝试同时使用UART并以BUSY状态接管。尝试通过信号量或互斥锁来保护UART的使用。 –

原来,这个问题是事做阻挡语句。 由于UART_Receive_Thread内部有HAL_UART_Receive和被阻塞的线程,直到被接收的东西,这导致在一个繁忙的HAL(因此,HAL_BUSY状态)。

溶液使用无阻塞语句不改变任何东西。 即,使用HAL_UART_Receive_ITHAL_UART_Transmit_IT同时并忽略阻断语句的工作。

感谢导致这种解决方案的所有建议。

使用FreeRTOS操作系统,你必须中断优先级设置为5或以上,因为低于5被保留用于操作系统。 因此改变你的代码的优先级设置为:

HAL_NVIC_SetPriority(USART1_IRQn, 5, 0); 
+0

感谢您的帮助提示,但不幸的是,这并没有解决我的问题。 – mozcelikors

从我所看到的HAL_UART_Transmit将与F4 HAL(。5.0),如果不是因为__HAL_LOCK(huart)工作过。 RX线程会锁定句柄,然后TX线程会尝试锁定并返回HAL_BUSY。 HAL_UART_Transmit_ITHAL_UART_Receive_IT在发送/接收期间不锁定手柄。

这可能会导致State成员出现问题,因为它是由帮助函数UART_Receive_ITUART_Transmit_IT非原子更新的。虽然我不认为这会影响手术。

您可以修改该功能以允许同时进行接收和发送。每次他们发布HAL的新版本时,你都必须更新它。

问题是ST HAL并不意味着要与RTOS一起使用。它在宏__HAL_LOCK的定义中这样说。重新定义它以使用RTOS的互斥体也值得尝试。与HAL_Delay()一样使用RTOS的线程休眠功能。

一般来说,虽然在线程中通过阻塞函数发送应该没问题,但我不会在线程中使用阻塞函数接收数据。你必然会遇到这样的超限错误。

同样,如果在接收中断中进行了太多处理,您可能会遇到溢出错误。我更喜欢使用DMA进行接收,如果我已经用完了DMA流,则会使用中断。中断只将数据复制到缓冲区,与DMA相似。然后使用线程processRxData来处理实际数据。