Разработка программы контроля изделий и подготовка программной документации

БАЛТИЙСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ "ВОЕНМЕХ"

им. Д.Ф. УСТИНОВА

















Отчет

	О прохождении преддипломной практики

«Программная документация»





























САНКТ-ПЕТЕРБУРГ, 2009 г


Содержание



	Цель

	Техническое задание

	Общие сведения о предприятии

	Общие сведения о разработанной программе

	Алгоритм программы

	Режимы работы программы

	Результаты тестирования

	Входные параметры

	Заключение

	Приложение 1 – Исходные тексты программы


Цель



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

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

Подготовка к написанию дипломной работы предусматривает изучение темы будущей работы, знакомство со всеми ее тонкостями и нюансами. Необходимо составить наиболее полное представление о предмете работы и хорошо ориентироваться в данном вопросе.

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


Техническое задание



Требуется разработать программу контроля версий компонент изделий и подготовить к выпуску программную документацию. 

Программная документация должна быть выполнена в соответствии с ГОСТ 19.105-78 (ЕСПД. Общие требования к программным документам). 

Комплект программного обеспечения должен содержать описание программы, текст программы и исполняемый модуль. 

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

Программа должна запускаться с помощью программы MonU «Монитор для сдачи работ» 643.0691.00249-01. Вывод информации должен осуществляться в окно монитора по каналу межпроцессного обмена. Программа взаимодействует с прибором через интерфейс RS-232. Программа может содержать часть, исполняемую на приборе, а может взаимодействовать со "Служебной программой для модуля М207" 643.0691.00255-01. Эталонные значения версий компонентов изделий должны храниться в текстовом файле в виде, удобном для чтения и редактирования в текстовом редакторе.

Общий алгоритм работы программы:

1.	Программа запускается с помощью скрипта программы MonU. Изделие, версии компонентов которого требуется проверить, определяется параметрами командной строки.

2.	Программа получает доступ к COM порту (или к иному интерфейсу связи с изделием).

3.	Подключается к MonU используя канал межпроцессного обмена.

4.	Открывает файл, содержащий эталонные версии компонентов изделий.

5.	Читает версии из изделия и сравнивает с эталонными. В случае различия, версии выводятся с помощью программы MonU. В случае, если версии всех компонентов изделия совпали, программа выводит "Контроль версий произведён. Результат: НОРМА". В случае, если имели место расхождения: "Контроль версий произведён. Результат: НЕНОРМА".

6.	Программа должна возвращать код результата. 0 – НОРМА, -1 – НЕНОРМА.

Входные параметры, пример:

ver_verify.exe M207

ver_verify.exe ПОТОК-3VSB X7

ver_verify.exe БЦВМб134

ver_verify.exe БС12



Общие сведения о предприятии



Акционерное общество «ГРАНИТ-ВТ» было образовано в 1992 году на базе коллектива сотрудников научно-исследовательского отдела ЦНИИ «ГРАНИТ».

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

Удачным примером работы компании может служить разработка в 1993-94гг. при содействии сотрудников российского представительства компании Intel® вычислительного модуля КРЕДО-486, используемого в настоящий момент в ряде железнодорожных и авиационных систем.

Отдельным этапом деятельности стала организация в 1994 г. совместно с АО «Гамма» (ныне ООО «Гамма Плюс») и при содействии представительства Intel® регионального центра поддержки разработок на основе элементов программируемой логики. В рамках этой деятельности более 40 предприятий (в основном – северо-западного региона России) были снабжены начальной версией САПР для разработки схем на основе программируемой логики, комплектом переводной литературы, возможностью программирования базовых PLD-схем, техническими консультациями. Со многими участниками работы регионального центра ЗАО «ГРАНИТ-ВТ» поддерживает технические контакты и коммерческую кооперацию и по сей день.

В активе предприятия:

- разработка, производство и поддержка в эксплуатации ряда совместимых комплектов электронных модулей на основе магистралей ISA, VME и CompactPCI; 

- разработка локомотивной информационно-управляющей системы повышения безопасности движения для модернизации локомотивов Октябрьской железной дороги; 

- участие в разработке комплексной бесплатформенной навигационной системы для модернизации авионики самолетов гражданской авиации; 

- разработка поездной информационно-управляющей системы с функцией обеспечения автоведения для высокоскоростной магистрали Москва-Санкт-Петербург. 

ЗАО «ГРАНИТ-ВТ» предлагает потребителю ряд вычислительных модулей общего назначения, модулей расширения памяти, интерфейсных и системозависимых модулей. Особенно рекомендуются модули расширения разработки ФГУП ЦНИИ «Гранит» и источники вторичного питания производства ООО «Авионика-Вист».

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

Можно заказать разработку специализированных модулей «под ключ» или любую составную часть такой разработки:

- разработку схемотехнических решений; 

- проектирование логических функций в заданном базисе (программируемые логические микросхемы); 

- разработку топологии печатных плат любой степени сложности с организацией при необходимости их производства; 

- автоматический и ручной монтаж и ремонт электронных модулей практически без ограничений по типу корпусов; 

- нанесение полипараксилиленового влагозащитного покрытия на изделия заказчика; 

- разработку тестового и функционального программного обеспечения; 

- разработку специализированного стендового оборудования. 

