Получение IrDA-сообщения на STM32H7

#c #stm32 #cortex-m #infrared #usart

#c #stm32 #cortex-m #инфракрасный #usart

Вопрос:

Я пытаюсь получить некоторые данные с помощью USART в режиме IrDA на плате STM32H7 с драйверами HAL.

Я получаю ожидаемый ответ на выводе gpio (скорость передачи в бодах, логика и синхронизация в порядке), но по какой-то причине данные никогда не перемещаются в регистр RDR USART, и когда я пытаюсь их прочитать, я просто получаю нули с первой попытки и тайм-аут после этого (режим опроса).

После заполнения структуры дескриптора IRDA я вызываю HAL_IRDA_DeInit() и HAL_IRDA_Init() . Я настраиваю GPIO в HAL_IRDA_MSP_Init() и отправляю первое сообщение, которое достигает цели (с помощью HAL_IRDA_Transmit() ). Затем цель отправляет ответ, который я могу проверить по pin-коду UART_RX. И здесь что-то происходит.. или лучше не происходит. Если я прочитаю UART с HAL_IRDA_Receive() (по 1 байту за раз) Я получаю только ноль, а затем тайм-ауты.

 IRDA_HandleTypeDef hirda4;

void vIrdaInit(void)
{
    hirda.Instance = USART3;
    hirda.Init.BaudRate = 60100;
    hirda.Init.WordLength = IRDA_WORDLENGTH_9B;
    hirda.Init.Parity = IRDA_PARITY_NONE;
    hirda.Init.Mode = IRDA_MODE_TX_RX;
    hirda.Init.Prescaler = 1;
    hirda.Init.PowerMode = IRDA_POWERMODE_NORMAL;

    /* Initialize the IRDA registers. Here also HAL_IRDA_MspInit() will be called */
    if (HAL_IRDA_Init(amp;hirda4) != HAL_OK)
    {
        Error_Handler();
    }

}
  
 /* Initialize IrDA low level resources. This function is called by HAL_IRDA_Init() */
void HAL_IRDA_MspInit(IRDA_HandleTypeDef* irdaHandle)
{

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(irdaHandle->Instance==USART3)
    {
        /* UART4 clock enable */
        __HAL_RCC_USART3_CLK_ENABLE();
        __HAL_RCC_GPIOB_CLK_ENABLE();

        /**UART4 GPIO Configuration
        PB10     ------> USART3_RX
        PB11     ------> USART3_TX
        */
        GPIO_InitStruct.Pin = GPIO_PIN_10;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
        GPIO_InitStruct.Alternate = GPIO_AF7_UART3;
        HAL_GPIO_Init(GPIOB, amp;GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_11;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        HAL_GPIO_Init(GPIOB, amp;GPIO_InitStruct);
    }
}

  

здесь выполняется вызов HAL_IRDA_Transmit()/HAL_IRDA_Receive():

 if(HAL_IRDA_Transmit(amp;hirda (uint8_t*)TxBuf, sizeof(RxBuf), 5000)!= HAL_OK)
{
    Error_Handler();
} 


memset(RxBuf, '', sizeof(RxBuf));
for (i = 0; i < 8; i  )
{
    // blocks here until timeout or data
    if(HAL_IRDA_Receive(amp;hirda, (uint8_t*)RxBuf, 1, 500)!= HAL_OK)
    {
        Error_Handler();
    } 
}
  

При первом запуске цикла у меня поднят флаг RXNE, но в RDR есть только 0. Следующие итерации всегда приводят к таймауту (от IRDA_WaitOnFlagUntilTimeout() ). Я понятия не имею, где искать… Импульсы, которые я получаю, больше, чем 3/16 периода, уровни в порядке, но, похоже, я не могу получить сообщение через декодер приема SIR и в регистре данных.

ОБНОВЛЕНИЕ: вот скриншот с принятым сигналом: IrDA_RX

Скорость передачи в бодах в норме, присутствуют стартовые и стоповые биты, и сообщение (9 бит) — это то, чего я жду. Но не распознается декодером и не передается UART.

Ответ №1:

Добавление фиктивного чтения в 1 байт сразу после вызова функции init позволило мне успешно прочитать один раз без тайм-аутов. Проблема в том, что после этого Receive() функция снова начинает возвращать тайм-ауты. Единственное обходное решение, которое я смог найти, это повторно инициализировать UART непосредственно перед вызовом Receive() функции. Это позволяет мне получить полное сообщение. Это неаккуратно, но это работает.

Я пытался найти регистры, которые изменяются, но мне не удалось определить, что вызывает проблему.