
4. Применение библиотеки
4.1 Создание проекта
Сначала загрузите QNXMomenticsIDE(“Launch” – “QNXMomenticsDevelopmentSuite6.3.2” – “IntegratedDevelopmentEnvironment”).
Если вы загружаете эту среду первый раз, то вам будет предложено выбрать папку для хранения проектов. Если оставить ту, что стоит по умолчанию, то workspace(пространство для хранения объектов) будет создано в папке “/user_name/ide4-workspace/” (user_name– имя пользователя). Все вновь создаваемые проекты будут добавляться в этотworkspace.
Рис.4.1 Настройки нового проекта |
После загрузки среды выберете меню “File” – “New” – “Project”. В появившемся окне выберете тип проекта: “C++” – “QNXC++Project” и нажмите на “Next”. Затем введите имя проекта (“ProjectName”), например "test_simple”, а также вид конечного файла (“Type”) - “Application” (приложение).
Далее нажмите на “Next”. В следующем окне выберете вкладку “BuildVariants”, где установите пункты “X86 (LittleEndian)” (см. рис.4.1).
Новый проект создастся после нажатия на “Finish” в папке “/User_name/de4-workspace/test_simple”.
В проекте появится файл исходного кода “test_simple.cc” с минимальным кодом для компиляции.
4.2 Пример использования
Рассмотрим простой пример, который продемонстрирует запись данных в устройство. Для начала нужно переписать в папку с проектом файлы библиотеки: “stdtypes.h”, “urc220.h”. Все файлы в каталоге с проектом автоматически добавляются в проект. Чтобы увидеть их в списке, нажмите на название проекта правой кнопкой мыши и выберете пункт меню “Refresh”.
Изменим исходный код. Добавим необходимые заголовочные файлы (в том числе файл библиотеки). Также прототип функции select_device(), которая понадобится в дальнейшем, а также создадим объект классаCURC220, с помощью которого и будем работать с устройством.
//------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include "urc220.h"
uint32 select_device();
CURC220urc;
//------------------------------------------------------------
Далее напишем функцию main():
//------------------------------------------------------------
int main(int argc, char *argv[])
{
printf("URC test\n");
uint32 index = select_device();
if(index == URC_MAXDEV) return EXIT_FAILURE;
printf("Opening device %d\n", index);
if(!urc.Open(index))
{
printf("ER: can't open device\n");
return EXIT_FAILURE;
}
printf("Changing LEDs state\n");
urc.SetOutput(0, 1);
urc.SetOutput(1, 0);
urc.SetOutput(2, 1);
urc.SetOutput(3, 0);
urc.SetOutput(4, 1);
urc.SetOutput(5, 0);
urc.SetOutput(6, 1);
urc.SetOutput(7, 0);
printf("Writing data to the device\n");
if(!urc.Write())
{
printf("ER: can't write data\n");
return EXIT_FAILURE;
}
urc.Close();
printf("Done\n");
return EXIT_SUCCESS;
}
//------------------------------------------------------------
Здесь сначала вызывается функция select_device(), которая вернёт номер того устройства, с которым необходимо работать. Так как всего может быть подключено не болееURC_MAXDEVустройств, то индекс устройства может принимать значения от 0 до (URC_MAXDEV- 1), поэтому если функция возвращаетURC_MAXDEV, значит произошла ошибка, поэтому идёт проверка значения переменнойindexна равенствоURC_MAXDEV.
Далее, если был возвращён корректный индекс, открываем это устройство, вызвав функцию Open(). В случае ошибки все функции класса возвращают 0, поэтому в случае возврата нуля программа выдаёт сообщение об ошибке и завершает работу (returnEXIT_FAILURE).
После того, как устройство было открыто, можно начать вызывать функции для работы. В данном случае вызывается метод SetOutput(), который в качестве первого параметра принимает номер цифрового выхода (от 0 до 7), а вторым параметром является значение на выходе (0 – низкий уровень, !0 – высокий). Так как цифровые выходы продублированы светодиодами, то после установки логической единицы на выходы 0, 2, 4 и 6, загорятся соответствующие светодиоды. Однако все внесенные изменения записываются не непосредственно в устройство, а в буфер в оперативной памяти (это нужно для увеличения скорости обмена между компьютером и устройством), поэтому окончательно записать все изменения можно вызвав функциюWrite(). Здесь также происходит проверка корректности выполнения функции.
Далее программа закрывает устройство и завершает работу.
Теперь рассмотрим исходный код функции select_device(). Эта функция нужна для выбора устройства среди устройств, подключённых к компьютеру. Получить список устройств можно с помощью функцииGetDevStates() того же класса. В качестве параметра функция принимает массив изURC_MAXDEVчисел, куда запишет состояние каждого слота для подключения устройства. Так, если значение ячейки массива равноURCSTATE_OPENED, значит устройство, соответствующее номеру этой ячейки, подключено.
Необходимость нумерации возникает из-за того, что требуется избежать путаницы номеров при подключении и отключении устройств. Например, если подключить первое устройство, а затем второе, то у них будут индексы 0 и 1 соответственно. Однако, если отключить первое подключенное устройство, то ячейка номер 0 примет значение URCSTATE_CLOSED, а ячейка номер 1 останется равнаURCSTATE_OPENED. Таким образом, номер подключённой платы остаётся неизменным на всё время подключения, вне зависимости от подключения/отключения других плат.
//------------------------------------------------------------
uint32 select_device()
{
uint32 states[URC_MAXDEV];
if(!urc.GetDevStates(states))
{
printf("ER: can not receive devices state\n");
return URC_MAXDEV;
}
printf("Active device index(s): ");
uint32 count = 0;
for(uint32 i = 0; i < URC_MAXDEV; i++)
{
if(states[i] == URCSTATE_OPENED)
{
printf("%d ", i);
count++;
}
}
if(!count) printf("<no>");
printf("\nTotal devices found: %d\n", count);
if(!count) return URC_MAXDEV;
printf("Input device index: ");
char buf[100];
fgets(buf, sizeof(buf) - 1, stdin);
int index = atoi(buf);
if(index >= URC_MAXDEV || index < 0)
{
printf("Wrong device index\n");
return URC_MAXDEV;
}
if(states[index] != URCSTATE_OPENED)
{
printf("Wrong device index\n");
return URC_MAXDEV;
}
return index;
}
//------------------------------------------------------------
Рис.4.2 Выполнение программы test_simple |
Если в процессе выполнения функции не возникло никаких ошибок, то она вернёт индекс выбранного устройства. В противном случае функция вернёт URC_MAXDEVв качестве ошибки.
Теперь компилируем проект. Для этого выберем меню “Project” – “BuildAll”. После выполнения этой команды будут созданы объектные (“*.o”) и исполняемые файлы всех проектов и конфигураций, в том числе и для проектаsimple_test.
При настройках по умолчанию имя исполняемого файла - “/user_name/ide4-workspace/test_simple/x86/o/test_simple”.
Запустим файл в консоли (“Launch” – “Utilities” – “Console”). Для вставки пути из буфера обмена нажмите наCtrl+Alt+V. Ход выполнения программы показан на рисунке 4.2. При этом на плате должны загореться светодиодыLED0,LED2,LED4 иLED6.