Как получить данные с HAL_UART? - PullRequest
1 голос
/ 30 мая 2019

Я узнаю о STM32.Я хочу получать данные от UART побайтно с прерыванием.

HAL_UART_Receive_IT(&huart1, buffer, length)

Где & huart1 - мои ворота uart, буфер - это хранилище ввода, а длина - количество входных байтов.Я использую следующую функцию для чтения данных

static requestRead(void *buffer, uint16_t length)
{
    uint8_t teste;
    while (HAL_UART_Receive_IT(&huart1, buffer, length) != HAL_OK) osDelay(1);
    //HAL_UART_RxCpltCallback
}

Я храню свои данные в:

void StartDefaultTask(void const *argument)
{
    char sender[] = "Alaska Sending\n";
    uint8_t receive[10];
    uint8_t data[30];

    for (;;)
    {
        uint8_t i = 0;
        memset(data, 0, 30);

        requestRead(&receive, 1);
        data[i++] = receive;

        while (data != '\r')
        {
            requestRead(&receive, 1);
            data[i++] = receive;
        }

        //HAL_UART_Transmit(&huart1, data, i, HAL_MAX_DELAY);

    }
    /* USER CODE END StartDefaultTask */
}

Моя проблема заключается в получении и сохранении значения.Когда я посылаю последовательностью строку символов в виде Добро пожаловать на Аляску \ n , только W читается и сохраняется, тогда мне нужно снова отправить буфер и снова просто сохранить только W. Как решить эту проблему?

1 Ответ

0 голосов
/ 31 мая 2019

Ну, здесь есть несколько проблем.

Массивы и их содержимое

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.

...