Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная 4 USART.docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
50.78 Кб
Скачать

Приём данных

Приём данных, переданных по протоколу, описанному выше, может быть осуществлён двумя способами: побайтный и приём в целом.

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

Принятые данные по прерыванию записываются в буфер приема и увеличивается счётчик количества необработанных байт. В бесконечном цикле проверяется этот счётчик и, если он отличен от нуля, производится обработка принятых байт, а счётчик необработанных данных уменьшается. Оба процесса приёма и обработки могут идти параллельно, т.к. приём, за исключением записи в буфер, идёт аппаратно и задействует АЛУ.

Этот метод обычно используется, когда неизвестна точная длина пакета и нет никакой последовательности, которая говорит о его окончании. И, если поток данных почти непрерывный (период передачи пакетов сравним с его длительностью). Тогда надо производить обработку пакета предельно быстро. Это обеспечивается эти методом.

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

Недостатком данного алгоритма является его сложность и не применимость, если производится сложный программный алгоритм приёма пакета.

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

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

Буферы приёма

Принимаемые данные перед обработкой должны сохраняться в отдельный, специально созданный для этого массив. Такой массив называется буфер. Есть два способа заполнения массива: Со сбросом в начало и «круглый» буфер.

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

Алгоритм круглого буфера подразумевает, что принятые данные расписываются с начала до конца буфера вне зависимости от принятого пакета, а затем только сбрасываются с начало. Получается запись данных по кругу. Этот алгоритм сложнее, но позволяет принимать данные непрерывно.

Примеры протоколов

Протоколы, рассмотренные ниже, расположены по возрастанию сложности. Именно в таком порядке их лучше всего реализовывать для понимания основных принципов приёма данных.

Однобайтная передача.

Самый простой протокол. Он подразумевает передачу только одного поля – поля команды. Причём это поле длиной один байт. Этот байт передаёт необходимую информацию. Количество различных команд равно 255, чего хватает для решения простых задач управления.

Данный протокол не подразумевает наличия стартовых и стоповых последовательностей. Реализовать его можно достаточно просто:

void USART2_IRQHandler(void)

{

uint8_t Res_data=0;

// Обработка события RXNE (приёма)

if ( USART_GetITStatus(USART2, USART_IT_RXNE) )

{

// очистка бита прерывания

USART_ClearITPendingBit(USART2, USART_IT_RXNE);

//Сюда пишется, что должно произойти приёме одного байта

Res_data = USART_ReceiveData(USART2);//Приняли байт

if (Res_data == 0x01)//Если принятый байт равен 1, …

{

RED_ON();//… зажигаем светодиод.

}

} }

При более сложных задачах, выполняемых достаточно долго. Рекомендуется их выносить в функцию main. Для этого при приёме байта выставляется флаг окончания приема, и этот флаг проверяется уже в функции main. Если флаг установлен, производится обработка принятого байта.

uint8_t receive_flag=0;

uint8_t Res_data=0;

void USART2_IRQHandler(void)

{

// Обработка события RXNE (приёма)

if ( USART_GetITStatus(USART2, USART_IT_RXNE) )

{

// очистка бита прерывания

USART_ClearITPendingBit(USART2, USART_IT_RXNE);

//Сюда пишется, что должно произойти приёме одного байта

Res_data = USART_ReceiveData(USART2);//Приняли байт

receive_flag = 1;

} }

int main()

{

if (receive_flag == 1)

{

receive_flag = 0;//Сбрасываем флаг.

switch (Res_data){

case 0x01:{RED_ON();}break;

case 0x02:{RED_OFF();}break;

}

}

}

Но возможен вариант, когда обработка будет настолько долгая, что успеет прийти следующий байт. Но тогда предыдущий будет затёрт. Чтобы этого не случилось, создаётся буфер, представляющий из себя массив данных типа char. Определяемый, к примеру, следующим образом:

uint8_t receive_buffer[256];

Для работы с этим буфером нам требуется ряд переменных:

  1. Указатель (не путать с указателями в Си) на место записи принятых данных.

  2. Указатель на место чтения обрабатываемых данных.

  3. Количество необработанных данных в буфере.

uint8_t receive_write=0, receive_read=0, receive_count=0;

Заполнение буфера тогда выглядит так:

receive_buffer[receive_write] = USART_ReceiveData(USART1);//Приняли байт

receive_write++;

receive_count++;

О переполнении можно не беспокоиться благодаря выбранному размеру буфера. По достижении 255 все переменные будут обнуляться автоматически.

Тогда, обработка это будет выглядеть так:

if (receive_count > 0)

{

switch (receive_buffer[receive_read]){

case 0x01:{RED_ON();}break;

case 0x02:{RED_OFF();}break;

}

receive_count--;

receive_read++;

}