ULiX
Зарегистрирован: 18.04.2007 Сообщения: 3 Откуда: Комсомольск-на-Амуре
|
Добавлено: Ср Апр 18 2007 12:46 Заголовок сообщения: Обработка ошибок при чтении\записи в устройство. |
|
|
По ппорядку о проблеме.
-= Объект =-
Существует определённое устройство.
Это устройство подключено через интерфейсную плату KOP.
Для данной платы устанавливается драйвер под DOS.
Драйвер обеспечиывает доступ к устройству посредством чтения записи в интерфейсы "KOP0" ... "KOPF".
Т.е. например, "Мост переменного тока" подключен к интерфейсной плате с адресом 1. Тогда для общения с данным прибором, мы должны посылать и считывать управляющие последовательности символов в интерфейс "KOP1".
Открывается интерфейс как обычный поток, или файл:
p5083=open("KOP1",O_RDWR);
или в BASIC:
OPEN "KOP1" FOR RANDOM AS 1
Запись чтение осуществляется командами:
n_bait = _write(p5083,s,len);
err = _read(p5083,p,ReadMsr);
-== Проблема ==-
Суть проблемы заключается в том, что нет возможности считывать состояние прибора в данный момент времени.
После подачи устройству управляющих символов, оно переходит в режим измерения. До завершения измерений, процес чтения\записи в устройство вызывает ошибку, так как прибор не отвечает на запросы, а занят процессом измерения.
Изучив исходники программы, я нашёл, как эту проблему решили косвенно. Но до конца разобраться не смог.
Привожу полный листинг поцедур библиотеки управления:
Код: |
/*
* Файл CP5083.h
* Макроопределения для работы
* и описания функций управления
* МОСТОМ P5083
*/
#ifndef _CP5083_H
#define _CP5083_H
#ifndef __STDIO_H
#include<stdio.h>
#endif
#define LenMsr 40 /* Длина (байт) сообщения от МОСТА */
#define LenStringMsr (50+1)
#define ReadMsr 29
/* Ошибки при работе с МОСТОМ */
#define NO_ERR_M 0 /* Нет ошибок */
#define NO_OPEN_KOP 1 /* Не открыт канал на устройство КОП */
#define ERR_OPEN_KOP 2 /* Ошибка открытия устройства КОП */
#define ERR_WR_M 3 /* Ошибка записи в МОСТ */
#define ERR_RD_M 4 /* - - - чтения с МОСТА */
#define ERR_PARM_M 5 /* - - - в задании параметров */
#define ERR_F_M 6 /* - - - в задании частоты */
#define PRIMARY_MSR 1
#define SECOND_MSR 2
//#define ERR_FILENAME 7 /* - - - в задании имени файла */
//#define ERR_OPEN_FILE 8 /* - - - открытия файла */
//#define ERR_WR_FILE 9 /* - - - записи в файл */
enum P5083SW { Off,On,R,C,L,Parallel,Serial,Tg_fi,Tg_s };
extern int cdecl ch_setmost();
extern int cdecl most_msr();
extern char* cdecl read_msr1(char *s);
struct Measure_P5083
{ float primary_msr,
second_msr,
frequency;
char prim_s,second_s;
int measure();
int measure(float f);
float ret(int btypemsr);
int sprint(char *pszStr);
char **primname();
char **secondname();
char primsym();
};
struct DriverMostP5083
{
int PrmP5083,
NumberUsr;
int init(char dev[]);
void closse(void);
int chset() { return(ch_setmost()); }
int msr() { return(most_msr()); }
int mode(P5083SW);
int mode();
int schema(P5083SW);
int schema();
int var(P5083SW);
int var();
int modes(P5083SW);
int modes();
int synchrS(P5083SW);
int synchrS();
int Umin(P5083SW);
int Umin();
int Usr(int n);
int Usr();
float frq(float ff);
float frq();
int parm(int p);
int parm();
//int set_parm(int p,int n=0,float v=0.0,P5083SW sw=C);
int procent(float v,P5083SW sw);
int error(void);
int error(int);
char* strerr(void);
char* readmsr1(char *s) { return(read_msr1(s)); }
char* readmsr(char *s);
char* measure1(char *s);
};
#endif
|
Код: |
/* Файл P5083L3.C
* Функции урпавления мостом
* Ver. 1.3
*
*
*/
#include<fcntl.h>
#include <io.h>
#include<dos.h>
#include <string.h>
#include"cp5083.h"
#define ReadMsr 29
#define IGNORE 0
#define ABORT 2
#define RETRY 1
#define NSTOP 10000l
#define NP 12
#define NS 9
#define NF 6
#define TIME 5
void interrupt (*vect24)(...);
void interrupt (*vect24_err)(...);
static float f_mosta=1.5;
static int parm_most=0xab,str_len,flag_most=1,
p5083=0,error_m=NO_OPEN_KOP;
static char M_ON[]={'S',0x04,0};
static char M_O[]={'O',0x04,0};
static char data[]={'U',10,
'S','U',040,'C',040,'P',040,'1',040,'D',040,040,10,
'F','R',040,040,'1',',','5','0',040,'S',040,'H',10,
'A','V',040,'1','0',10,
'P','R',040,'1',',','0','0','0','0','0',040,'-','0','9',
040,'F',
'W',0x04,0};
static char *StrErrorMost[]={{"Нет ошибок."},
{"Не открыт канал на устройство КОП."},
{"Ошибка открытия устройства КОП."},
{"Записи в МОСТ."},
{"Чтения с МОСТА."},
{" "},
{"В задании частоты."},
{" "}
};
int handler(int err,int ax,int bp,int si)
{
long int i;
if((ax&0x0100) == 0) {
bdosptr(0x09,"ERROR READ KOP !$",0);
return(ABORT);
}
i=NSTOP;
while( i-- > 0 ) ;
return(RETRY);
}
int write_p5083(char *s,int len)
{
int n_bait;
setvect(0x24,vect24_err);
n_bait=_write(p5083,s,len);
setvect(0x24,vect24);
return(n_bait);
}
int ch_setmost()
{
if( flag_most )
{
if( write_p5083(data,str_len) != str_len)
error_m=ERR_WR_M;
else { flag_most=0; error_m=NO_ERR_M; }
}
return error_m;
}
char * DriverMostP5083::strerr(void)
{
return StrErrorMost[error_m];
}
int most_msr()
{
if(write_p5083(M_ON,2) != 2) error_m=ERR_WR_M;
else error_m=NO_ERR_M;
return error_m;
}
int DriverMostP5083::init(char dev[])
{
int handler(int err,int ax,int bp,int si);
if( (p5083=open(dev,O_RDWR)) > 0)
{
vect24=getvect(0x24);
harderr((int (*)())handler);
vect24_err=getvect(0x24);
setvect(0x24,vect24);
str_len=strlen(data);
ch_setmost();
}
else error_m=ERR_OPEN_KOP;
return(p5083);
}
// Программы оставленные от версии 1.1
//***********************************************
char *read_msr1(char *s)
{
int err,i;
char *p;
*s=0;
switch(error_m)
{
case ERR_OPEN_KOP: break;
case NO_OPEN_KOP: break;
default:
p=s;
for(i=0;i<5;i++)
{ *p=data[18+i];
p++;
}
*p=' '; p++;
*p='к'; p++;
*p='Г'; p++;
*p='ц'; p++;
*p=' '; p++;
if( _write(p5083,M_O,2) == 2 )
{
err=_read(p5083,p,ReadMsr);
if( err != ReadMsr ) error_m=ERR_RD_M;
else {
p=p+ReadMsr;
*p=0;
error_m=NO_ERR_M;
return(s);
}
}
else error_m=ERR_WR_M;
}
return(NULL);
}
char *DriverMostP5083::measure1(char *s)
{
*s=0;
switch(error_m)
{
case ERR_OPEN_KOP: break;
case NO_OPEN_KOP: break;
case ERR_PARM_M: break;
default:
ch_setmost();
if( most_msr() == NO_ERR_M)
return(read_msr1(s));
// else error_m=ERR_WR_M;
}
return(NULL);
}
// ***************************************************
char *DriverMostP5083::readmsr(char *s)
{
int err;
char *p;
*s=0;
switch(error_m)
{
case ERR_OPEN_KOP: break;
case NO_OPEN_KOP: break;
default: p=s;
if( _write(p5083,M_O,2) == 2 )
{
err=_read(p5083,p,ReadMsr);
if( err != ReadMsr ) error_m=ERR_RD_M;
else {
p=p+ReadMsr;
*p=0;
error_m=NO_ERR_M;
return(s);
}
}
else error_m=ERR_WR_M;
}
return(NULL);
}
int DriverMostP5083::error()
{
return(error_m);
}
int DriverMostP5083::error(int err)
{
error_m=err;
return error_m;
}
void DriverMostP5083::closse()
{
close(p5083); error_m=NO_OPEN_KOP;
}
int DriverMostP5083::mode(P5083SW pr)
{
switch(error_m)
{
case ERR_OPEN_KOP: case NO_OPEN_KOP: break;
default:
switch(pr)
{
case L: data[5]='L'; parm_most&=0xfe; break;
case C: data[5]='C'; parm_most|=0x01; break;
}
/* switch(sc)
{
case Tg_s: data[11]='D'; parm_most|=0x08; break;
case Tg_fi: data[11]='Q'; parm_most&=0xf7; break;
}
*/
flag_most=1;
}
return 0;
}
int DriverMostP5083::modes(P5083SW sc)
{
switch(error_m)
{
case ERR_OPEN_KOP: case NO_OPEN_KOP: break;
default:
switch(sc)
{
case Tg_s: data[11]='D'; parm_most|=0x08; break;
case Tg_fi: data[11]='Q'; parm_most&=0xf7; break;
}
flag_most=1;
}
return 0;
}
int DriverMostP5083::mode()
{ return(parm_most&0xfe); }
int DriverMostP5083::modes()
{ return((parm_most&0xf7)>>3); }
int DriverMostP5083::schema(P5083SW sw)
{
switch(error_m)
{
case ERR_OPEN_KOP: case NO_OPEN_KOP: break;
default:
switch(sw)
{
case Parallel: data[7]='P'; parm_most|=0x02; break;
case Serial: data[7]='S'; parm_most&=0xfd; break;
}
flag_most=1;
}
return 0;
}
int schema()
{ return((parm_most&0xfd)>>1); }
int DriverMostP5083::var(P5083SW sw)
{
switch(error_m)
{
case ERR_OPEN_KOP: case NO_OPEN_KOP: break;
default:
switch(sw)
{
case On: data[9]='V'; parm_most|=0x04; break;
case Off: data[9]='1'; parm_most&=0xfb; break;
}
flag_most=1;
}
return 0;
}
int DriverMostP5083::var()
{ return((parm_most&0xfd)>>2); }
int DriverMostP5083::synchrS(P5083SW sw)
{
switch(error_m)
{
case ERR_OPEN_KOP: case NO_OPEN_KOP: break;
default:
switch(sw)
{
case On: data[24]='S'; parm_most|=0x20; break;
case Off: data[24]='A'; parm_most&=0xdf; break;
}
flag_most=1;
}
return 0;
}
int DriverMostP5083::synchrS()
{ return((parm_most&0xdf)>>5); }
int DriverMostP5083::Umin(P5083SW sw)
{
switch(error_m)
{
case ERR_OPEN_KOP: case NO_OPEN_KOP: break;
default:
switch(sw)
{
case On: data[26]='L'; parm_most|=0x40; break;
case Off: data[26]='H'; parm_most&=0xbf; break;
}
flag_most=1;
}
return 0;
}
int DriverMostP5083::Umin()
{ return((parm_most&0xbf)>>6); }
int DriverMostP5083::Usr(int n)
{
char str_n[2];
if( n==1 || n<0 || n > 99 )
{ error_m=ERR_PARM_M; return(error_m); }
sprintf(str_n,"%2d",n);
data[32]=str_n[1];
if( str_n[0] ==' ' ) data[31]='0';
else data[31]=str_n[0];
if(n == 0) parm_most&=0x7f;
else parm_most|=0x80;
flag_most=1;
return 0;
}
int DriverMostP5083::Usr()
{
int ret_n;
char str_n[2];
if((parm_most & 0x80) == 0) return 0;
str_n[1]=data[32];
if( data[31] =='0' ) str_n[0]=' ';
else str_n[0]=data[31];
sscanf(str_n,"%2d", &ret_n);
return ret_n;
}
int DriverMostP5083::procent(float v,P5083SW sw)
{
return 0;
}
int DriverMostP5083::parm(int p)
{ parm_most=p;
return parm_most;
}
int DriverMostP5083::parm()
{ return parm_most; }
/* int set_parm(int p,int n,float v,P5083SW sw)
{
parm_most=p;
if((p&0x01)==0x01) mode_Msr(C);
else mode_Msr(L);
if((p&0x02)==0x02) schema(Parallel);
else schema(Serial);
if((p&0x04)==0x04) mode_Var(On);
else mode_Var(Off);
if((p&0x08)==0x08) mode_Second(Tg_s);
else mode_Second(Tg_fi);
if((p&0x10)==0x10) procent(v,sw);
else procent(v,sw);
if((p&0x20)==0x20) synchrS(On);
else synchrS(Off);
if((p&0x40)==0x40) U_min(On);
else U_min(Off);
if((p&0x80)==0x80) mode_Usr(n);
else mode_Usr(0);
ch_setmost();
return 0;
} */
/* if( write_p5083(data,str_len) != str_len)
error_m=ERR_WR_M;
else error_m=NO_ERR_M;
}
return(error_m);
} */
float DriverMostP5083::frq(float f)
{
float retcod;
int i;
char strf[8];
retcod=0.;
if( f < 0.1 ) { f=0.1; retcod=(-1.); }
if( f > 100.) { f=100.; retcod=(-1.); }
if( f < 1 ) sprintf(strf,"%5.3f",f);
else
if( f < 10) sprintf(strf,"%5.2f",f);
else if( f == 100.0 ) sprintf(strf,"%5.0f",f);
else sprintf(strf,"%5.1f",f);
for(i=0;i<5;i++)
if( strf[i] == '.') data[18+i]=',';
else data[18+i]=strf[i];
f_mosta=f;
flag_most=1;
return(retcod);
}
float DriverMostP5083::frq()
{ return f_mosta; }
//
|
Первая функция которая будет вызываться из этой библиотеки это процедура инициализации драйвера:
Код: |
int DriverMostP5083::init(char dev[])
{
int handler(int err,int ax,int bp,int si);
if( (p5083=open(dev,O_RDWR)) > 0)
{
vect24=getvect(0x24);
harderr((int (*)())handler);
vect24_err=getvect(0x24);
setvect(0x24,vect24);
str_len=strlen(data);
ch_setmost();
}
else error_m=ERR_OPEN_KOP;
return(p5083);
}
|
Как мы отсюда видим обработчиком ошибки задаётся процедура:
Код: | int handler(int err,int ax,int bp,int si)
{
long int i;
if((ax&0x0100) == 0) {
bdosptr(0x09,"ERROR READ KOP !$",0);
return(ABORT);
}
i=NSTOP;
while( i-- > 0 ) ;
return(RETRY);
} |
\\Запомнили прежний адрес обработчика
vect24=getvect(0x24);
\\Задали новую процедуру вызываемую при генерации ошибки устройства
harderr((int (*)())handler);
\\Снова запомнили адрес обработчика теперь указывающего
\\на наш обработчик
vect24_err=getvect(0x24);
\\Восстановили прежний обработчик прерывания.
setvect(0x24,vect24);
Теперь у нас vect24_err указывает на обработчик handler
а vect24 содержит старый адрес для восстановления.
Далее эти вектора используются при записи в устройство:
Код: |
int write_p5083(char *s,int len)
{
int n_bait;
setvect(0x24,vect24_err);
n_bait=_write(p5083,s,len);
setvect(0x24,vect24);
return(n_bait);
}
|
--== ЗАДАЧА ==--
Осуществить перехват ошибки устройства средствами C++Builder.
Функции оперирования с векторами прерываний в C++Builder не поддерживаются. Нужно найти альтернативный способ задать обработчик данной ошибки, не используя функции:
setvect();
getvect();
harderr();
Предусмотреть присутствующую в обработчике проверку:
Код: |
if((ax&0x0100) == 0) {
bdosptr(0x09,"ERROR READ KOP !$",0);
return(ABORT);
}
|
Интуитивно предпологаю, что нужно использовать блок
try
catch
Но возможно придётся также заменить и функции работы с потоками, так как не уверен, что dos функция _write генерирует ошибки с помощью throw.
Заранее большое спасибо всем, кто откликнется. |
|