Описание библиотеки для стенда, страница 2
Описание файла
Документ из архива "Описание библиотеки для стенда", который расположен в категории "". Всё это находится в предмете "программное обеспечение управляющих комплексов (поук)" из 9 семестр (1 семестр магистратуры), которые можно найти в файловом архиве МГТУ им. Н.Э.Баумана. Не смотря на прямую связь этого архива с МГТУ им. Н.Э.Баумана, его также можно найти и в других разделах. Архив можно найти в разделе "книги и методические указания", в предмете "поук" в общих файлах.
Онлайн просмотр документа "Описание библиотеки для стенда"
Текст 2 страницы из документа "Описание библиотеки для стенда"
#include <stdio.h>
#include <stdlib.h>
#include "urc220.h"
uint32 select_device();
CURC220 urc;
//------------------------------------------------------------
Далее напишем функцию 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, поэтому в случае возврата нуля программа выдаёт сообщение об ошибке и завершает работу (return EXIT_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” – “Build All”. После выполнения этой команды будут созданы объектные (“*.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.
4.3 Универсальный пример
Ниже приведён универсальный пример, который демонстрирует все функции для работы с устройством. Данное консольное приложение выводит на экран все данные с платы, которые можно считать, в виде таблицы, а также устанавливает значения ШИМ на всех каналах и мигает светодиодами.
Здесь, как и в предыдущем примере, сначала происходит выбор устройства с помощью функции select_device(), а затем подключение к выбранному устройству. ШИМ меняется линейно от 0 до +700 и обратно, а данные на экран выводятся 4 раза в секунду.
Подключение заголовочных файлов, прототипы функция и функция main():
//------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include "urc220.h"
//------------------------------------------------------------
uint32 select_device();
void *test_complex(void *);
CURC220 urc;
//------------------------------------------------------------
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("Creating thread\n");
pthread_t thread;
int ret = pthread_create(&thread, NULL, &test_complex, NULL);
if(thread == 0 || ret != EOK)
{
printf("ER: can't create thread (%d)\n", ret);
return EXIT_FAILURE;
}
getchar();
pthread_detach(thread);
pthread_abort(thread);
urc.Close();
printf("Done\n");
return EXIT_SUCCESS;
}
//------------------------------------------------------------
Здесь, после подключения к устройству, создаётся дополнительный поток, в котором будет выполняться функция test_complex(). Также есть проверка на успешность создания потока. Далее вызывается функция getchar(), которая заблокирует основной поток до нажатия на Enter, после чего программа закроет обращение к устройству и завершит свою работу.
В функции test_complex() реализован бесконечный цикл, в котором происходит считывание данных из устройства с помощью метода Read() с проверкой успешности выполнения, далее заполняются значения локальных переменных с помощью функций GetInput(), GetOutput(), GetADC() и GetEnc(). Далее все значения выводятся на экран. Затем идёт подсчёт нового значения ШИМ и запись данных обратно в устройство.
Исходный код функции test_complex() приведён ниже.
//------------------------------------------------------------
void *test_complex(void *)
{
printf("Complex test\n");
int sign = +1;
int led_num = 0;
while(1)
{
if(!urc.Read())
{
printf("ER: can't read data\n");
delay(1000);
}
uint8 in[4];
uint8 out[8];
uint16 adc[4];
int16 pwm[4];
int32 enc[2];
for(int i = 0; i < 4; i++)
urc.GetInput(i, &in[i]);
for(int i = 0; i < 8; i++)
urc.GetOutput(i, &out[i]);
for(int i = 0; i < 4; i++)
urc.GetADC(i, &adc[i]);
for(int i = 0; i < 4; i++)
urc.GetPWM(i, &pwm[i]);
for(int i = 0; i < 2; i++)
urc.GetEnc(i, &enc[i]);
printf("%d %d %d %d - %d %d %d %d %d %d %d %d - %04d %04d %04d %04d - %03d %03d %03d %03d - %d,%d\n",
in[0], in[1], in[2], in[3],
out[0], out[1], out[2], out[3],
out[4], out[5], out[6], out[7],
adc[0], adc[1], adc[2], adc[3],
pwm[0], pwm[1], pwm[2], pwm[3],
enc[0], enc[1]);
int16 cur_pwm = pwm[0];
cur_pwm += sign * 50;
urc.SetPWM(0, cur_pwm);
urc.SetPWM(1, cur_pwm);
urc.SetPWM(2, cur_pwm);
urc.SetPWM(3, cur_pwm);
if(cur_pwm == 700) sign = -1;
if(cur_pwm == 0) sign = +1;
for(int i = 0; i < 8; i++)
urc.SetOutput(i, 0);
urc.SetOutput(led_num, 1);
led_num++;
if(led_num == 8) led_num = 0;
if(!urc.Write())
{
printf("ER: can't write data\n");
delay(1000);
}
delay(250);
}
return NULL;
}
//------------------------------------------------------------
Рис.4.3 Выполнение программы test_complex |
Ход выполнения программы показан на рисунке 4.3.
5. Содержание
1. Техническое задание 2
2. Драйвер 3
2.1 Алгоритм работы 3
3. Библиотека для работы с платой на компьютере 5
3.1 Алгоритм работы с библиотекой 5
3.2 Описание функций класса CURC220 5
4. Применение библиотеки 9
4.1 Создание проекта 9
4.2 Пример использования 9
4.3 Универсальный пример 13
5. Содержание 16
17