Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DiplomKrutova.docx
Скачиваний:
46
Добавлен:
03.05.2015
Размер:
1.46 Mб
Скачать

Глава 4. Тестирование системы передачи.

    1. Цель тестирования

Для тестирования корректности обмена информацией между устройствами системы «Витязь», регистратором параметров движения поезда и стационарной ПЭВМ было решено создать стенд РПДП и разработать ПО стенда РПДП. ПО стенда РПДП предназначено для входного контроля блоков РПДП. Структурная схема стенда РПДП представлена на рисунке 4.1.1.

Рисунок 4.1.1 - Структурная схема стенда РПДП.

Стенд РПДП состоит из:

  • Блока РПДП;

  • Источника питания 75В;

  • Контролера KCAN-G, подключенного к разъему CAN – головной блока РПДП по дублированной CAN – шине;

  • Контролера KCAN-P, подключенного к разъему CAN – поездной блока РПДП по дублированной CAN – шине;

  • Стационарной ПЭВМ соединенной с KCAN-G и KCAN-P - кабелем USB, с блоком РПДП и Роутером Wi-Fi - кабелем Ethernet;

  • Роутер Wi-Fi , для отладки ПО в области сетевого взаимодействия;

  • Два модуля Wi-Fi для отладки ПО в области беспроводной передачи данных с блока РПДП.

ПЭВМ подключается к KCAN-G и KCAN-P кабелем USB, так же ПЭВМ подключается к блоку РПДП кабелем Ethernet. В свою очередь KCAN-G и KCAN-P по CAN шине подключаются к блоку РПДП.

    1. Требования к ПО стенда РПДП

Для проверки блока РПДП требуется произвести запись эталонной регистрации средствами KCAN-G и KCAN-P контролеров. ПО подключается к KCAN-G и KCAN-P по каналу USB. ПО открывает эталонный файл регистрации, и, в соответствии с CAN – идентификаторами (KCAN-G < 0x600, KCAN-P > 0x600), по USB каналу записывает информацию в KCAN-G и KCAN-P контролеры. В свою очередь KCAN-G и KCAN-P контролеры записывают информацию в блок РПДП по CAN каналу.

Подключив ПЭВМ, кабелем Ethernet, к блоку РПДП, требуется произвести считывание зарегистрированной блоком РПДП регистрации и сравнение ее с отправленной эталонной регистрацией.

Рисунок 4.2.1 РПДП Рисунок 4.2.2 Стенд РПДП

Рисунок 4.2.3 CAN-G, CAN-P-контроллер

    1. Установление USB соединения

После запуска программы необходимо выбрать эталонную регистрацию для ее дальнейшей отправки на РПДП. Эталонная регистрация представляет собой бинарный файл расширения .rpdp, содержащий набор зарегистрированных РПДП строк.

Рисунок 4.3.1 Окно открытия эталонной регистрации

После открытия эталонной регистрации, необходимо произвести ее отправку нажатием на кнопку «Отправить» BtnSendToCan. В первую очередь необходимо произвести установление соединения с CAN-контроллером по USB. Данную задачу выполняет функция InitUSB(), приведенная ниже. При вызове этой функции происходит процесс инициализации устройства.

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