За долгие годы разработки специальной управляющей техники коллектив ЗАО «ГРАНИТ-ВТ» приобрел глубокий опыт создания вычислительных модулей, приборов и систем, предназначенных для управления подвижными объектами в реальном времени в тяжелых эксплуатационных условиях (климатические и механические воздействия). Основная предлагаемая ЗАО «ГРАНИТ-ВТ» продукция, в первую очередь, флагманская линия вычислительных и периферийных модулей, предназначена именно для этого сегмента рынка. Сфера применения диктует основные технические принципы, которых, на наш взгляд, следует придерживаться при разработке высоконадежной аппаратуры для ответственных применений и которые являются основой технической политики ЗАО «ГРАНИТ-ВТ»:

- ориентация на промышленные стандарты в части общей вычислительной архитектуры, внутренних и внешних интерфейсов, конструкторских решений, общего программного обеспечения, стендового оборудования, технологических процессов; 

- открытость технических решений, что подразумевает возможность, при необходимости, предоставления потребителю всей технической информации (схемотехническая и конструкторская документация, исходные тексты встроенного, инструментального и тестового программного обеспечения собственной разработки). Открытость документации позволяет пользователю провести сертификацию конечной продукции; 

- использование элементной базы, удовлетворяющей условиям эксплуатации конечной аппаратуры. Как правило, это компоненты в индустриальном исполнении, в расширенном температурном исполнении, в отдельных обоснованных случаях – компоненты, выполненные по военным нормам; 

 	- долгосрочная поддержка воспроизводства (возможность выпуска идентичной аппаратуры в течении длительного срока эксплуатации систем). Основывается на преимущественном использовании компонентов, обладающих долгосрочной поддержкой производителя (long-life support) или являющихся де-факто промышленным стандартом и выпускаемых несколькими производителями; 

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

- обеспечение гарантированного теплосъема путем использования теплопроводящих прокладок, сплошных утолщенных металлизированных слоев в многослойных печатных платах, кондуктивного отвода тепла на несущие конструкции через металлические теплостоки и клиновые замки; 

- использование влагозащитного покрытия на основе полипараксилилена, обеспечивающего отсутствие “воздушных подушек” под SMD-компонентами и, как следствие, отсутствие открытого конденсата на поверхности печатной платы и компонентах при термоциклировании; 

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

- использование ремонтопригодных технологий, обеспечение долгосрочного гарантийного и послегарантийного обслуживания; 

- дифференцированный подход к встроенному системному и функциональному программному обеспечению: возможность разработки специализированных программных комплексов для ответственных критичных по времени применений в управляющих системах реального времени, обеспечивающих рестартуемость (восстановление прерванного хода вычислительного процесса) вычислительного процесса при кратковременных отказах электропитания и функциональных сбоях с сохранением интегральных величин; возможность разработки минимального программного обрамления для обеспечения программирования функциональных задач на языке высокого уровня; совместимость с универсальными ОС реального времени типа VxWorks™, QNX™, ОС2000 и др., подтвержденная опытными работами.



Общие сведения о разработанной программе



Наименование программы  “Программа проверки версий изделий”.

Обозначение исполняемого файла программы – Version-verifier.exe.

Программа написана на языке C++ – CBuilder версии 10.0 фирмы Borland Software Corporation для ОС Windows.


Программа производит проверку версий отдельного модуля или версий модулей входящих в состав прибора по усмотрению пользователя. 

Программа располагается и исполняется на стендовой ЭВМ.

База эталонов версий создается и хранится в файлах “device_list.xml” и “module_list.xml”.

Вызов программы осуществляется запуском исполняемого модуля программы средствами операционной системы, либо из командной строки с параметрами командной строки.

У программы есть один параметр командной строки – наименование изделия.

Пример:



C:\Version-verifier.exe BS12



Или



C:\Version-verifier.exe M207



Через параметр командной строки в программу вводится наименование изделия, подлежащего проверке. Так же наименование изделия можно передать через скрипт “Сервисной программы монитор для сдачи работ” 643.0691.00249-01. Подробнее о скриптах “Сервисной программы монитор для сдачи работ” можно прочитать в руководстве программиста 643.0691.00249-01 33 01.

Информацию о модулях программа получает из XML-файлов “device_list.xml” и “module_list.xml”.

Поправки в работу программы можно внести с помощью файла “corrections.txt”.

Программа может быть запущена через “Сервисную программу монитор для сдачи работ” 643.0691.00249-01. В этом случае результаты работы программы будут выводиться в окне “Сервисной программы монитор для сдачи работ”. О запуске приложений через “Сервисную программу монитор для сдачи работ” можно прочитать в руководстве программиста 643.0691.00249-01 33 01.



Алгоритм программы



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

Производится поиск наименования изделий в файле “device_list.xml”. Сначала производится поиск среди тегов “device” (список приборов), если изделие не обнаружено, то поиск продолжается в теге “default” среди тегов “module”(список модулей). 

Если изделие найдено, то программа получает тип изделия (прибор или модуль). Если изделие не найдено, то выводится сообщение об ошибке. 

Если с входными параметрами было получено наименование модуля, то программа считывает из файла “device_list.xml” базовый адрес модуля по умолчанию.

Затем из файла “module_list.xml” считываются адреса регистров версий, значения версий и разрядность версий соответствующего модуля.

Затем программа считывает фактические значения версий модуля и сравнивает их со значениями, считанными из файла “module_list.xml”. При совпадении этих значений программа выдает норму, при несовпадении – ненорму.

Если с входными параметрами было получено наименование прибора, то программа считывает из файла “device_list.xml” базовые адреса всех модулей, входящих в состав прибора.

Затем из файла “module_list.xml” считываются адреса регистров версий, значения версий и разрядность версий для каждого модуля, входящего в состав прибора.

