Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Использование функции sprintf



Функция sprintfвключает в себя следующие параметры:

char *str – указатель на начало массива.

Str – строку, которую надо записать в массив.

Например, если надо записать в массив text слово Привет, надо использовать строку:

sprintf(text, “Привет”);

Если надо вывести число в массив, то это делается в зависимости от типа числа. Если число знаковое то используется директива %d. Например:

sprintf(text, “%d”, Rand); Тогда в text запишется значение переменной Rand.

Если же число беззнаковое, то используется %u. Например:

sprintf(text, “%u”, Rand); Тогда в text запишется значение переменной Rand но без знака.

Если надо ввести несколько данных в одну строку, то можно сделать так:

sprintf(text, “%u %u”, Rand[0], Rand[1]);


 

Часть 3: Протокол передачи.

Протоколы передачи данных.

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

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

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

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

Стартовая последовательность говорит о начале передачи. Зачастую её делают уникальной, т.е. такой, что она больше не может встречаться в пакете. Встретив её, устройство точно знает, что это начало пакета и начинает приём.

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

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

Данные содержат в себе информацию, передаваемую устройству. Это может быть всё, что угодно, кроме команды этому устройству.

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

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

Приём данных

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Самый простой протокол. Он подразумевает передачу только одного поля – поля команды. Причём это поле длиной один байт. Этот байт передаёт необходимую информацию. Количество различных команд равно 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++;

}

 


 

Задание

1. Написать программу, которая отправляет заданный байт на ПК с периодом 1 секунда.

2. Написать функцию, отправляющую на ПК строку. И на её основе написать передачу на ПК строки вида: «i=x», где х увеличивается на 1 каждую секунду.

3. Написать программу, которая по команде с ПК зажигает заданный светодиод.

Порядок выполнения задания.

Задание 1:

1. Запустить файл «lab5DMA.uvproj» в папке «lab4».

2. Разобраться в структуре программы и найти функцию main().

3. Внутри цикла while(1) отправить любой байт с помощью функции send_to_USART (см. пункт «Отправка байта по USART»).

4. В следующей строке вызвать функцию задержки программы на 1 секунду: delay_ms(1000);

5. Проверить работоспособность программы. Для этого необходимо выполнить следующие действия:

5.1. Подключить соединительные провода от модуля USART к соответствующим выводам отладочной платы. Порт и номер ножки порта можно определить, посмотрев, какие выводы использованы для инициализации USART в функции «USART_ini(void)» в коде программы.

5.2. Запустить на ПК программу «ComMon.exe», которая находится в папке «ПО\Работа с COM портом\ComMon». Выбрать COM-порт и снять обе галочки «text».

 

 

Задание 2:

1. Написать функцию передачи строки по USART как описано в «Отправка строки с текстом по USART».

2. Написать счётчик, который увеличивает значение i на 1 каждую секунду.

3. С помощью функции sprintf из раздела «Использование функции sprintf» создайте строку вида «i=x», где вместо х вставляется значение i.

4. С помощью написанной функции по передаче строки, отправьте полученную строку на ПК.

Задание 3:

1. Выяснить номера выводов, к которым подключены светодиоды, как описано в разделе «Определение подключения светодиодов» лабораторной работы 1.

2. В функцию main() после строки USART_ini(); добавить код инициализации выводов, к которым подключены светодиоды. Код скопировать из программы для лабораторной работы 1.

3. Найти в программе функцию обработки прерываний USART3_IRQHandler(void). После строки, которая реализует сохранение принятого байта в переменную Res_data, добавить проверку следующих условий (условную конструкцию if): если принятый байт равен 1, включить красный светодиод; если принятый байт равен 2, включить желтый светодиод; если принятый байт равен 3, включить зеленый светодиод; если принятый байт равен 4, включить синий светодиод. Если принят ноль, выключить все светодиоды.

4. Проверить работоспособность программы. Для этого необходимо выполнить следующие действия:

4.1. Подключить соединительные провода от модуля USART к соответствующим выводам отладочной платы. Порт и номер ножки порта можно определить, посмотрев, какие выводы использованы для инициализации USART в функции «USART_ini(void)» в коде программы.

4.2. Запустить на ПК программу «ComMon.exe», которая находится в папке «ПО\Работа с COM портом\ComMon». Выбрать COM-порт и снять обе галочки «text». Для отправки данных на МК необходимо ввести данные в строку внизу окна программы в виде шестнадцатеричных чисел и нажать кнопку «Send».

 

 


Поделиться:



Популярное:

Последнее изменение этой страницы: 2017-03-11; Просмотров: 1079; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.047 с.)
Главная | Случайная страница | Обратная связь