Ну, здесь есть несколько проблем.
Массивы и их содержимое
data[i++] = receive;
хранит адрес из receive
буфер, значение указателя памяти, в массив data
.Это, конечно, не то, что вы хотите.Поскольку это очень базовая парадигма программирования на C, я бы рекомендовал пересмотреть главу о массивах и указателях в хорошем учебнике по C .
Что вы отправляете и чего ожидаете
while (data != '\r')
Даже если вы получите правильный адрес массива и его значение (см. Выше), вы отправляете строку, оканчивающуюся на '\n'
, и проверяете на наличие символа '\r'
, поэтомуизмените одно или другое, чтобы получить совпадение.
Отсутствует volatile
uint8_t receive[10];
Буфер приема должен быть объявлен volatile
, так как к нему будет осуществляться доступобработчиком прерываний.В противном случае основная программа пропустит запись в буфер, даже если она проверит, завершен ли прием (см. Ниже).
Работа с оборудованием в режиме реального времени
while (HAL_UART_Receive_IT(&huart1, buffer, length) != HAL_OK) osDelay(1);
Это позволило бы прерыванию приема (и обработки ошибок) UART получить один байт.Пока все в порядке, но функция возвращает до получения байта, и, поскольку она вызывается снова немедленно, она вернет HAL_BUSY
во второй раз и будет ждать миллисекунду перед попыткойснова.В эту миллисекунду она пропустит большую часть остальной части передачи, поскольку байты поступают быстрее, чем это, и ваша программа ничего с этим не делает.
Более того, основная программа не проверяет, когда завершен приемвозможно, получая доступ к буферу до того, как обработчик прерываний поместит в него значение.
Если вы получаете данные с использованием прерываний, вам придется что-то делать с этими данными в обработчике прерываний.(Если вы не используете прерывания, а опрашиваете для данных, то убедитесь, что вы уложитесь в срок, установленный скоростью интерфейса).
HAL isне подходит для такого рода задач
HAL не имеет интерфейса для приема данных неизвестной длины, ограниченных определенным значением.Конечно, основная программа может опрашивать приемник по одному байту за раз, но затем она должна гарантировать, что опрос происходит быстрее, чем поступают данные. Другими словами, программа может сделать очень мало, ожидая передачи.
Есть некоторые обходные пути, но я даже не буду сейчас на них намекать, потому что они приведут к взаимоблокировкам в среде RTOS, которые, как правило, возникают в самые неудобные времена, и их довольно сложнорасследовать и правильно избегать.
Вместо этого напишите ваш обработчик прерываний
(все это подробно описано в Справочном руководстве для вашего контроллера)
- установить приоритет прерывания UART
NVIC_SetPriority()
- включить прерывание с помощью
NVIC_EnableIRQ()
- установить бит
USART_CR1_RXNEIE
равным 1
в обработчике прерываний,
- чтение регистра
SR
- , если установлен бит
RXNE
, - чтение данных из регистра данных
- сохранить его в буфере
- установитьглобальный флаг, если он соответствует завершающему символу
- , переключиться на другой буфер, если ожидается больше данных, пока программа обрабатывает первую строку.
Не забудьтеобъявляя объявление всех переменных, к которым обращается обработчик прерывания, как volatile
.