Затем программа считывает фактические значения версий модулей, входящих в состав прибора, и сравнивает их со значениями, считанными из файла “module_list.xml”. При совпадении этих значений для каждого модуля программа выдает норму, при несовпадении хотя бы для одного модуля – ненорму.



Режимы работы программы



Если программа была запущена “Сервисной программой монитор для сдачи работ” 643.0691.00249-01, то она будет свернута, и вся информация будет выводиться в окне “Сервисной программы монитор для сдачи работ”. После выполнения проверки, программа будет завершена самостоятельно.

Если программа была запущена из командной строки независимо от “Сервисной программы монитор для сдачи работ”, то вся информация будет выводиться в текстовом поле окна программы. После выполнения проверки, программа останется открытой.



Результаты тестирования



При проверке версий прибора фиксируется, результат проверки для каждого модуля, входящего в состав прибора. Если проверка всех модулей завершилась с результатом НОРМА, общий результат – НОРМА. Если проверка хотя бы одного модуля завершилась с результатом НЕНОРМА, то общий результат - НЕНОРМА.

При проверке версий отдельного модуля, результат НОРМА - если проверка завершилась успешно; и НЕНОРМА – если проверка завершилась неудачно.


Входные параметры



Структура XML-файла “device_list.xml”

Файл “device_list.xml” состоит из тегов “device” и тега “default”. 

Тег “device” имеет атрибут “name”, в котором содержится название прибора, соответствующего этому тегу. Внутри тегов “device” содержатся теги “module”, которые имеют атрибут “baseaddress”, содержащий базовый адрес модуля в приборе. Внутри тега “module” указывается название модуля.

Тег “default” содержит в себе теги “module”. Тег “module” имеет один атрибут “baseaddress”, в котором содержится базовый адрес модуля по умолчанию. Внутри тега “module” указывается название модуля.

Структура XML-файла “module_list.xml”

Файл “module_list.xml” состоит из тегов “module”.

Тег “module” содержит в себе тег “name” и теги “version”. Тег “name” содержит в себе название модуля. Тег “version” имеет один атрибут “description”, в котором содержится информация о версии, описываемой соответствующим тегом “version”. Тег “version” содержит в себе теги “address” (адрес регистра версии модуля), “value” (значение версии модуля) и “type” (разрядность версии модуля). 

При выпуске новой версии модуля, тег “name” в соответствующем теге “module” дополняется датой выпуска следующей версии. Затем создается новый тег “module” с наименованием модуля и обновленными значениями версий в теге “version”.

Структура TXT-файла “corrections.txt”

Если есть необходимость проверить прибор с более ранними версиями каких-либо модулей, входящих в его состав, составляется файл поправок “corrections.txt”. Структура файла “corrections.txt” по п. 0.

Если в папке с программой содержится файл “corrections.txt”, то программа производит обработку этого файла.

В процессе обработки заполняется массив поправок, содержащих два наименования модулей: с поздней версией и с более ранней версией.

Файл “corrections.txt” предназначен для внесения поправок в работу программы.

Файл состоит из записей вида: 

<name>=<new_name>;

Здесь “name” – наименование модуля, который необходимо проверить с особыми значениями версий; “new_name” – наименование модуля в файле “module_list.txt” с особыми значениями версий.


Заключение



В ходе преддипломной практики (в период с 15 декабря 2008 по 15 февраля 2009 г.) мною были выполнены поставленные предварительно задачи:

- получены практические навыки работы в коллективе инженеров,

- разработана программа проверки версий компонент изделий,

- подготовлена к выпуску программная документация.


Приложение 1 – Исходные тексты программы



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

#ifndef Unit2H

#define Unit2H

//--------------------------------------------------------------#include <Classes.hpp>

//--------------------------------------------------------------class Executing : public TThread

{

private:

protected:

void __fastcall Execute();

public:

bool 		end;

__fastcall Executing(bool CreateSuspended);

};

//--------------------------------------------------------------#endif

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

#include <vcl.h>

#pragma hdrstop

#include "Unit1.h"

#include "Unit2.h"

#include <stdio.h>

#include "ProgExchCl_b.h"

#include "Udevices.h"

#define SecondLevelNodeAccess Form1->XMLDocument1->DocumentElement->ChildNodes

#define ThirdLevelNodeAccess(a) Form1->XMLDocument1->DocumentElement->ChildNodes->GetNode(a)->ChildNodes


#define FourthLevelNodeAccess(a, b) Form1->XMLDocument1->DocumentElement->ChildNodes->GetNode(a)->ChildNodes->GetNode(b)->ChildNodes

char 		received_data[255];

PModule		Module; 			// массив модулей

PCorrection Correction; // массив исправлений

HANDLE 		m_Disp = NULL; // для монитора

int 		wrtd, // для функции mWrite

cor_count; // количество исправлений

TCom* 		ComPort; // порт

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

void __fastcall msg(char *str)//сообщение для монитора

{

if(!mWrite(m_Disp, (AnsiString(str)+AnsiString("\n\r")).c_str(), strlen(str)+2, &wrtd));

}

void __fastcall logmsg(AnsiString mes)//сообщение в поле мемо

{

Form1->LogText->Lines->Add(mes);

}

//--------------------------------------------------------------char __fastcall DeviceOrModule(AnsiString Parameter, int* item_index) // определить что было передано с начальными параметрами: прибор или модуль и выдать порядковый номер нужного тега.

