IPB

Welcome Guest ( Log In | Register )

2 Pages V  < 1 2  
Ответить в данную темуНачать новую тему
> Вввод-вывод в СОМ-порт, переделать досовский ввод в виндовый
Гость_klep_*
post 29.4.2005, 12:51
Post #16





Guests






Я вот вообще в таких случаях делаю универсальный клас, который работает с уже класами устройствами (УСБ, Порты, или в файл).

В таком случае очень просто перенаправить поток в файл и посмотреть результат.
Перейти в начало страницы
 
+Цитировать сообщение
Гость_Kazanova84_*
post 29.4.2005, 13:05
Post #17





Guests






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

Цитата
Какив возможный диапазон этих интервалов, какая нужна точность их определения?


Диапазон порядка... ну точно не знаю. Где-то порядка нескольких сотен измерений в сенунду я думаю (одна-две, думаю не больше). Только вот как точно определить это время? Повторить надо с приемлемой точностью ну хотя бы +- 5%
Перейти в начало страницы
 
+Цитировать сообщение
Гость_Kazanova84_*
post 29.4.2005, 14:46
Post #18





Guests






Еще информация: по ходу вычислений в программе я просек, что временнЫе интервалы нигде не отслеживаются, а вместо этого используется какая-то временнАя константа. То есть предполагается, что на любой машине при любых условиях времена чтения будут одинаковыми. Это достигается должно быть функцией init, которая выполняется всегда с параметром 5957. Отсюда вытекает следующий вопрос: как отследить в ДОСе короткие интервалы и как затем их реализовать при задержке в винде? Функции типа Sleep не катят, так как задержки требуются порядка десятков микросекунд (как в коде чтения)
Перейти в начало страницы
 
+Цитировать сообщение
Гость_klep_*
post 29.4.2005, 15:34
Post #19





Guests






Винда != ОС реального времени.

Тебе придется устанавливать режим реального времени для процесса и самому отсчитывать все интервалы, благо в винде есть GetTickCount (который тоже в мили.сек считает, придется самому микро высчитывать).
Перейти в начало страницы
 
+Цитировать сообщение
Гость_Kazanova84_*
post 2.5.2005, 22:02
Post #20





Guests






так... с временнЫми задержками теоретически разобрался. Думаю проблему можно решить при помощи функций QueryPerformanceFrequency и QueryPerformanceCounter. Сделать приоритет потока считывания below normal (чтоб не тормозить остальное) и считывать Counter пока не пройдет заданный интервал времени.

Но вот еще неувязочка! Вот кусок кода который написал Adil:
Код
dcb.fRtsControl=RTS_CONTROL_HANDSHAKE;
dcb.fDtrControl=DTR_CONTROL_HANDSHAKE;
dcb.fDsrSensitivity=1;//не знаю, надо ли это устанавливать, чтобы ловить DSR?

и еще:
Код
//использование:
//поднять RTS
EscapeCommFunction(port,SETRTS);
//сбросить RTS
EscapeCommFunction(port,CLRRTS);
//поднять DTR
EscapeCommFunction(port,SETDTR);
//сбросить DTR
EscapeCommFunction(port,CLRDTR);


Вроди все понятно, но в MSDN про элементы структуры DCB написано:
Цитата
fDtrControl
Specifies the DTR (data-terminal-ready) flow control. This member can be one of the following values:

DTR_CONTROL_DISABLE
Disables the DTR line when the device is opened and leaves it disabled.

DTR_CONTROL_ENABLE
Enables the DTR line when the device is opened and leaves it on.

DTR_CONTROL_HANDSHAKE
Enables DTR handshaking. If handshaking is enabled, it is an error for the application to adjust the line by using the EscapeCommFunction function.


Меня смутила последнее про DTR_CONTROL_HANDSHAKE. То же самое написано про fRtsControl. То ли я дурак, но мне кажется, что там написано, мол нельзя вызывать EscapeCommFunction если установлен флаг DTR_CONTROL_HANDSHAKE. А как тогда его поднимать????
Перейти в начало страницы
 
+Цитировать сообщение
Гость_Hydra_*
post 3.5.2005, 5:40
Post #21





Guests






Похоже, что DTR_CONTROL_HANDSHAKE переводит систему в режим установления соединенеия. Т.е. одна пашина поднимает DTR и ждет, пока вторая поднимет RTS. Поптом вторая поднимает DTR, а первая RTS.
Соединение установлено, ведущий и ведомый выбраны - передавайте данные.
Перейти в начало страницы
 