Общий смысл работы с девайсами класса HID сводится к открытию девайса самой обычной функцией CreateFile() и последующему чтению из него функцией ReadFile(). Всё точно так же, как при работе с обычными файлами. Но до этого нужно получить путь к девайсу (device path)[9]. Для получения пути к устройству, необходимо проделать несколько следующих шагов [10]:

  1. Получить GUID (Globally Unique Identifier) класса HID. GUID — статистический уникальный 128-битный идентификатор. Этот идентификатор указан в протоколе CAN-контроллера, поэтому в программе он задается явным образом.

  2. Далее необходимо получить набор с описанием всех девайсов этого класса. Для этого надо вызвать функцию SetupDiGetClassDevs(), передав ей в качестве параметра GUID. Функция вернет дескриптор этого набора. Вторым параметром передается ноль, так как для выбора устройства не используется счетчик. Третий параметр – дескриптор окна для ассоциирования с устройством, также можно задать NULL. Последним параметр указывает на то, что в набор необходимо включать только устройства, присутствующие в системе (DIGCF_PRESENT).

  3. Если дескриптор создан успешно, нужно открыть цикл по 127 устройствам (максимальное число возможных подключений по USB). Пройтись по ранее созданному набору устройств вызовом функции SetupDiEnumDeviceInterfaces(). Пройтись - значит вызывать её в цикле для каждого элемента набора до тех пор, пока она не вернёт false. Каждый элемент, для которого функция вернёт true, соответствует одному подключённому девайсу класса HID. Функция SetupDiEnumDeviceInterfaces() получает в качестве параметра дескриптор набора устройств, GUID интересующего устройства, счетчик для количества найденных интересующих устройств и элемент типа SP_DEVICE_INTERFACE_DATA для записи информации об устройствах.

  4. Если функция вернёт false, нужно вызвать GetLastError() и проверить наличие ошибки ERROR_NO_MORE_ITEMS. Если она есть, значит программа дошла до конца списка и можно выходить из цикла.

  5. Теперь можно получить путь к девайсу. Для этого надо вызвать функцию SetupDiGetDeviceInterfaceDetail(), передавая ей информацию о девайсе, полученную с помощью SetupDiEnumDeviceInterfaces(), и дескрипор массива девайсов. Путь надо получать отдельно для каждого девайса. Это лучше делать в цикле. Нужно отметить, что для получения пути к девайсу функцию необходимо вызвать дважды, так как при первом вызове она возвращает размер структуры PSP_DEVICE_INTERFACE_DETAIL_DATA, содержащей инвормацию об устройтве. При втором вызове функция записывает путь к устройству в следующий параметр functionClassDeviceData->DevicePath структуры PSP_DEVICE_INTERFACE_DETAIL_DATA.

  6. После того, как программа узнала путь к устройству, она может определить PID и VID устройства. Для этого вызывается функция GetVID_PID(). Определив VID и PID устройства программа сравнивает их с VID и PID, интересующими разработчика. Если они равны, можно сделать вывод, что это требуемое устройство.

  7. Теперь можно открывать девайс. Для этого необходимо вызвать функцию CreateFile(), задав в качестве имени файла путь к девайсу. Функция возвращает дескриптор hRead, позволяющий производить чтение из устройства при передаче ей в качестве второго параметра GENERIC_READ. Функция возвращает дескриптор hWrite, позволяющий производить запись на устройство при передаче ей в качестве второго параметра GENERIC_WRIGHT.

  8. После того, как все нужные девайсы уже открыты (или не найдены), необходимо удалить набор устройств, полученный в пункте 2. Это делается вызовом функции SetupDiDestroyDeviceInfoList().

Листинг 4.3.1

hDevInfoList = SetupDiGetClassDevs(&Guid, NULL, NULL, (DIGCF_PRESENT));

if(hDevInfoList != INVALID_HANDLE_VALUE)