{

int i, all_nodes;

// ищем прибор

all_nodes = SecondLevelNodeAccess->GetCount(); // количество тегов второго уровня

for (i = 0; i < all_nodes; i++) {

if(AnsiString(SecondLevelNodeAccess->GetNode(i)->Attributes[WideString("name")] ) == Parameter){

*item_index = i;

return 1;

}

}

// если прибор не найден, ищем модуль в теге default

all_nodes = SecondLevelNodeAccess->FindNode("default")->ChildNodes->GetCount(); // количество тегов третьего уровня в теге default

for (i = 0; i < all_nodes; i++) {

if(AnsiString(SecondLevelNodeAccess->FindNode("default")->ChildNodes->GetNode(i)->Text) == Parameter){

*item_index = i;

return 2;

}

}

return 0;

}

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

void __fastcall GetModuleList(AnsiString Parameter, PModule* ModuleList, int item_index, int* modules_counter) // получение списка модулей входящих в состав прибора

{

int 		i, j, k, p, all_modules, version_count;

AnsiString	mes;

*modules_counter = ThirdLevelNodeAccess(item_index)->GetCount(); // количество модулей в приборе

*ModuleList = new TModule[*modules_counter]; // выделяем память под массив модулей


for (i = 0; i < *modules_counter; i++) { // заполняем поля name и baseaddress

if(cor_count)

{

for(j = 0; j < cor_count; j++) {

if (AnsiString(ThirdLevelNodeAccess(item_index)->GetNode(i)->GetNodeValue()) == Correction[j].name) {

(*ModuleList)[i].name = Correction[j].new_name;

break;

}

else (*ModuleList)[i].name = AnsiString(ThirdLevelNodeAccess(item_index)->GetNode(i)->GetNodeValue());

}

}

else (*ModuleList)[i].name = AnsiString(ThirdLevelNodeAccess(item_index)->GetNode(i)->GetNodeValue());

(*ModuleList)[i].baseaddress = StrToInt(ThirdLevelNodeAccess(item_index)->GetNode(i)->Attributes[WideString("baseaddress")]);

}

//	LOG->Add(AnsiString());

// активизация dll со списком модулей

Form1->XMLDocument1->FileName = "module_list.xml";

Form1->XMLDocument1->Active = true;

all_modules = SecondLevelNodeAccess->GetCount(); // сколько всего модулей в базе

for (i = 0; i < *modules_counter; i++) {

for (j = 0; j <= all_modules; j++) { // заполняем поля version

if (j >= all_modules) { // не нашли модуль (ошибка в файле с исправлениями)

mes = AnsiString("Не найден модуль ") + (*ModuleList)[i].name;

MessageBox(NULL, mes.c_str() , "Ошибка", MB_ICONERROR | MB_OK );

break;

}

if ((*ModuleList)[i].name == AnsiString(ThirdLevelNodeAccess(j)->GetNode(0)->GetNodeValue())) {

(*ModuleList)[i].version_count = ThirdLevelNodeAccess(j)->GetCount() - 1;

for (k = 0; k < (*ModuleList)[i].version_count; k++) {

(*ModuleList)[i].version[k] = new TVersion;

(*ModuleList)[i].version[k]->address = StrToInt(FourthLevelNodeAccess(j, k+1)->GetNode(0)->NodeValue);

(*ModuleList)[i].version[k]->value = StrToInt(FourthLevelNodeAccess(j, k+1)->GetNode(1)->NodeValue);

(*ModuleList)[i].version[k]->type = StrToInt(FourthLevelNodeAccess(j, k+1)->GetNode(2)->NodeValue);

(*ModuleList)[i].version[k]->description = AnsiString(ThirdLevelNodeAccess(j)->GetNode(k+1)->Attributes[WideString("description")]);

}

break;

}

}

//		LOG->Add(ModuleList[i].name + AnsiString(" ") + ModuleList[i].baseaddress);

}

}

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


void __fastcall GetModule(AnsiString Parameter, PModule* ModuleList, int item_index) // получаем информацию для одного модуля

{

int i, j, all_modules;

*ModuleList = new (TModule);

(*ModuleList)[0].name = AnsiString(Form1->XMLDocument1->DocumentElement->ChildNodes->FindNode("default")->ChildNodes->GetNode(item_index)->GetNodeValue());

(*ModuleList)[0].baseaddress = StrToInt(Form1->XMLDocument1->DocumentElement->ChildNodes->FindNode("default")->ChildNodes->GetNode(item_index)->Attributes[WideString("baseaddress")]);

Form1->XMLDocument1->FileName = "module_list.xml";

Form1->XMLDocument1->Active = true;

all_modules = SecondLevelNodeAccess->GetCount();

for (i = 0; i <= all_modules; i++) {

if (i >= all_modules) {

MessageBox(NULL, "Модуль не был найден. Версия недоступна", "Error", MB_ICONERROR | MB_OK );

break;

}

if ((*ModuleList)[0].name == AnsiString(ThirdLevelNodeAccess(i)->GetNode(0)->GetNodeValue())) {

(*ModuleList)[0].version_count = ThirdLevelNodeAccess(i)->GetCount() - 1;

for (j = 0; j < (*ModuleList)[0].version_count; j++) {

(*ModuleList)[0].version[j] = new TVersion;

(*ModuleList)[0].version[j]->address = StrToInt(FourthLevelNodeAccess(i, j+1)->GetNode(0)->NodeValue);

(*ModuleList)[0].version[j]->value = StrToInt(FourthLevelNodeAccess(i, j+1)->GetNode(1)->NodeValue);

(*ModuleList)[0].version[j]->type = StrToInt(FourthLevelNodeAccess(i, j+1)->GetNode(2)->NodeValue);

(*ModuleList)[0].version[j]->description = AnsiString(ThirdLevelNodeAccess(i)->GetNode(j+1)->Attributes[WideString("description")]);

}

break;

}

}

/*	LOG->Add((*ModuleList)[0].name + AnsiString(" ") + (*ModuleList)[0].baseaddress);

for (i = 0; i < (*ModuleList)[0].version_count; i++) {

LOG->Add((*ModuleList)[0].version[i]->address);

LOG->Add((*ModuleList)[0].version[i]->value);

LOG->Add((*ModuleList)[0].version[i]->type);

}  */

}

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