+Цитировать сообщение
Гость_Adil_*
post 3.5.2005, 9:12
Post #22





Guests






Цитата(Kazanova84 @ May 2 2005, 10:02 PM)
Меня смутила последнее про DTR_CONTROL_HANDSHAKE. То же самое написано про fRtsControl. То ли я дурак, но мне кажется, что там написано, мол нельзя вызывать EscapeCommFunction если установлен флаг DTR_CONTROL_HANDSHAKE. А как тогда его поднимать????
*
Да, ты прав - приношу свои извинения - когда писал ответ, писал по-памяти sad.gif, конечно, надо просто устанавливать
RTS_CONTROL_ENABLE и DTR_CONTROL_ENABLE. Меня все время с толку сбивает _HANDSHAKE и то, что мы хотим управлять битами вручную

P.S. Исправил свой топик
Перейти в начало страницы
 
+Цитировать сообщение
Гость_Kazanova84_*
post 3.5.2005, 12:57
Post #23





Guests






Adil, остается вопрос, как правильно ловить DSR? Вот предложенный тобой код:
Код
//чтобы ловить DSR надо:
DWORD EvtMask;
BOOL Res=WaitCommEvent(port,&EvtMask,&o);
if(!Res && GetLastError()==ERROR_IO_PENDING)
{
do
{
  DWORD wf=WaitForSingleObject(o.hEvent,1000);
  if(wf!=WAIT_OBJECT_0)
  {
     //тайме-аут или ошибка: здесь можно предпринять какие либо действия,
     //например выйти из цикла
  }
  else
      Res=TRUE;
}while(!Res);
}
if(Res)
{
//DSR отработал
}

Дело в том, что нам нужно мгновенно проверить состояние DSR, и записать очередной бит данных в соответствии с состоянием DSR. Т.е. нам не нужно отслеживать изменение DSR! В девайсе стоИт АЦП, который передает в СОМ оцифрованные данные. Как я смог разобраться (с вашей помощью smile.gif ) после сигнала девайс цифрит текущее значение, а затем в цикле 16 раз передает биты этого значения по DSR (при подаче импульса-строба DTR перед передачей очередного бита).

Вот код утилиты, тестирующей чтение:
Код
// comtest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

/////////////////////////////////

#define DSR_TIMEOUT 5
#define STROBE_TIMEOUT 1


void WaitMicroseconds(__int64);
void BeginWait();
void WaitUntill(__int64 timeout);


__int64 timerFreq;
__int64 timerValue;
__int64 timerOld;

__int64 waitOld;



//////////////////////////////////