{

SP_DEVICE_INTERFACE_DATA deviceInfoData; // здесь хранится информация об отдельном девайсе...

for(int i=0; i<127; i++)

{

ZeroMemory(&deviceInfoData, sizeof(deviceInfoData));

deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

if(SetupDiEnumDeviceInterfaces(hDevInfoList, 0, &Guid, i, &deviceInfoData)) //Если нашлось устройство с данным GUID вернет true

{

functionClassDeviceData = NULL;

requiredLength = 0;

SetupDiGetDeviceInterfaceDetail(hDevInfoList, &deviceInfoData, NULL, 0, &requiredLength, NULL); //The first time returns the size of the structure in Length.

functionClassDeviceData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requiredLength);

functionClassDeviceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

//The second time returns a pointer to the data in hDevInfoList (functionClassDeviceData).

if(SetupDiGetDeviceInterfaceDetail(hDevInfoList, &deviceInfoData, functionClassDeviceData, requiredLength, &requiredLength, NULL))

{

wcscpy(OutPipe, functionClassDeviceData->DevicePath);

/*Параметры

strDestinati cтрока, являющаяся выходным значением. strSource исходная строка с нулевым символом в конце.*/

wcscat(OutPipe, L"\\PIPE01");

wcscpy(InPipe, functionClassDeviceData->DevicePath);

wcscat(InPipe, L"\\PIPE00");

result = GetVID_PID(functionClassDeviceData->DevicePath, &VID, &PID);

free(functionClassDeviceData);

//для первого CAN1

if(result && (VID == 0xACD1))

{

if(PID == 0x2F24) status = true;

}

//для второго CAN2

if(result && (VID == 0xACD1))

{

if(PID == 0x2E47) status = true;

}

if(status)

{

CloseHandle(hWrite);

CloseHandle(hRead);

hWrite = CreateFile(OutPipe, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

if(hWrite == INVALID_HANDLE_VALUE)

{

strTemp = "Невозможно открыть OutPipe: " + SysErrorMessage(GetLastError());

Application->MessageBox(strTemp.w_str(), ProgName, MB_OK|MB_ICONERROR);

status = false;

break;

}

hRead = CreateFile(InPipe, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

if(hRead == INVALID_HANDLE_VALUE)

{

strTemp = "Невозможно открыть InPipe: " + SysErrorMessage(GetLastError());

Application->MessageBox(strTemp.w_str(), ProgName, MB_OK|MB_ICONERROR);

CloseHandle(hWrite);

status = false;

break;

Функции WriteUSB() и ReadUSB() работают предельно просто. Вся их суть заключается в вызове функций WriteFile(hWrite, tmp_buf1, kol, &dwBytesWritten, NULL) и ReadFile(hRead, InFile, kol, &dwBytesRead, NULL). Обеим функциям в качестве параметров передаются созданные ранее дескрипторы чтения и записи, указатель на буфер, куда записывать прочитанную информацию или откуда считывать передаваемую. Помимо этого задается требуемое количество байт для чтения и записи и задается параметр, куда записывается фактическое количество прочитанных или записанных байт. Далее при сравнении требуемого и фактического количества можно выявить ошибки чтения и записи.

Листинг 4.3.2

bool __fastcall TForm1::WriteUSB(unsigned char* tmp_buf1, int kol)

{

int err;

UnicodeString asTemp;

bool status;

status = false;

if (bUSBEnable == true) {

if(!WriteFile(hWrite, tmp_buf1, kol, &dwBytesWritten, NULL)) {

err = GetLastError();

asTemp = "Ошибка посылки запроса. Код ошибки: " + IntToStr((int)err);

Application->MessageBoxW(asTemp.w_str(), ProgName, MB_OK|MB_ICONERROR);

status = false;

goto LabExitWUSB;

}

if(dwBytesWritten != kol) {

Application->MessageBoxW(L"Посылка ушла не полностью!!!", ProgName, MB_OK|MB_ICONERROR);

status = false;

goto LabExitWUSB;

}

}

status = true;

LabExitWUSB:

return status;

}

//---------------------------------------------------------------------------

bool __fastcall TForm1::ReadUSB(int kol)

{

int err;

UnicodeString asTemp;

bool status;

status = false;

if (bUSBEnable == true) {

if(!ReadFile(hRead, InFile, kol, &dwBytesRead, NULL)) {

err = GetLastError();

asTemp = "Ошибка приема посылки. Код ошибки: " + IntToStr((int) err);

Application->MessageBoxW(asTemp.w_str(), ProgName, MB_OK|MB_ICONERROR);

status = false;

goto LabExitRUSB;

}

if(dwBytesRead != kol) {

Application->MessageBoxW(L"Посылка пришла не полностью!!!", ProgName, MB_OK|MB_ICONERROR);

status = false;

goto LabExitRUSB;

}

}

status = true;

LabExitRUSB:

return status;

}

    1. Упаковка и отправка эталонной регистрации по USB

После установления соединения можно начать отправку эталонной регистрации. Обмен сообщениями между CAN-контроллерами и ПЭВМ производится строго по протоколам обмена. В самом первом сообщении после USB соединения необходимо произвести настройку скорости обмена по CAN. Ниже представлен протокол обмена:

Таблица 4.4.1

Настройка скорости обмена. ПЭВМKCAN (7 байт)

Байт

Значение

Примечание

0

0x0F

1

0xA3

2

0 бит = 1 – изменить значение

0 бит = 0 – только чтение

3

0x00

резерв

4

CNF1

см. табл. 2

5

CNF2

6

CNF3

Таблица 4.4.2

Значения регистров CNF для разных скоростей обмена

Скорость Кбит/сек

Значение

Примечание

CNF1

CNF2

CNF3

125

0x03

0xB9

0x84

250

0x01

0xB9

0x84

используется по умолчанию

1000

0x00

0xCA

0x81

После отправки 7 байтового сообщения, устанавливающего скорость обмена, KCAN отправляет на ПЭВМ ответное 7 байтовое сообщение, формат которого представлен в Табл. 4.4.3.

Таблица 4.4.3

ПЭВМKCAN (7 байт)

Байт

Значение

Примечание

0

0xEF

1

0xA3

2

резерв

3

резерв

4

CNF1

установленная скорость обмена

5

CNF2

6

CNF3

После обмена с CAN-контроллером 7 байтовыми сообщениями с управляющей информацией, можно непосредственно производить передачу эталонной регистрации на CAN-контроллеры, которые, в свою очередь, произведут отправку информации на РПДП. Эталонная регистрация отправляется на CAN-контроллеры сообщениями определенного формата, описанного в протоколе обмена сообщениями:

Таблица 4.4.4

ПЭВМKCAN (58 байт)

Байт

Значение

Примечание

0

0x0F

1

0xA4

2

-

кол-во сообщений для передачи (от 0 до 5)

3

-

кол-во сообщений для приема (от 0 до 1)

4

-

номер линии CAN для передачи (0 или 1)

5

-

резерв

6,7

-

идентификатор принимаемого сообщения (Табл. 5)

8,9

-

идентификатор 1-ого сообщения для передачи + длина сообщения (Табл. 5)

10-17

-

информация 1 сообщения

18,19

-

идентификатор 2 сообщения для передачи + длина (Табл. 5)

20-27

-

информация 2 сообщения

28,29

-

идентификатор 3 сообщения для передачи + длина (Табл. 5)

30-37

-

информация 3 сообщения

38,39

-

идентификатор 4 сообщения для передачи + длина (Табл. 5)

40-47

-

информация 4 сообщения

48,49

-

идентификатор 5 сообщения для передачи + длина (Табл. 5)

50-57

-

информация 5 сообщения

Таблица 4.4.5

Упаковка идентификатора и длины сообщения.

байт/бит

7

6

5

4

3

2

1

0

1

SID10

SID9

SID8

SID7

SID6

SID5

SID4

SID3

2

SID2

SID1

SID0

XX

DLC3

DLC2

DLC1

DLC0

Примечание: SIDn – n-ый бит идентификатора, DLCn – n-ый бит длины сообщения.

Пример упаковки (по таблице 4.4.5.) идентификатора и длины сообщения:

Листинг 4.4.1

shTemp = (((OutFile[i][6]<<8)|OutFile[i][5])<<5)|0x08;

tmp_buf1[8] = (shTemp>>8)&0xFF;

tmp_buf1[9] = shTemp&0xFF;

Как видно из протокола ПЭВМKCAN (таблица 4.4.4), отправка эталонной регистрации на CAN-контроллер производится сообщениями размером 58 байт. В одном сообщении умещается информация о состоянии максимум 5-и прослушиваемых устройств системы «Витязь» (идентификаторов). Эта информация берется из эталонного файла регистрации и записывается в 10-17, 20-27, 30-37, 40-47 и 50-57 байты сообщения. Идентификаторы самих устройств записываются в 8,9; 18,19; 28,29; 38,39 и 48,49 байты.

Из полученного от ПЭВМ сообщения размером 58 байт CAN-контроллер вынимает информацию о состоянии устройств, представленных своими уникальными идентификаторами, и формирует сообщение собственного (понятного РПДП) формата для дальнейшей отправки на РПДП.

Запись информации в РПДП производится строками по 17 байт. Формат строк описан в таблице 3.2.1. РПДП самостоятельно формирует значения 1,2,3,4 байтов строк, отвечающих за время приема сообщения от CAN-контроллера, 5,8 резервных байтов и 9 байта, отвечающего за номер KCAN, отправившего сообщение (0 или 1 – головной KCAN-G, 2 или 3 – поездной KCAN-P). Оставшиеся 6,7 и 10-17 байты РПДП вынимает из сообщения, присланного CAN-контроллером.

На каждое полученное сообщение размером 58 байт CAN-контроллер отправляет ответ – сообщение размером 19 байт. Проанализировав это сообщение можно выявить произошедшие при передаче ошибки, если они были.

Таблица 4.4.6

ПЭВМKCAN (19 байт)

Байт

Значение

Примечание

0

0xEF

1

0xA4

2

-

ошибки работы CAN-контроллера

если 0, то ошибок нет

0 бит = 1 – не удалось передать по CAN за 10 мс

1 бит = 1 – нет приема более 50 мс

3

-

ошибки CAN1 интерфейса по передаче (TEC)

4

-

ошибки CAN1 интерфейса по приему (REC)

5

-

ошибки CAN2 интерфейса по передаче (TEC)

6

-

ошибки CAN2 интерфейса по приему (REC)

7

0x00

резерв

8

0x00

резерв

9,10

-

идентификатор принятого сообщения + длина

11-18

-

информация

Функция BtnSendToCanClick() производит все вышеописанные действия, то есть инициирует USB-соединение вызовом функции InitUSB(), описанной выше, и производит обмен сообщениями с CAN-контроллером.

Листинг 4.4.1

void __fastcall TForm1::BtnSendToCanClick(TObject *Sender)

{

int CAN=1;

int flag=0, iseek=2;

if(!InitUSB(CAN)) return;

StatusBar->Panels->operator [](1)->Text = "Соединение установлено ";

//по протоколу заполняем «управляющий» буфер

//для задания режима взаимодействия по USB

chOut[0]=0x0F;

chOut[1]=0xA3;

chOut[2]=0x01;

chOut[3]=0x00;

chOut[4]=0x01; //устанавливается скорость 250 Кбит/сек

chOut[5]=0xB9;

chOut[6]=0x84;

if (!WriteUSB(chOut, 7)) //отправка по USB «управляющего» сообщения (7 байт)

{

Application->MessageBoxW(L"Ошибка записи!!!", L"Запись", MB_OK | MB_ICONWARNING);

return;

}

if (!ReadUSB(7)) //прием ответного сообщения по USB (7 байт)

{

Application->MessageBoxW(L"Ошибка чтения!!!", L"Чтение", MB_OK | MB_ICONWARNING);

return;

}

FormirovanieCANPocketov(); //формирование CAN пакетов и их отправка по USB

StatusBar->Panels->operator [](2)->Text = "Запись произведена ";

BtnReadHeader->Enabled = true;

Screen->Cursor = crDefault;

}

Функция FormirovanieCANPocketov() производит формирование CAN-пакетов размером 58 байт и отправку этих пакетов на KCAN-G или KCAN-P CAN-контроллеры в зависимости от идентификаторов устройств, которые составляют сообщение: если идентификаторы < 0x600 - отправка по KCAN-G (в функции InitUSB() устанавливаются VID и PID KCAN-G), если идентификатор > 0x600 – отправка по KCAN-P (в функции InitUSB() устанавливаются VID и PID KCAN-P).

    1. Считывание регистрации с РПДП по Wi-Fi и сравнение.

После отправки регистрации на РПДП необходимо отсоединить USB-кабель и подключиться к блоку РПДП по Wi-Fi. Открыть оглавление, найти в нем только что созданную регистрацию и прочитать ее. Процесс считывания описан в главе 3.

После считывания необходимо произвести сравнение двух регистраций с целью выявления искажений в информации об устройствах. Сравнение двух регистраций ошибок не выявило. Но для проверки работоспособности программы было решено модифицировать по 1 байту в 3, 4 и 5 кадрах регистрации с целью определения, выявит ли программа эти изменения.

Как видно из рис.4.5.1 программа выявила все модификации, предоставив информацию о кадре, в котором встретилась некорректная запись, об идентификаторе, в 8-и байтовом сообщении которого произошли изменения, и о самих изменениях. Программа также предоставляет возможность просмотра содержания любого интересующего кадра обеих регистраций. На рис.4.5.1 выведено содержание третьего кадра, в котором, как выяснилось, присутствуют ошибки. Можно увидеть, что последний байт информации об устройстве с идентификатором 0x01С7 был искажен (вместо 0x00 значение 0x50).

Рисунок 4.5.1 Сравнение эталонной и зарегистрированной регистраций.

    1. Вывод

Для тестирования корректности обмена информацией между устройствами системы «Витязь», регистратором параметров движения поезда и стационарной ПЭВМ был создан стенд РПДП, а также ПО стенда РПДП. Для проверки блока РПДП производилась запись эталонной регистрации средствами KCAN-G и KCAN-P контролеров по каналу USB в РПДП. Далее регистрация, зарегистрированная блоком РПДП, считывалась с помощью Wi-Fi-технологий на стационарную ПЭВМ для дальнейшего сравнения с эталонной.

Сравнение двух регистраций ошибок не выявило. Для проверки работоспособности программы было решено модифицировать считанную по Wi-Fi регистрацию. Программа выявила все модификации, предоставив информацию о кадрах, в которых встречались некорректные записи.

Таким образом, можно сделать вывод, что, так как не модифицированные файлы регистрации при сравнении совпали, информация проследовала из опрашиваемых устройств системы «Витязь» (которые мы имитировали при отправке эталонной регистрации средствами KCAN-G и KCAN-P контролеров) в РПДП, а потом в ПЭВМ без искажений. Это доказывает, что выявленные в третьей главе участки превышения фактической скорости над допустимой не следствие искажения информации при передаче, а следствие более серьезной проблемы в работе основных устройств электропоезда.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]