unsigned int _fastcall get_version(unsigned int BaseAddress, unsigned int type) // считываем версию с модуля

{

unsigned short i, j;

unsigned short SHsum; // контрольная сумма

unsigned char* pTarget = new unsigned char[10];

unsigned char* pReceived;

unsigned short MessageSize = 6;

unsigned int version;

ComPort = new TCom("COM2", 115200);

i = ComPort->link_on();

if(i) {

MessageBox(NULL, AnsiString(i).c_str(), "Ошибка инициализации порта", MB_OK);

return 0;

}

pTarget[0]= 0x31;

pTarget[1]=(unsigned char)(MessageSize); //младший байт

pTarget[2]=(unsigned char)(MessageSize>>8); //старший байт

pTarget[3] = 0x04;

pTarget[4] = (unsigned char) type;

*(int*)(pTarget + 0x05) = BaseAddress;

version = 0;

SHsum=0x0;

for ( i=3; i<=8; i++ ){SHsum+=pTarget[i];}	//подсчёт КС

//	MessageBox(NULL, AnsiString(SHsum).c_str(), "Контрольная сумма", MB_OK);

pTarget[9]=(unsigned char)(SHsum);//младший байт

pTarget[10]=(unsigned char)(SHsum>>8);//старший байт

ComPort->write(pTarget, 3+MessageSize+2);

delete [] pTarget;

Sleep(100);

i = ComPort->read();

if(i>0)

{

//		MessageBox(NULL, AnsiString(i).c_str(), "Принято байт", MB_OK);

pReceived = ComPort->get_receiver_ptr(); //считываем полученное значение

if ( pReceived[0] != 0x55 || pReceived[1] != 0xAA) {

MessageBox(NULL, pReceived, "Ошибка", MB_OK);

return 0;

}

// наложение масок

switch (type) {

case 1:

version = (unsigned int) (*( char* )(pReceived + 5))&0x000000FF;

break;

case 2:

version = (unsigned int) (*( short* )(pReceived + 5))&0x0000FFFF;

break;

case 4:

version = (unsigned int) *( int* )(pReceived + 5);

break;

default:

version = (unsigned int) (*( short* )(pReceived + 5))&0x0000FFFF;

break;

}

}

ComPort->link_off();

return version;

}

__fastcall Executing::Executing(bool CreateSuspended)// конструктор

: TThread(CreateSuspended)

{

end = false; // метка окончания = ложно

}

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

int __fastcall get_correction(PCorrection* CorrectionList) // обработка файла исправлений

{

int 	i = 0;

int 	j = 0;

int		n = 0;

int 	correction_counter = 0; // количество исправлений

FILE* 	CorrectFilePtr; // файл с исправлениями

char	tempchar = ' ';

char*	tempFile;	 //массив под файл с сиправлениями

char	control_buff[20]; // массив знаков препинания

if ((CorrectFilePtr = fopen("corrections.txt","r")) == NULL) {

return 0;

}

// узнаем размер файла и выделяем временный массив под файл

fseek(CorrectFilePtr,0L,SEEK_END);

n = ftell(CorrectFilePtr);

fseek(CorrectFilePtr,0L,SEEK_SET);

tempFile = new char[n];

//исправляем возможные ошибки пунктуации

while(tempchar == '\n' || tempchar == ' '){

tempchar = fgetc(CorrectFilePtr);

}

tempFile[0] = tempchar;

i = 1;

while (1){

tempchar = fgetc(CorrectFilePtr);

if(tempchar == '\n'){

continue;

}

if(tempchar == ' '){

continue;

}

if(tempchar == '='){

control_buff[j] = tempchar;

j++;

}

if(tempchar == ';'){

control_buff[j] = tempchar;

correction_counter++;

j++;

}

if(tempchar == EOF){

tempFile[i] = tempchar;

control_buff[j] = tempchar;

break;

}

tempFile[i] = tempchar;

i++;

}

//правильно ли расставлены знаки припенания

for (i = 0; i <= j; i++){

if(control_buff[i] == '='){

if(control_buff[i+1] != ';'){

logmsg("В файле корректировки обнаружена ошибка. Корректировки учтены не будут33");

return 0;

}

}

if(control_buff[i] == ';'){

if(!(control_buff[i+1] == '=' || control_buff[i+1] == EOF)){

logmsg("В файле корректировки обнаружена ошибка. Корректировки учтены не будут331");

return 0;

}

}

}

//	MessageBox(NULL, tempFile,"Пpочитано",MB_OK);

*CorrectionList = new TCorrection[correction_counter];

//заполянем массив исправлений

tempchar = 0;

i = 0;

n = 0;

while (tempchar != EOF) {

while(tempFile[i] != '=') {

(*CorrectionList)[n].name += tempFile[i++];

}

//		(*CorrectionList)[n].name[j] = '\0';

i++;

while(tempFile[i] != ';') {

(*CorrectionList)[n].new_name += tempFile[i++];

}

//		(*CorrectionList)[n].new_name[j] = '\0';

n++;

tempchar = tempFile[++i];

}

/*	for (j = 0; j < correction_counter; j++) {

MessageBox(NULL, (*CorrectionList)[j].name,"",MB_OK);

MessageBox(NULL, (*CorrectionList)[j].new_name,"",MB_OK);

} */

delete [] tempFile;

fclose(CorrectFilePtr);

return correction_counter;

}