int main(int argc, char* argv[])
{
    
    char PortName[] = {"COM1"};
    ////////////////////////////////////////////////////

    //для хранения старых настроек
    DCB  old;
    DWORD    OldEvMask;

    //инициализируем порт
    OVERLAPPED o;
    DCB dcb;


    HANDLE port=CreateFile(
 PortName,
 GENERIC_READ|GENERIC_WRITE,
 0,
 NULL,
 OPEN_EXISTING,
 FILE_FLAG_OVERLAPPED,
 NULL
 );

    if(port == INVALID_HANDLE_VALUE)
    {
 MessageBox(0,"Error","Cant open COM-port",MB_OK);
 //ErrorExit("Open",GetLastError());
 return 0;
    }

    dcb.DCBlength = sizeof(DCB);
    GetCommState(port,&dcb);
    memcpy((void*)&old, (void*)&dcb, sizeof(DCB)); //сохраняем старые настройки, чтоб потом восстановить
    
    //переходим на ручное управление RTS'ом и DTR'ом
    dcb.fRtsControl=RTS_CONTROL_ENABLE;
    dcb.fDtrControl=DTR_CONTROL_ENABLE;
    dcb.fDsrSensitivity=1;  //не знаю, надо ли это устанавливать, чтобы ловить DSR?
    SetCommState(port,&dcb);
    
    //задаем маску сигналов, на которые должен реагировать порт
    //перед этим сохраняем старую маску, чтоб потом восстановить
    GetCommMask(port, &OldEvMask);
    
    //SetCommMask(port, EV_DSR);//будем реагировать на изменение DSR
    
    memset(&o,0,sizeof(o));
    o.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);//подготавливаем эвент
    //игициализация завершена



    if(!QueryPerformanceFrequency((LARGE_INTEGER*)&timerFreq)) {
 printf("Timer not supported!");
 return 0;
    }
    else {
 QueryPerformanceCounter((LARGE_INTEGER*)&timerValue);
 printf("Timer frequency: %I64u\nCurrentValue: %I64u\n", timerFreq, timerValue);
    }

    //goto exit;
    

    printf("\nPress any key to begin scaning...\n");
    getch();
    printf("Scan started! Press any key to stop scanning...\n");

    /////////////
    int   value;
    DWORD tickCount;
    DWORD timeOut;
    DWORD valueCount;
    DWORD EvtMask;

    //int min;
    //int max;
    //min = max = 0;

    ///////////////////////////
    
    tickCount = GetTickCount();
    valueCount = 0;

    BOOL res;


    do {

 BeginWait();
 /////////////////////
 SetCommMask(port, 0);  // сначала не реагируем ни на что

 value = 0;

 WaitMicroseconds(15);
 EscapeCommFunction(port, SETDTR);  // Raise DTR

 WaitMicroseconds(15);
 EscapeCommFunction(port, SETRTS);  // Raise RTS

 WaitMicroseconds(15);
 
 SetCommMask(port, EV_DSR);  // теперь реагируем на DSR

 for(int i = 0; i < 16; i++)
 {
     if(!EscapeCommFunction(port, CLRDTR))
   printf("CLRDTR failed! Step #%d\n", valueCount);
     
     //WaitMicroseconds(STROBE_TIMEOUT);
     if(!EscapeCommFunction(port, SETDTR))
   printf("SETDTR failed! Step #%d\n", valueCount);
     
     value <<= 1;

     // catch DSR
     WaitMicroseconds(DSR_TIMEOUT); // ничего не делаем какое-то время
     res = WaitCommEvent(port, &EvtMask, &o);
     if(!res) {
   
   if(GetLastError() == ERROR_IO_PENDING) {
       // DSR не изменился. Очередной бит = 0
       SetCommMask(port, EV_DSR); // чтобы отменить ожидание DSR

   }
   else {
       // произошла ошибка
       // ....
   }
     }
     else {
   // DSR изменился. Записываем бит = 1
   value += 1;
     }

 } // чтение value закончено

 value &= 0x0fff;
 
 valueCount++;

 ////////////////
 WaitUntill(4950);   // our speed 1value/5000usec

    }
    while(!_kbhit());

    timeOut = GetTickCount() - tickCount;

    printf("Scan stopped!\n\nReaded %d in %d milliseconds (%d values/sec)\n",
 valueCount, timeOut, (valueCount*1000/timeOut));

    getch();
    
    
    ////////////////////

//exit:

    SetCommMask(port, OldEvMask);
    SetCommState(port,&old);


    CloseHandle(port);
    
    return 0;
}

////////////////////////////////////////////////////////////////////////


void WaitMicroseconds(__int64 timeout)
{
    __int64 to;
    QueryPerformanceCounter((LARGE_INTEGER*)&timerOld);

    do {
 QueryPerformanceCounter((LARGE_INTEGER*)&timerValue);
 to = (timerValue - timerOld)*1000000/timerFreq;
 //printf(".");
    }
    while(to < timeout);
    //printf("\n");

}

///////////////////////////////////

void WaitUntill(__int64 timeout)
{
    __int64 to;

    do {
 QueryPerformanceCounter((LARGE_INTEGER*)&timerValue);
 to = (timerValue - waitOld)*1000000/timerFreq;
    }
    while(to < timeout);
}

/////////////////////////

void BeginWait()
{
    QueryPerformanceCounter((LARGE_INTEGER*)&waitOld);
}


Но здесь меня мучают некоторые сомнения...

1) Когда мы включаем SetCommMask(port, EV_DSR), если в этот момент DSR был поднят, а потом опустился. Он же изменился, но его новое значение = 0. А в такой ситуации мой код определит его как 1, ведь так? Как быть? Нельзя ли просто проверить он == 1 или он == 0?

2) Грамотно ли вообще организовано считывание?.. Как сделать лучше?
Перейти в начало страницы
 
+Цитировать сообщение
Гость_Adil_*
post 3.5.2005, 16:37
Post #24





Guests






