В предыдущей части нашего занятия мы познакомились с механизмом использования API FreeRTOS в телах обработчиков прерываний, создали и настроили проект и написали код для отправки байта, принятого по шине USART, в очередь.
Теперь в функции задачи для обработки байта и разбора строк TaskParseUSART мы создадим несколько локальных переменных и указатель на структуру очереди для передачи строки функции задачи для вывода строк на дисплее
void TaskParseUSART(void const * argument)
{
osEvent event;
static char str[30];
static uint8_t cnt=0;
uint8_t b;
int yp;
struct_out *qstruct;
Зададим цвет для строки, выводимой на дисплей
struct_out *qstruct;
TFT_SetTextColor(LCD_COLOR_BLUE);
Добавим бесконечный цикл
TFT_SetTextColor(LCD_COLOR_BLUE);
for(;;)
{
}
В бесконечном цикле примем байт из очереди
for(;;)
{
event = osMessageGet(USART_Queue, 100);
Добавим условие наличия данных в очереди
event = osMessageGet(USART_Queue, 100);
if (event.status == osEventMessage)
{
}
В теле условия заберём байт из очереди в переменную
if (event.status == osEventMessage)
{
b= event.value.v;
Если превысили количество байтов для строки, обнулим счётчик
b= event.value.v;
//если вдруг случайно превысим длину буфера
if(cnt>25)
{
cnt=0;
}
Сохраним байт в массив в позицию, соответствующую значению счётчика, перед этим выйдя из тела условия
cnt=0;
}
str[cnt] = b;
Наша тестовая строка будет состоять из двух символов и заканчиваться будет символами возврата каретки и перевода строки. Последний из них будет 0x0A.
Поэтому исследуем наш байт на равенство коду данного символа, а в противном случае инкрементируем счётчик
str[cnt] = b;
if(b==0x0A)
{
}
else cnt++;
В теле условия равенства коду последнего символа мы будем исследовать строку, так как появление данного символа означает окончание нашей строки и полному её присутствию в нашем строковом массиве.
Обнулим предыдущий символ, так как это скорей всего 0x0D. Это и будет окончание принятой строки
if(b==0x0A)
{
str[cnt-1]=0;
Вообще наша строка будет состоять из строки «String» и двух символов однозначного целого числа, первое из которых будет номером строки, а второе — множителем для позиции по вертикали.
Выделим память под структуру для очереди и проинициализируем нашу структуру
str[cnt-1]=0;
qstruct = osMailAlloc(strout_Queue, osWaitForever);
qstruct->tick_count = osKernelSysTick();
yp = atoi(str+7);
qstruct->y_pos = yp*60;
Мы преобразовали элемент по 7-му адресу в строке в число. Умножили данное число на 60. Это и будет позиция по вертикали.
На всякий случай проверим, что мы не ушли за пределы позиции, затем обнулим в строковом массиве элемент, где был индекс позиции, теперь это будет конец строки, так как нам не нужно отображать данное число, затем соответствующему элементу очереди приравняем указатель на нашу строку и отправим нашу структуру в очередь для последующего приёма её в функции задачи, отвечающей за вывод строк на дисплее. Также затем, выйдя из условия, обнулим счётчик
qstruct->y_pos = yp*60;
if ((yp<=3)&&(yp>=1))
{
str[cnt-2]=0;
sprintf(qstruct->str, "%s", str);
osMailPut(strout_Queue, qstruct);
}
cnt=0;
Соберём наш код и прошьём контроллер.
В результате мы получим лишь только шапку, так как мы ещё не послали в шину USART нашего контроллера никакие строки
Как же можно нам это сделать, чтобы как-то автоматизировать процесс? Не вводить же нам постоянно строки в терминальной программе.
Есть вариант подключения ещё одного контроллера и передачи с него строк по тому же USART, такой вариант у меня в мыслях был. Но потом меня вдруг осенило! Ведь можно же в терминальной программе Terminal 1b писать скрипты. Вот этим мы сейчас и займёмся. Конечно, я не буду подробно описывать механизм написания скриптов, так как урок не об этом, но как и куда их писать, я конечно же расскажу.
Запустим программу Terminal 1b, соединимся с нашим портом, настроив порты и нажав и нажмём в программе кнопку Connect, а затем нажмём кнопку Scripting
Теперь в открывшееся окно вставим скрипт следующего содержания
program test;
var i,j: integer;
str1: string;
begin
str1:='String';
while (true) do
begin
for j:=1 to 5 do
begin
for i:=1 to 3 do
begin
comsendstr(str1+inttostr(j)+inttostr(i)+#13+#10);
end;
Delay(1000);
end;
end;
end.
Если кто-то программировал в Pascal, ну или на худой конец в Basic, ничего здесь нового для себя не откроет, а если и не программировал, то здесь всё подобно и языку C, только вместо открывающей фигурной скобки здесь оператор begin, а вместо закрывающей — end. Остальное всё, в принципе, так же. API используется встроенный в программу.
Мы в данном скрипте создали и проинициализировали строковый массив. Здесь не нужно указывать его размер. Затем мы создали цикл от 1 до 5 для передачи различных пяти строк, отличающихся друг от друга лишь последней цифрой. затем мы в данном цикле создали ещё один цикл от 1 до 3, чтобы к строке ещё и присоединить индекс последующего отображения в определённом месте по вертикали на дисплее нашей Discovery. То есть каждая из 5 строк будет передаваться по 3 раза, только с разным индексом на конце, затем будет задержка на 1 секунду, чтобы мы успели рассмотреть наши 3 одинаковые строки в разных местах дисплея. Вот в принципе и весь код скрипта.
Сохраним на будущее наш скрипт в специальном формате с помощью кнопки Save
Затем нажмём кнопку Run и наш скрипт начнёт выполняться, если конечно в нём нет ошибок
А вот и результат
Можно попробовать изменить задержку. Я пробовал менять её до 1, всё работало корректно, что значит, что мы создали вполне вменяемый и оптимальный код, имеющий полное право на существование.
Итак, сегодня мы научились пользоваться механизмом очередей в обработчиках прерываний, и, оказывается, благодаря API, разработанному для контроллеров STM, мы не встретились ни с какими трудностями, так как борьбу с этим трудностями взял на себя данный API.
Благодарю за внимание!
Предыдущая часть Программирование МК STM32 Следующий урок
Отладочную плату можно приобрести здесь STM32F746G-DISCOVERY
Смотреть ВИДЕОУРОК (нажмите на картинку)
stroutqueue ? где-то объявлена ?