//--------------------------------------------------------------void __fastcall Executing::Execute()

{

CoInitialize(NULL);

char 			item_type;

DWORD 			res;

char			received_data[255];

unsigned int	received_version = 0;

AnsiString 		mes;

int 			i, j, index, modules_counter, all_modules, p, param_num;

int 			error = 0;

if(!FileExists("device_list.xml")){

MessageBox(NULL, "Файл device_list.xml не был найден ", "Ошибка", MB_ICONERROR | MB_OK );

PostMessage(Form1->Handle, WM_CLOSE, 0,0);

return;

}

if(!FileExists("module_list.xml")){

MessageBox(NULL, "Файл module_list.xml не был найден ", "Ошибка", MB_ICONERROR | MB_OK );

PostMessage(Form1->Handle, WM_CLOSE, 0,0);

return;

}

//	обработка входных параметров

if (ParamCount() == 0) {

MessageBox(NULL, "Не было передано ни одного параметра!", "Ошибка", MB_ICONERROR | MB_OK );

PostMessage(Form1->Handle, WM_CLOSE, 0,0);

return;

}

// получить управление над функциями библиотеки ProgExchCl.dll

res = ProgExchCl_LoadLibrary();

if(res != 0x0)

{

sprintf(received_data, "Ошибка %d при обращении к библиотеке \"ProgExchCl.dll\".", res);

MessageBox(NULL, received_data, "Ошибка", MB_OK);

}

//открытие канала выдачи данных на экран

sprintf(received_data, "PipeDisplay%d", GetCurrentProcessId());

res = mOpen(received_data, &m_Disp);

if(res == 0x0)

{

// перевести вывод в режим отладочной (0x01 0x02) или отчетной (0x01 0x01) информации

received_data[0] = 0x01; received_data[1] = 0x01;

res = mWrite(m_Disp, received_data, 2, &wrtd);

if(res != 0x0)

{

sprintf(received_data, "Ошибка %d при переводе вывода в режим отладочной информации", res);

MessageBox(NULL, received_data, "Ошибка", MB_OK);

logmsg(received_data);

}

Form1->WindowState = wsMinimized;

}

else {

sprintf(received_data, "Ошибка %d при открытии канала выдачи данных на экран", res);

logmsg(AnsiString(received_data));

logmsg(AnsiString("Режим автономной работы"));

Form1->WindowState = wsNormal;

}

cor_count = get_correction(&Correction);

// открытие XML-файла

Form1->XMLDocument1->FileName = "device_list.xml";

Form1->XMLDocument1->Active = true;

item_type = DeviceOrModule(ParamStr(1), &index);

// получение списка модулей входящих в состав прибора

if (item_type == 0){

MessageBox(NULL, "Прибор или модуль не был найден", "Ошибка", MB_ICONERROR | MB_OK );

PostMessage(Form1->Handle, WM_CLOSE, 0,0);

return;

}

if (item_type == 1) {

GetModuleList(ParamStr(1), &Module, index, &modules_counter);

if(index == -1) {

PostMessage(Form1->Handle, WM_CLOSE, 0,0);

return;

}

mes = AnsiString("Проверка версии прибора: ") + ParamStr(1);

}

if (item_type == 2) {

GetModule(ParamStr(1), &Module, index);

if(index == -1) {

PostMessage(Form1->Handle, WM_CLOSE, 0,0);

return;

}

mes = AnsiString("Проверка версии модуля: ") + ParamStr(1);

modules_counter = 1;

}

msg(" ");

msg(" ");

msg(mes.c_str());

logmsg(mes.c_str());

// перевести вывод в режим отладочной (0x01 0x02) или отчетной (0x01 0x01) информации

received_data[0] = 0x01; received_data[1] = 0x02;

res = mWrite(m_Disp, received_data, 2, &wrtd);

if(res != 0x0)

{

//		sprintf(received_data, "Ошибка %d при переводе вывода в режим отладочной информации", res);

//		MessageBox(NULL, received_data, "Ошибка", MB_OK);

}

// вывод результатов тестирования по каждому модулю

for (i = 0; i < modules_counter; i++) {

// название модуля

msg(" ");

msg(Module[i].name.c_str());

logmsg(" ");

logmsg(Module[i].name.c_str());

for (j = 0; j < Module[i].version_count ; j++) {

received_version = get_version( (unsigned int) (Module[i].baseaddress + Module[i].version[j]->address), Module[i].version[j]->type);

// если версии совпадают, то НОРМА, если не совпадают, то НЕНОРМА

if(received_version == Module[i].version[j]->value){

mes =AnsiString(" ") + Module[i].version[j]->description + AnsiString(" 0x") + IntToHex((int) Module[i].version[j]->value, Module[i].version[j]->type) + AnsiString(" :HOPMA ");

msg(mes.c_str());

logmsg(mes.c_str());

}

else {

mes =AnsiString(" ") + Module[i].version[j]->description + AnsiString(" 0x") + IntToHex((int) received_version, Module[i].version[j]->type) + AnsiString(" :HEHOPMA ") + AnsiString("(должно быть 0x") + IntToHex((int) Module[i].version[j]->value, Module[i].version[j]->type) + AnsiString(")");

msg(mes.c_str());

logmsg(mes.c_str());

error+=1;

}

}

}

// перевести вывод в режим отладочной (0x01 0x02) или отчетной (0x01 0x01) информации

received_data[0] = 0x01; received_data[1] = 0x01;

res = mWrite(m_Disp, received_data, 2, &wrtd);

if(res != 0x0)

{

//		sprintf(received_data, "Ошибка %d при переводе вывода в режим отчетной информации", res);

//		MessageBox(NULL, received_data, "Ошибка", MB_OK);

}

// общий результат тестирования

if(error)	{

msg(" ");

msg("Результат: НЕНОРМА");

logmsg(" ");

logmsg("Результат: НЕНОРМА");

}

else	{

msg(" ");

msg("Результат: НОРМА");

logmsg(" ");

logmsg("Результат: НОРМА");

}

// освобождаем динамически выделенную память

if (item_type == 1) {

delete [] Module;

}

else delete Module;

delete [] Correction;

if(mClose != NULL)

{

// отключить каналы обмена

mClose(m_Disp);

}

ProgExchCl_FreeLibrary();

CoUninitialize();

PostMessage(Form1->Handle, WM_CLOSE, 0,0);

}

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