Если изветсна частота, с которой идет передача данных, то может тогда и не нужно ожидать изменения DSR с WaitCommEvent?:
Код
...
do {
 BeginWait();
 /////////////////////
 //SetCommMask(port, 0);  // сначала не реагируем ни на что
    //все, что связано с SetCommMask - можно убрать

 value = 0;
 WaitMicroseconds(15);
 EscapeCommFunction(port, SETDTR);  // Raise DTR

 WaitMicroseconds(15);
 EscapeCommFunction(port, SETRTS);  // Raise RTS

 WaitMicroseconds(15);
 DWORD ModemStatus;
 for(int i = 0; i < 16; i++,value <<= 1)
 {
   EscapeCommFunction(port, CLRDTR);
   EscapeCommFunction(port, SETDTR);
   WaitMicroseconds(DSR_TIMEOUT); // ничего не делаем какое-то время
   GetModemStatus(port,&ModemStatus);
   if(ModemStatus&MS_DSR_ON)
     value|=1;
} // чтение value закончено
printf("Step #%d: value=%03Xh\n", valueCount++,value&0x0fff)
////////////////
WaitUntill(4950);   // our speed 1value/5000usec
}while(!_kbhit());
...
Перейти в начало страницы
 
+Цитировать сообщение
Гость_Kazanova84_*
post 4.5.2005, 14:14
Post #25





Guests






Adil, точно! Как я раньше не видел этой функции?! Тока точнее она называется GetCommModemStatus. Частота передачи не знаю какая, так что буду пробовать этот код...
Перейти в начало страницы
 
+Цитировать сообщение
Гость_Adil_*
post 4.5.2005, 16:20
Post #26





Guests






[OFFTOP]
Цитата(Kazanova84 @ May 4 2005, 02:14 PM)
Тока точнее она называется GetCommModemStatus
Мда, что-то совсем с памятью плохо стало... Старею, что ли... cry.gif [/OFFTOP]
Так а попробуй осциллографом померить. Хотя тут наверное не частота, а скорее время реакции на строб...
Перейти в начало страницы
 
+Цитировать сообщение
Гость_Kazanova84_*
post 4.5.2005, 22:08
Post #27





Guests






Цитата
... Так а попробуй осциллографом померить...

Не, я думаю это уже лишнее. Я померил в досе, что скорость чтения примерно 12000 значений в минуту (или 200 в секунду). Теперь, скорее всего методом подбора, нужно найти необходимые задержки перед посылом сигналов девайсу (примерно они будут равны 10 мкс - так было написано в комментарии) и все smile.gif

Ну раз уж пошло такое обсуждение, хочу спросить, как вы думаете, зачем нужно такое странное определение структуры:
Код
struct signal
{
   int sig:12;
   int:2;
};


? Она даже не выровнена по байтам. Я такое первый раз вижу. Я сначала подумал, что это для того, чтобы выделять младшие 12 бит от 16 битного значения, но потом засомневался, а не проще было бы потом сделать &=0x0fff ? И зачем там именно 2 бита, а не 4, для дополнения до 16ти? Есть у кого какие предположения?
Перейти в начало страницы
 
+Цитировать сообщение
Гость_Hydra_*
post 5.5.2005, 5:12
Post #28





Guests






АЦП у устройства 14и битное.
Перейти в начало страницы
 
+Цитировать сообщение
Гость_Kazanova84_*
post 5.5.2005, 10:31
Post #29





Guests






Hydra, там вообще то в цикле с АЦП читается 16 бит! Еще раз код:
Код
struct signal
{
    int sig:12;
    int:2;
};

int get(void)
{
    while(Glob==0);
    Glob=0;
    struct signal s;
    int i,k,j;
    s.sig=0;
    for(i=0;i<200;i++);
    
    outportb(B+4,1);  // Поднять DTR (только)
    for(i=0;i<200;i++);       // > 10 mkS
    
    outportb(B+4,3);  // Поднять DTR и RTS
    for(i=0;i<200;i++);       //Задержка для оцифровки
    
    for(i=0;i<16;i++)
       {
  outportb(B+4,2);  // Опустить DTR поднять RTS
  outportb(B+4,3);  // Поднять DTR и RTS
  s.sig<<=1;
  s.sig+=(1&(inportb(B+6)>>5));   // DSR поднят? да=1, нет=0
    }
    return s.sig;
}
Перейти в начало страницы
 
+Цитировать сообщение
Гость_Artem13_*
post 6.6.2005, 10:33
Post #30





Guests






Тут надо видеть девайс....
Перейти в начало страницы
 
+Цитировать сообщение

2 Pages V  < 1 2
Ответить в данную темуНачать новую тему

 



Lo-Fi Version Time is now: 21.8.2018, 23:22