KEEN SIDE успешно заменяет аналогичные продукты таких известных брендов, как Phoenix Contact, Weidmueller, Degson, Winstar, Hsuan Mao, KLS, G-NOR, Mean Well и др.
РадиоЛоцман - Все об электронике

Пример построения пользовательского интерфейса в приложениях Open AT

Т. Ташпулатов
Новости Электроники 19, 2007

Некоторые практические советы по работе с открытым пакетом Open AT. Этот пакет бесплатно поставляется компанией Wavecom разработчикам беспроводных систем.

В предлагаемой статье мы попытаемся рассмотреть практическую реализацию пользовательского интерфейса на приложении Open AT.
 

Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Реализация игры «Тетрис» на платформе Wavecom OpenAT

Рис. 1. Реализация игры «Тетрис» на платформе Wavecom OpenAT

Командный режим

Самым простым и наиболее распространенным способом взаимодействия приложения OpenAT с пользователем является общение через последовательный порт с использованием эмулятора терминала. Последовательный порт модема при этом находится в так называемом командном режиме (COMMAND MODE). Пользователь вводит команды с классическим префиксом AT, и получает один или несколько ответов модема:

ATZ

OK

AT+WIND?

+WIND: 32767

OK

AT+START

ERROR

Команда из последнего примера приводит к выдаче сообщения об ошибке, так как не является стандартной AT-командой. Тем не менее, мы можем сделать ее понятной модему, воспользовавшись возможностью создавать собственные команды в API OpenAT (здесь и далее подразумевается использование библиотеки ADL из комплекта поставки OpenAT).

adl_atCmdSubscribe ("at+start", (adl_atCmdHandler_t)AtStartHandler, ADL_CMD_TYPE_ACT);

Обработчик нашей команды:

void AtStartHandler (adl_atCmdPreParser_t *p)

{

adl_atSendResponse (ADL_AT_RSP, " Hello, world! ");

};

Скомпилируем, загрузим (AT+WDWL) и запустим наше приложение (AT+WOPEN=1). Убеждаемся, что набор стандартных команд пополнился еще одной:

ATZ

OK

AT+START

Hello, world!

Прозрачный режим

Необходимость предварять собственные команды префиксом AT и завершать ввод нажатием Enter может быть не всегда удобна. Часто от пользователя требуется нажатие одной-двух клавиш, например, стрелки управления курсором для перемещения по пунктам экранного меню, или «горячей клавиши» для выполнения определенных действий. В этом случае альтернативой стандартному командному режиму является режим прозрачной передачи данных (DATA MODE).

Для работы в DATA MODE воспользуемся соответствующими вызовами группы Flow Control Manager из API OpenAT. Зарегистрируем собственные обработчики событий управления и передачи данных для работы с последовательным портом UART1:

UARTHandle = adl_fcmSubscribe (ADL_PORT_UART1, (adl_fcmCtrlHdlr_f)UARTCtrlHandler, (adl_fcmDataHdlr_f)UARTDataHandler);

Переведем последовательный порт в режим передачи данных:

adl_fcmSwitchV24State (UARTHandle, ADL_FCM_V24_STATE_DATA);

Теперь все данные, вводимые в последовательный порт, будут попадать в наш обработчик:

bool UARTDataHandler (u16 DataLen, u8 *Data)

{

return (TRUE);

}

Вывод в последовательный порт тоже несложен:

adl_fcmSendData (UARTHandle, data, len);

Остается только реализовать собственный протокол обмена. При большом желании и в прозрачном режиме можно имитировать работу с AT-командами, построив соответствующим образом логику обработки входного потока и пользуясь вызовами уже знакомой нам группы Commands из API OpenAT.

Организация выводимой информации

Вывод сообщений приложения с использованием стандартных сервисов adl_atSendResponse () или adl_fcmSendData () удобен до тех пор, пока этих сообщений немного. В случае, когда поток отладочной информации велик, ориентироваться в нем становится затруднительно. Ситуация становится еще хуже, если выводятся потоки сообщений от различных частей приложения, работающих независимо друг от друга - например, сообщения о состоянии GSM-сети или GPRS-соединения, о процессе приема или передачи данных и так далее.

Выйти из положения можно, переведя терминал в режим эмуляции ANSI и воспользовавшись управляющими последовательностями ANSI. Это даст нам возможность раскрасить выводимые символы в 16 цветов, а фон - в 8.

ascii ansiSetGreenColor [] = {0x1b, ‘[‘, ‘4', ‘2', ‘m', 0};

wm_sprintf (buf, "%sЭто строчка зеленого цвета", ansiSetGreenColor);

adl_fcmSendData (UARTHandle, buf, wm_strlen (buf));

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

Очистим экран:

ascii ansiClearScreen [] = {0x1b, ‘[‘, ‘2', ‘J', 0};

adl_fcmSendData (UARTHandle, ansiClearScreen, wm_strlen (ansiClearScreen));

Выведем приветствие в правом верхнем углу (практичней было бы вывести там, к примеру, уровень сигнала RSSI, получаемый командой AT+CSQ):

wm_sprintf (buf, "%c[%d;%dHHello, world!", 0x1b, x, y);

adl_fcmSendData (UARTHandle, buf, wm_strlen (buf));

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

Работа с таймерами

Теперь нам осталось разобраться только с периодичностью вывода информации. Библиотека ADL OpenAT предлагает разработчику возможность работы с двумя типами таймеров - однократными и циклическими.

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

void MyTimeout (u8 id)

{

wm_sprintf (buf, "Сработал таймер %d", id)

adl_fcmSendData (UARTHandle, buf, wm_strlen (buf));

}

В качестве минимальных отрезков времени доступны два: 18,5 и 100 миллисекунд. Указанное количество отсчетов (100) и выбранный тип (18,5 мс) даст в результате интервал срабатывания таймера в 1.85 секунд.

adl_tmrSubscribe (FALSE, 100, ADL_TMR_TYPE_TICK, (adl_tmrHandler_t) MyTimeout);

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

tmrHandle = adl_tmrSubscribe (TRUE, 10, ADL_TMR_TYPE_100MS, (adl_tmrHandler_t) ScreenRefresh);

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

adl_tmrUnSubscribe (tmrHandle, (adl_tmrHandler_t)ScreenRefresh, ADL_TMR_TYPE_100MS);

tmrHandle = adl_tmrSubscribe (TRUE, 9, ADL_TMR_TYPE_100MS, (adl_tmrHandler_t) ScreenRefresh);

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

Тетрис для фортепиано с оркестром

Вооружившись полученными знаниями, можно реализовать известную игру на платформе Wavecom OpenAT (см. рис. 1). Запуск игры будет производиться командой AT+START, управление игрой - нажатиями клавиш J, K, L в режиме прозрачной передачи данных.

Отрисовка изменений на экране выполняется периодически, вместе с обновлением показаний часов (время, прошедшее с момента запуска приложения).

Электронные компоненты. Бесплатная доставка по России
Для комментирования материалов с сайта и получения полного доступа к нашему форуму Вам необходимо зарегистрироваться.
Имя