voron
Интересующийся
Offline
|
|
« : 03-08-2010 21:00 » |
|
У меня есть вопросы по UNIОРС - может посоветуете как выкрутится... Вопрос состоит в том чтобы сделать драйвер для устройства RS232 (Контроллер WE2108) . Есть пример но в нем не ясно ОРС берет функции передачи в порт на себя или нужно все формировать . Коротко драйвера еще не делал. Все очень туго... И еще придется потом расширяться до 11 устройств (конвертеры в RS485) - Помогите пожалуйста
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #1 : 04-08-2010 05:27 » |
|
вы про это и это? а зачем вам свой драйвер, чем вам штатный не угодил? вам вообще API достаточно будет... PS там сейчас win98 ставят? PPS выкладывайте пример...
|
|
« Последнее редактирование: 04-08-2010 05:45 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
voron
Интересующийся
Offline
|
|
« Ответ #2 : 04-08-2010 07:34 » |
|
вы про это и это? а зачем вам свой драйвер, чем вам штатный не угодил? Его и хочу изменить Кажется все просто только опыта не хватает Добавлено через 4 дня, 2 часа, 51 минуту и 56 секунд:Вот пример: /* (C) Fastwel Inc. 1999
Демонстрационная реализация user-defined DLL для универсального OPC сервера. Может служить "болванкой" для разработки настоящего сервера.
ВНИМАНИЕ! В данном примере предполагается, что в адресном пространстве сервера (видимом клиентам через IBrowseServerAddressSpace) будет задано одно "устройство" с несколькими группами тегов. Более "продвинутый" (но и более сложный) пример с несколькими устройствами находится в файле dataserv.cpp. */
#include "windows.h" #include "dataserv.h" #include <math.h> #include <process.h> #include <stdio.h>
#define MAX_TAG 5
// Массивы тегов, видимых OPC-сервером // (для простоты они одинаковой длины, // в реальности, массивы, конечно, будут разные)
TAnTag AnTag[MAX_TAG]; TBitTag BitTag[MAX_TAG]; TIntTag IntTag[MAX_TAG];
// структура, рассказывающая OPC-серверу, где находятся массивы тегов...
TDataForOPCServer DataForOpc={1,MAX_TAG,AnTag,MAX_TAG,BitTag,MAX_TAG,IntTag,0};
// ... и функция, возвращающая OPC-серверу указатель на эту структуру:
__declspec( dllexport ) const TDataForOPCServer * PASCAL GetDataForOPCServer() { return &DataForOpc; };
//=== Функции изменения тегов разного типа: ==================
// функция для изменения значения аналогового тега
__declspec( dllexport ) unsigned char PASCAL SetAnTagValue( unsigned number, // номер тега в массиве float value // новое значение параметра ) { if(number<0 || number>=MAX_TAG) return FALSE; AnTag[number].value=value;
// здесь по идее нужно записать значение в реальное // физическое устройство. При неудаче вернуть FALSE. return TRUE; };
//--------------------------------------------------------------------------- // функция для изменения значения битового тега
__declspec( dllexport ) unsigned char PASCAL SetBitTagValue( unsigned number, // номер тега в массиве unsigned char value // новое значение параметра ) { if(number<0 || number>=MAX_TAG) return FALSE; BitTag[number].value=value; // здесь по идее нужно записать значение в реальное // физическое устройство. При неудаче вернуть FALSE. return TRUE; };
//--------------------------------------------------------------------------- // функция для изменения значения целого тега
__declspec( dllexport ) unsigned char PASCAL SetIntTagValue( unsigned number, // номер тега в массиве int value // новое значение параметра ) { if(number<0 || number>=MAX_TAG) return FALSE; IntTag[number].value=value; // здесь по идее нужно записать значение в реальное // физическое устройство. При неудаче вернуть FALSE. return TRUE; };
//---------------------------------------------------------------------------
float Dt= (float)0.01; float Tt;
// Главная рабочая нить DLL, в которой должен происходить опрос // устройства и обновление значений в массивах тегов:
void WorkingThread( void *dummy ) // Thread function { while(1) { int i; Sleep(100); // пауза 0,1 секунды // Заснуть на некоторое время надо обязательно, // иначе эта нить не даст житья OPC-серверу и другим приложениям! // (можно заснуть на меньший период, допустимо до 10 ms) Tt=Tt+Dt; if(Tt>10) Tt=Tt-(float)3.1415926*3; for(i=1; i != MAX_TAG; i++) // Для демонстрационных // целей мы не изменяем тег No 1, чтобы в него можно // было спокойно записывать значения из OPC-клиентов { // симулируем изменение значений: AnTag[i].value= (float)sin(Tt+i); BitTag[i].value= (AnTag[i].value>0)? 1:0; IntTag[i].value= (int)(AnTag[i].value * 10); // Вместо симуляции в реальном сервере здесь // должен происходить опрос устройства и обновление // значений }; }; };
//--------------------------------------------------------------------------- // Класс, конструктор которого запускает рабочую нить DLL // (это можно делать и из DLLEntryPoint по DLL_PROCESS_ATTACH, // но через конструктор объекта, кажется, удобнее)
class MyWorkingThread { public:
MyWorkingThread() // Все делает конструктор: {
// Заполняем массив имен тегов для OPC-сервера: for(int i=0; i != MAX_TAG; i++) { char s[64]=""; char ss[64]=""; char sss[64]="";
char* prefix= (i<MAX_TAG/2)? "unit1." : "unit2."; // Демонстрация того, как действует символ "." (точка) // внутри имени тега. Если, например, имя тега имеет вид // unit1.tag1, то OPC сервер создаст группу тегов unit1 // (внутри устройства) и добавляет тег tag1 (уже без префикса) // в эту группу. Таким образом можно структурировать пространство // имен. Более глубокие уровни вложенности не поддерживаются //(то есть точка в имени, если она есть, должна быть только одна) sprintf(s,"%sanalog_%d",prefix,i); sprintf(ss,"%sbit_%d",prefix,i); sprintf(sss,"%sint_%d",prefix,i); AnTag[i].setName(s); BitTag[i].setName(ss); IntTag[i].setName(sss); }; // Создаем рабочую нить: _beginthread( WorkingThread, 0, NULL ); }; };
//=========================================================
/* инициализация статического объекта, конструктор которого сразу после загрузки DLL создает рабочую нить (чтобы не возиться с DLLEntryPoint - хотя это, конечно, дело разработчика): */ MyWorkingThread* mythread=new MyWorkingThread;
Добавлено через 9 часов, 17 минут и 45 секунд:Да !!!!!!!! Это все будет работать на ХР
|
|
« Последнее редактирование: 04-08-2010 16:52 от voron »
|
Записан
|
|
|
|
|
voron
Интересующийся
Offline
|
|
« Ответ #4 : 04-08-2010 18:21 » |
|
Главное правильно поставить вопрос! Спасибо за ссылку! Буду продолжать разбираться... Добавлено через 20 дней, 20 часов, 26 минут и 39 секунд:Вот нашел здесь http://www.pcports.ru/SerialGate.php библиотеку. Буду пытаться сегодня лепить драйвер
|
|
« Последнее редактирование: 25-08-2010 14:47 от voron »
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #5 : 25-08-2010 15:11 » |
|
эта библиотека - из разряда "люди, где можно найти компонент Hello World, для delphi?"(с)
|
|
« Последнее редактирование: 25-08-2010 15:14 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
voron
Интересующийся
Offline
|
|
« Ответ #6 : 25-08-2010 15:59 » |
|
) Добавлено через 1 день, 16 часов, 11 минут и 51 секунду:Вот что получается: #include "windows.h" #include "dataserv.h" #include "SerialGate.h"
//#include <math.h> #include <iostream> #include <conio.h> #include <process.h> #include <stdio.h> #include <string.h>
#define MAX_TAG 1 //для начала взял 1 тег
TAnTag AnTag[MAX_TAG];
// структура, рассказывающая OPC-серверу, где находятся массивы тегов...
//TDataForOPCServer DataForOpc={1,MAX_TAG,AnTag,MAX_TAG,BitTag,MAX_TAG,IntTag,0}; TDataForOPCServer DataForOpc={1,MAX_TAG,AnTag,0};//Подправил структуру
// ... и функция, возвращающая OPC-серверу указатель на эту структуру:
__declspec( dllexport ) const TDataForOPCServer * PASCAL GetDataForOPCServer() { return &DataForOpc; };
//=== Функции изменения тегов аналог. типа: ==================
// функция для изменения значения аналогового тега
__declspec( dllexport ) unsigned char PASCAL SetAnTagValue( unsigned number, // номер тега в массиве float value // новое значение параметра ) { if(number<0 || number>=MAX_TAG) return FALSE; AnTag[number].value=value; //<<<<<<<<ВНИМАНИЕ<<<<<<<<<<<<
int port = 1; int rate = 9600;
SerialGate sg;
bool res = sg.Open(port, rate); if(res == false) {return 0;}
while(true) { char sbuf[13] ="S98;MSV?;S00;"; for(int i; i<strlen(sbuf)+1; i++) {char c=sbuf[i];
sg.Send(&c, sizeof(c));
if(i == strlen(sbuf)+1) break;} }
sg.Close();
return TRUE; else return FALSE; };
// Главная рабочая нить DLL, в которой должен происходить опрос // устройства и обновление значений в массивах тегов:
void WorkingThread( void *dummy ) // Thread function { int port = 1; int rate = 9600;
SerialGate sg; bool res = sg.Open(port, rate); if(res == false){return 0;}
char buf[30]; int dwBytesRead = 0; bool terminate = false; while(!terminate) { Sleep(100); // пауза 0,1 секунды // Заснуть на некоторое время надо обязательно, // иначе эта нить не даст житья OPC-серверу и другим приложениям! dwBytesRead = sg.Recv(buf, sizeof(buf));
for(int j = 0; j < dwBytesRead; j++) { if((buf[j+1]<'0')||(buf[j+1]>'9')); //неправильный формат float eror=0; AnTag[i].value=(float)eror; else { for(int i=1; i != MAX_TAG; i++) AnTag[i].value=(float)atof(buf); if(buf[j] == 'LF'){terminate = true; break;} } } } sg.Close(); }
//--------------------------------------------------------------------------- // Класс, конструктор которого запускает рабочую нить DLL // (это можно делать и из DLLEntryPoint по DLL_PROCESS_ATTACH, // но через конструктор объекта, кажется, удобнее)
class MyWorkingThread { public:
MyWorkingThread() // Все делает конструктор: {
// Заполняем массив имен тегов для OPC-сервера: for(int i=0; i != MAX_TAG; i++) { char s[64]="";
char* prefix= (i<MAX_TAG/2)? "unit1." : "unit2."; // Демонстрация того, как действует символ "." (точка) // внутри имени тега. Если, например, имя тега имеет вид // unit1.tag1, то OPC сервер создаст группу тегов unit1 // (внутри устройства) и добавляет тег tag1 (уже без префикса) // в эту группу. Таким образом можно структурировать пространство // имен. Более глубокие уровни вложенности не поддерживаются //(то есть точка в имени, если она есть, должна быть только одна) sprintf(s,"%sanalog_%d",prefix,i); AnTag[i].setName(s); }; // Создаем рабочую нить: _beginthread( WorkingThread, 0, NULL ); }; };
//=========================================================
/* инициализация статического объекта, конструктор которого сразу после загрузки DLL создает рабочую нить (чтобы не возиться с DLLEntryPoint - хотя это, конечно, дело разработчика): */ MyWorkingThread* mythread=new MyWorkingThread; ////////////////////////////////////////////////////////////////////////////// Я подозреваю что контр. ничего не поймет. Скорее всего нужно будет перевести в hex запрос и c ответом шаманить. Надеюсь до 13 сентября успею
|
|
« Последнее редактирование: 27-08-2010 08:11 от voron »
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #7 : 27-08-2010 08:12 » |
|
что сказать.... пробуйте! если не получится курите мануалы))) PS но есть ошибки в цикле SetAnTagValue() и еще один "забубух" очень забавный... там же) PPS кстати рекомендую при форматировании кода пользоваться либо табами либо пробелами - но чем нибудь одним. а то вот так вот потом перемешивается... и кстати, перед тем как сервер писать - лучше сначала com-управление проверить. а то непонятно будет, где ошибки искать)
|
|
« Последнее редактирование: 27-08-2010 19:45 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
voron
Интересующийся
Offline
|
|
« Ответ #8 : 28-08-2010 10:09 » |
|
Еще не пробовал этот вариант. Прибор на работе. Но когда пробовал сервер "сериал-гейтовский" то все запросы игнорировались - отсюда мысль насчет формата. PS в прошлом году как-то еще тогда просто ради интереса делал приложение на делфях - оно просто сбрасывало в файл hex ответ, а на Label прописывал преобразователь char. И все улыбались - тогда. А сейчас так не катит "спиногрызы". Увлекся. Суть в том что работало. Правда запрос был через edit.
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #9 : 28-08-2010 17:01 » |
|
ниииче не понял)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #10 : 28-08-2010 17:25 » |
|
Ochkarik, попробуй альт+стрелку влево
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #11 : 28-08-2010 18:49 » |
|
Алексей1153++, пробовал, в хроме не работает
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
voron
Интересующийся
Offline
|
|
« Ответ #12 : 16-01-2011 07:42 » |
|
Ничего не вышло. Ochkarik, а "есть ошибки в цикле SetAnTagValue() Ага и еще один "забубух" очень забавный... там же)" - не могли бы вы по подробнее показать на ошибки
Добавлено через 15 минут и 6 секунд: С начала разберусь с СОМ-портом. Затем перейду к драйверу. Рассчитываю на вашу поддержку
|
|
« Последнее редактирование: 16-01-2011 07:57 от voron »
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #13 : 30-01-2011 00:16 » |
|
while(true) { char sbuf[13] ="S98;MSV?;S00;"; for(int i; i<strlen(sbuf)+1; i++) { char c=sbuf[i]; sg.Send(&c, sizeof(c)); if(i == strlen(sbuf)+1) break; } }
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #14 : 31-01-2011 02:06 » |
|
признаюсь, не перечитывал весь топик, но вот это выглядит лишним if(i == strlen(sbuf)+1) break;
А вот i нужно инициализировать. ЗЫ может я просто не въехал
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #15 : 31-01-2011 09:56 » |
|
resource, угу) а про внешний while(true), что думаешь?)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #16 : 31-01-2011 15:16 » |
|
Ну я просто думал, что может я чего-то недопонимаю. Такое ощущение что этим break'ом хотели выйти из while. Об этом только гадать можно, но надо ли
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #17 : 31-01-2011 15:20 » |
|
ага, я и говорю, "забубух" с ошибками)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
voron
Интересующийся
Offline
|
|
« Ответ #18 : 12-05-2011 17:53 » |
|
Всем спасибо! Разобрался с драйвером. SerialGate не использовал
|
|
|
Записан
|
|
|
|
|