#ifndef Unit1H

#define Unit1H

//--------------------------------------------------------------#include <Classes.hpp>

#include <Controls.hpp>

#include <StdCtrls.hpp>

#include <Forms.hpp>

#include <msxmldom.hpp>

#include <XMLDoc.hpp>

#include <xmldom.hpp>

#include <XMLIntf.hpp>

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

typedef struct _SVersion{

unsigned int	address; //адрес регистра версии

unsigned int	value; 	//считанное значение версии

unsigned int	type;		//разрядность версии

AnsiString		description;//описание версии

} TVersion,* PVersion;

typedef struct _SModule{

AnsiString 	name; //имя модуля

unsigned int	baseaddress; //базовый адрес модуля

int				version_count;//количество версий у модуля

PVersion		version[10]; //массив версий модуля

} TModule,* PModule;

typedef struct _SCorrection{

AnsiString	name;

AnsiString	new_name;

} TCorrection,* PCorrection;

class TForm1 : public TForm

{

__published:	// IDE-managed Components

TXMLDocument *XMLDocument1;

TMemo *LogText;

void __fastcall FormActivate(TObject *Sender);

void __fastcall FormClose(TObject *Sender, TCloseAction &Action);

private:	// User declarations

public:		// User declarations

__fastcall TForm1(TComponent* Owner);

};

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

extern PACKAGE TForm1 *Form1;

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

#endif

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

#include <vcl.h>

#pragma hdrstop

#include "Unit1.h"

#include "Unit2.h"

#include <stdio.h>

//--------------------------------------------------------------#pragma package(smart_init)

#pragma resource "*.dfm"

Executing	*Thread;

TForm1 *Form1;

tagMSG lpMsg;

//--------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

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

void __fastcall TForm1::FormActivate(TObject *Sender)

{

Thread = new Executing(FALSE); // запускаем поток

}

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

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)

{

Thread->WaitFor();

delete (Thread);

}

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

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

#ifndef UdevicesH

#define UdevicesH

#include <classes.hpp>

//#include "U_MK_pipe.h"

#include <Mask.hpp>

//--------------------------------------------------------------// Абстрактный класс, реализующий базовые функции любого устройства

class TDevFather: public TObject

{

__published:

private:	// User declarations

protected:

bool active;

char receiver[0x1000];//априорно выделено 4кб буфера, приготовлены для отправки классу монитору

int receiver_size;//размер реально принятых байт в буфере

public:

virtual __fastcall TDevFather();

virtual __fastcall ~TDevFather();

virtual int __fastcall link_on();

virtual int __fastcall link_off();

//функции для работы с мостом в целях ввода/вывода

//чтение из буфера устройтва

virtual int __fastcall scan();//Возвращает признак состояния устройства

virtual int __fastcall read();//Если положительное число, то это число пинятых байт, если отрицательное, то это код ошибки

virtual char* __fastcall get_receiver_ptr();//

//отправить данные

virtual int __fastcall write(char* chs, int size);//передача символов/байтов на устройство

//запись в буфер

//virtual int __fastcall add_to_sender(char* chs, int size);//передача символов/байтов в передающий буфер

};

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

class TCom: public TDevFather

{

__published:

private:	// User declarations



protected:

AnsiString comname;

int baudrate;

HANDLE com_hndl;

DCB st_dcb;

public:

virtual __fastcall TCom(char* comname, int baudrate);

virtual __fastcall ~TCom();

int __fastcall link_on();

int __fastcall link_off();



//функции для работы с мостом в целях ввода/вывода

//чтение из буфера устройтва

int __fastcall scan();//Возвращает признак состояния устройства

int __fastcall read();//Если положительное число, то это число пинятых байт, если отрицательное, то это код ошибки

//virtual char* __fastcall get_receiver_ptr();// метод наследуется без изменения

//отправить данные

virtual int __fastcall write(char* chs, int size);//передача символов/байтов на устройство

//запись в буфер

//virtual int __fastcall add_to_sender(char* chs, int size);//передача символов/байтов в передающий буфер

void __fastcall set_comname(AnsiString comname);

void __fastcall set_baudrate(int baudrate);

AnsiString __fastcall get_comname();

int __fastcall get_baudrate();

};

