Драйвер STM32F4 UART HAL 'сохраняет строку в буфере переменных'

Я в процессе написания программного обеспечения для STM32F4. STM32 необходимо протянуть строку через UART. Эта строка имеет переменную длину и поступает от датчика каждую секунду. Строка хранится в фиксированном буфере, поэтому содержимое буфера постоянно изменяется.

Входящая строка выглядит так: A12941; P2507; T2150; C21; E0;

Настройки UART:

  • Скорость передачи: 19200
  • Длина слова: 8 бит
  • Четность: Нет
  • Остановить ставки: 1
  • Передискретизация: 16 образцов
  • Глобальное прерывание: включено
  • Нет настроек DMA

Часть используемого кода в функции main.c:

uint8_t UART3_rxBuffer[25];

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    HAL_UART_Receive_IT(&huart3, UART3_rxBuffer, 25); //restart interrupt reception mode

    
int main(void)
{  
  HAL_UART_Receive_IT (&huart3, UART3_rxBuffer,25);
}
  while (1)
  {
  }
}

Часть кода в stm32f4xx_it.c

void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */
  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
  /* USER CODE BEGIN USART3_IRQn 1 */
  /* USER CODE END USART3_IRQn 1 */
}

Это действительно работает, чтобы заполнить буфер переменными строками таким образом, но поскольку буфер постоянно пополняется, трудно извлечь начало и конец строки. Например, буфер может выглядеть так: [0] 'E' [1] '0' [2] '/ n' [3] 'A' [4] '1' [5] '2' [6] '9' [7] '4' [8] '1' [9] ';' [10] «P» и т. Д. Но я бы хотел иметь буфер, который начинается с «A».

У меня вопрос, как я могу правильно обрабатывать входящие строки на uart, чтобы у меня была только строка A12941; P2507; T2150; C21; E0 ;?

Заранее спасибо!!


person Elektro17    schedule 22.04.2021    source источник


Ответы (2)


Я вижу три возможности:

  1. Выполняйте всю свою обработку в прерывании. Когда вы дойдете до конца сообщения переменной длины, сделайте все, что вам нужно сделать с информацией, а затем измените переменную местоположения, чтобы перезапустить заполнение буфера с самого начала.

  2. Используйте (как минимум) два буфера параллельно. Когда вы обнаруживаете конец сообщения переменной длины в контексте прерывания, то начинаете заполнять другой буфер с нулевой позиции и сигнализируете основному контексту, что предыдущий буфер готов к обработке.

  3. Используйте два буфера последовательно. Позвольте прерыванию заполнить кольцевой буфер циклическим образом, не обращая внимания на то, когда сообщение заканчивается. В основном контексте просканируйте с конца предыдущего сообщения, чтобы увидеть, есть ли у вас еще целое сообщение. Если вы это сделаете, скопируйте его в другой буфер таким образом, чтобы он начинался с начала буфера. Запишите, где он закончился, в кольцевом буфере для следующего раза, а затем выполните обработку в линейном буфере.

Вариант 1 подходит только в том случае, если вы можете выполнить всю обработку за меньшее время, чем требуется передатчику для отправки следующего или двух байтов. Два других варианта используют немного больше памяти, и их немного сложнее реализовать. Вариант 3 может быть реализован с DMA в круговом режиме, если вы достаточно часто запрашиваете новые сообщения, что позволяет избежать прерываний. Вариант 2 позволяет ставить в очередь несколько сообщений, если ваш основной контекст может опрашиваться недостаточно часто.

person Tom V    schedule 23.04.2021
comment
Спасибо, что ответили на мой вопрос. Хорошо, тогда вариант 3 кажется мне лучшим. У вас есть образец кода для этого? - person Elektro17; 23.04.2021

Я хотел бы поделиться образцом кода, связанным с вашей проблемой. Однако это не совсем то, что вы ищете. Вы можете редактировать этот фрагмент кода по своему усмотрению. Если я не ошибаюсь, вы также можете отредактировать его в соответствии с вариантом 3.

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART2) {
    HAL_UART_Receive_IT(&huart2,&rData,1);

    rxBuffer[pos++] = rData;
    if (rData == '\n') {
        pos = 0;
    }
}

Перед запуском в основной функции перед циклом while вы должны разрешить прерывание для одного байта, используя HAL_UART_Receive_IT (& huart2, & rData, 1) ;. Если ваши входящие данные имеют ограничитель, например '\ n', вы можете сохранять целые данные, которые могут иметь разную длину для каждого кадра.

Если вы хотите, чтобы фрейм данных начинался с определенного символа, вы можете подождать, чтобы сохранить данные, пока не получите этот символ. В этом случае вы можете отредактировать этот код, изменив '\ n' в качестве своего символа, и после того, как вы получите этот символ, вы должны начать сохранять следующие данные внутри буфера.

person karamelekrobotics    schedule 25.04.2021