//--------------------------------------------------------------#endif

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

#pragma hdrstop

#include <Forms.hpp>

#include <Mask.hpp>

#include "Udevices.h"

//--------------------------------------------------------------__fastcall TDevFather::TDevFather(){}

//--------------------------------------------------------------__fastcall TDevFather::~TDevFather(){}

//--------------------------------------------------------------int __fastcall TDevFather::link_on()

{ return 0; }

//--------------------------------------------------------------int __fastcall TDevFather::link_off()

{ return 0; }

//-------------------------------------------------------------- //функции для работы с мостом

int __fastcall TDevFather::scan()//Возвращает признак состояния устройства

{

//

return receiver_size;

}

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

int __fastcall TDevFather::read()//Если положительное число, то это число принятых байт, если отрицательное, то это код ошибки

{

//

return receiver_size;

}

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

char* __fastcall TDevFather::get_receiver_ptr()//

{

return receiver;

}

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

int __fastcall TDevFather::write(char* chs, int size)

{

return size;

}

//---------------TCom-------------------------------------------__fastcall TCom::TCom(char* comname, int baudrate)

{

//

TCom::comname=comname; //="COM1";

TCom::baudrate=baudrate; //=115200;

active=false;

}

//--------------------------------------------------------------__fastcall TCom::~TCom()

{

//

if(active)

{

link_off();

}

}

//--------------------------------------------------------------int __fastcall TCom::link_on()

{

//

if (!active)

{

com_hndl=CreateFile(comname.c_str(), GENERIC_READ | GENERIC_WRITE , 0, NULL, OPEN_EXISTING, 0, 0);

if (com_hndl == INVALID_HANDLE_VALUE)

{

//MessageBoxA(0,"Invalid handle value","Simple_COM", MB_OK);

active=false;

return -1;

}

//настройка параметров соединения

st_dcb.DCBlength= sizeof(DCB);

st_dcb.Parity=NOPARITY; //NOPARITY, ODDPARITY, MARKPARITY	, EVENPARITY

st_dcb.StopBits=ONESTOPBIT; //ONESTOPBIT , ONE5STOPBITS	, TWOSTOPBITS

st_dcb.ByteSize=8; //4-8

st_dcb.BaudRate=baudrate; //CBR_115200

SetCommState(com_hndl, &st_dcb);

if ( com_hndl == INVALID_HANDLE_VALUE)

{

//MessageBoxA(0,"Invalid handle value","Simple_COM", MB_OK);

active=false;

return -1;

}

SetupComm(com_hndl, 40000, 40000);//размеры банков

if (com_hndl == INVALID_HANDLE_VALUE)

{

//MessageBoxA(0,"Invalid handle value","Simple_COM", MB_OK);

active=false;

return -1;

}

SetCommMask(com_hndl,EV_RXCHAR);

if (com_hndl == INVALID_HANDLE_VALUE)

{

//MessageBoxA(0,"Invalid handle value","Simple_COM", MB_OK);

active=false;

return -1;

}

active=true;

};

if (!active)

{

return -1;

}else{

return 0;

}

}

//--------------------------------------------------------------int __fastcall TCom::link_off()

{

//

if (active)

{

active=false;

CloseHandle(com_hndl);

return 0;

}

else

{

active=false;

return -1;

}

}

//--------------------------------------------------------------int __fastcall TCom::scan()//Возвращает признак состояния устройства

{

COMSTAT st;

unsigned long Err;

if (active)

{

if ( ClearCommError(com_hndl, &Err, &st) )

{

return st.cbInQue;

}

else

{

//MessageBoxA(0,"Com scan error","Simple_COM", MB_OK);

return -1;

}

}

else

{

return 0;

}

}

//--------------------------------------------------------------int __fastcall TCom::read()//Если положительное число, то это число пинятых байт, если отрицательное, то это код ошибки

{

COMSTAT st;

unsigned long Err;

unsigned long readed_bytes;

//

readed_bytes=0;

if (active)

{

if ( ClearCommError(com_hndl, &Err, &st) )

{

if ( (Err & CE_BREAK)>0 )

{

//MessageBoxA(0,"Com read error : CE_BREAK","Simple_COM", MB_OK);

return -2;

}

if ( 0x1000>st.cbInQue )

{

if (! ReadFile(com_hndl, receiver, st.cbInQue, &readed_bytes, NULL) )

{

//MessageBoxA(0,"Com read error : ReadFile 1","Simple_COM", MB_OK);

return -3;

}

}

else

{

if (! ReadFile(com_hndl, receiver, 0x1000, &readed_bytes, NULL) )

{

//MessageBoxA(0,"Com read error : ReadFile 2","Simple_COM", MB_OK);

return -4;

}

}

}

else

{

//MessageBoxA(0,"0шибка сканирования устройства COM","Simple_COM", MB_OK);

}

}

return (int)readed_bytes;

}

//--------------------------------------------------------------int __fastcall TCom::write(char* chs, int size)

{

unsigned long sended;

//

sended=0;

if (! WriteFile(com_hndl, chs, (unsigned long)size, &sended, NULL) )

{//ошибка

//MessageBoxA(0, "Ошибка передачи данных", "Simple_COM", MB_OK);

return -1;

}

return (int)sended;

}

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

void __fastcall TCom::set_comname(AnsiString comname){}

void __fastcall TCom::set_baudrate(int baudrate){}

AnsiString __fastcall TCom::get_comname()

{//

return comname;

}

//--------------------------------------------------------------int __fastcall TCom::get_baudrate()

{//

return baudrate;

}





2