Перейти к содержанию
    

ПК и GPIO-интерфейс

Доброго времени суток!

 

Возможно ли использовать стандартный персональный компьютер в качестве GPIO-контроллера? Хочу подключить к нему всего 4 линии, на 2 из них подать высокий логический уровень, и 2 другие в программе опрашивать на наличие сигнала.

 

Нужен ли в данном случае нестандартный контроллер (покупной, разрабатываемый) или он уже есть в составе ПК (если да, как к нему подключиться)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возможно ли использовать стандартный персональный компьютер в качестве GPIO-контроллера? Хочу подключить к нему всего 4 линии, на 2 из них подать высокий логический уровень, и 2 другие в программе опрашивать на наличие сигнала.

Нужен ли в данном случае нестандартный контроллер (покупной, разрабатываемый) или он уже есть в составе ПК (если да, как к нему подключиться)?

Все зависит от скорости. У обычного LPT-порта есть целых пять (если не ошибаюсь) линий, способных работать на ввод. Пример такого решения - всем известный AvReal. А вот статья, одна из нескольких, как минимум:

http://www.pcports.ru/articles/2.php

Еще способ, сравнительно простой - использовать обычную PCI-ную сетевую карточку. У таких карточек есть загрузочное ПЗУ или хотя бы панелька для него, вот к ней и можно подключиться:

http://fpga-faq.narod.ru/

Ну и, наконец, можно сделать простейший адаптер на МК, подключаемый к COM - порту. И к этому адаптеру подключить ваши линии (это, если скорости небольшие, наиболее предпочтительный вариант) ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все зависит от скорости. У обычного LPT-порта есть целых пять (если не ошибаюсь) линий, способных работать на ввод. Пример такого решения - всем известный AvReal. А вот статья, одна из нескольких, как минимум:

http://www.pcports.ru/articles/2.php

Еще способ, сравнительно простой - использовать обычную PCI-ную сетевую карточку. У таких карточек есть загрузочное ПЗУ или хотя бы панелька для него, вот к ней и можно подключиться:

http://fpga-faq.narod.ru/

Ну и, наконец, можно сделать простейший адаптер на МК, подключаемый к COM - порту. И к этому адаптеру подключить ваши линии (это, если скорости небольшие, наиболее предпочтительный вариант) ...

спасибо за ответ! Видимо, действительно, штатной возможности у ПК нет (на electronics.stackexchange.com ответили то же самое). Наверно остановлюсь на МК или покупном чем-нибудь вроде http://www.mccdaq.com/pci-data-acquisition...O24-Series.aspx

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

спасибо за ответ! Видимо, действительно, штатной возможности у ПК нет

такая штатная возможность есть у последовательных портов. или переходников USB -> serial, если на плате нет.

там помимо RX,TX есть на выход две линии RTS и DTR, правда с уровнями +-12В. и 4 линии на вход CTS, DSR, DCD и RI, которые обычно от 3-5 вольтовых TTL лог уровней тоже срабатывают. порог на уровне около +1.4В

EIA-232 Input Threshold Low 1.2 V

EIA-232 Input Threshold High 1.6 V

 

скорости-то какие нужны?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

такая штатная возможность есть у последовательных портов. или переходников USB -> serial, если на плате нет.

C USB надежность никудышняя выйдет. Хотя, смотря, для чего это надо. Можно (и лучше) такое сделать с настоящим COM - портом, только вот нужно ли ? Не проще ли будет сделать простейший адаптер на МК с RS232C и подключить его к COM-порту не через левое колено, а как полагается ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

C USB надежность никудышняя выйдет. Хотя, смотря, для чего это надо. Можно (и лучше) такое сделать с настоящим COM - портом, только вот нужно ли ? Не проще ли будет сделать простейший адаптер на МК с RS232C и подключить его к COM-порту не через левое колено, а как полагается ?

насчёт надёжности, не знаю, особых проблем при использовании переходниками USB->COM вроде не возникало, единственное что было это кривые драйвера для XP64, когда незакрытый порт периодически вызывал синий экран при закрытии программы. да еще нежелание работать вместе нескольких одинаковых тексасовских демо плат, где usb->com тексасовские же, не могли нормально номера портов поделить между собой, и то только на ноутбуке, то есть работало оно почему-то при включении в определённой последовательности и только в определённые порты, причина опять же в кривых драйверах.

ну и еще со скоростью переключения контрольно-статусных io порта через usb переходник тоже беда.

 

но если нужна только пара IO без каких-либо жестких требований по времени, то зачем плодить лишние сущности в виде МК.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

но если нужна только пара IO без каких-либо жестких требований по времени, то зачем плодить лишние сущности в виде МК.

Уж лучше в виде MK, подключаемого к настоящему COM - порту, чем в виде USB-переходника ...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

такая штатная возможность есть у последовательных портов. или переходников USB -> serial, если на плате нет.

там помимо RX,TX есть на выход две линии RTS и DTR, правда с уровнями +-12В. и 4 линии на вход CTS, DSR, DCD и RI, которые обычно от 3-5 вольтовых TTL лог уровней тоже срабатывают. порог на уровне около +1.4В

EIA-232 Input Threshold Low 1.2 V

EIA-232 Input Threshold High 1.6 V

 

скорости-то какие нужны?

Про скорости - входной сигнал опрашивается не чаще раза в 1 мс (f <= 1000 Гц), при этом первый фронт на одной из линий хотелось бы поймать максимально быстро.

 

А разве можно управлять линиями последовательного порта ПК на манер GPIO (а как?)? Это что-то вроде bitbang mode у FT232RL?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Про скорости - входной сигнал опрашивается не чаще раза в 1 мс (f <= 1000 Гц), при этом первый фронт на одной из линий хотелось бы поймать максимально быстро.

 

А разве можно управлять линиями последовательного порта ПК на манер GPIO (а как?)? Это что-то вроде bitbang mode у FT232RL?

 

управлять можно. только вот с 1 мс может не получиться.

с УСБ переходником особенно. там циклы на шине вроде как не сильно чаше идут.

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

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

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

 

для windows:

#include "ComPort.h"
void main(){
  ComPort port("COM1", 9600);
  port.Rts(1);        //rts -> 1;
  port.Dtr(0);        //dtr -> 0;
  if (port.Cts()){};
}

 

 

 

ComPort.h:

#ifndef __COMPORT_H_
#define __COMPORT_H_

#include <windows.h>

class ComPort{
private:
 HANDLE hCom;
 int opened;
 char * luaBuff;
 int lastReadNum;
public:
 ~ComPort();
 ComPort();
 ComPort(const char * comPortStr,int speed, int byteSize = 8, int parity = 0, int stopBit = 0);
 int Init(const char * comPortStr,int speed, int byteSize = 8, int parity = 0, int stopBit = 0);
 int SetBaudRate(int speed);
 void Close ();
 int Read(char * c,int num);
 const char * Read(int num = 1024);
 int LastReadNum();
 int Status();
 int Writef(char * str, ...);
 int Write(char *c, int num);
 int Write(char *c);
 int Write(char c);
 int Rts(int level);
 int Dtr(int level);
 int Cts();
 int Dsr();
 int Ri();
 int Dcd();
 void ClearTxBuff();
 void ClearRxBuff();
 int RxBuffNum();
};

#endif

 

ComPort.cpp:

#include "comPort.h"
#include <stdarg.h>
#include <stdio.h>

void ComPort::ClearTxBuff(){
 PurgeComm(hCom,PURGE_TXCLEAR);
}

void ComPort::ClearRxBuff(){
 PurgeComm(hCom,PURGE_RXCLEAR);
}

int ComPort::SetBaudRate(int speed){
 DCB dcb;
 GetCommState( hCom, &dcb );
 dcb.BaudRate = speed ;
 if ( !SetCommState( hCom, &dcb ) ){
//    CloseHandle(hCom);
   return 1;  //SetCommState error
 }
 return 0;
}

int ComPort::Status(){
 unsigned int stat;
 GetCommModemStatus(hCom, (LPDWORD)&stat);
 return stat;
}

int ComPort::Cts(){
 return Status() & MS_CTS_ON ? 1 : 0;
}

int ComPort::Dsr(){
 return Status() & MS_DSR_ON ? 1 : 0;
}

int ComPort::Ri(){
 return Status() & MS_RING_ON ? 1 : 0;
}

int ComPort::Dcd(){
 return Status() & MS_RLSD_ON ? 1 : 0;
}


int ComPort::Rts(int level){
 DCB dcb;
 GetCommState( hCom, &dcb );
 dcb.fRtsControl = level ? RTS_CONTROL_ENABLE : RTS_CONTROL_DISABLE;
 if ( !SetCommState( hCom, &dcb ) ){
//    CloseHandle(hCom);
   return 1;  //SetCommState error
 }
return 0;
}

int ComPort::Dtr(int level){
 DCB dcb;
 GetCommState( hCom, &dcb );
 dcb.fDtrControl = level ? DTR_CONTROL_ENABLE : DTR_CONTROL_DISABLE;
 if ( !SetCommState( hCom, &dcb ) ){
//    CloseHandle(hCom);
   return 1;  //SetCommState error
 }
 return 0;
}

ComPort::~ComPort(){
 Close();
 delete[] luaBuff;
}

ComPort::ComPort(){
 lastReadNum = 0;
 opened = 0;
 luaBuff = new char[2]; luaBuff[0]=0; luaBuff[1]=0;
}

ComPort::ComPort(const char * comPortStr,int speed, int byteSize, int parity, int stopBit){
 lastReadNum = 0;
 opened = 0;
 luaBuff = new char[2]; luaBuff[0]=0; luaBuff[1]=0;
 Init(comPortStr,speed,byteSize,parity,stopBit);
}

/* Initialize Communication port */
int ComPort::Init(const char * comPortStr,int speed, int byteSize, int parity, int stopBit){
 DCB dcb;

 COMMTIMEOUTS  CommTimeOuts ;
 if ( ( hCom = CreateFile (comPortStr, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ) )
              == INVALID_HANDLE_VALUE   ) {
    return 1; // error
 }
 CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
 CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
 CommTimeOuts.ReadTotalTimeoutConstant = 0;
 CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
 CommTimeOuts.WriteTotalTimeoutConstant = 0;

 if ( !SetCommTimeouts( hCom, &CommTimeOuts )){
   CloseHandle(hCom);
   return 2; // SetCommTimeouts error
 }

 dcb.DCBlength = sizeof ( DCB ) ;
 dcb.BaudRate = speed ;
 dcb.fBinary = TRUE ;
 dcb.fParity = 0;
 dcb.fOutxCtsFlow = 0;         // CTS output flow control
 dcb.fOutxDsrFlow = 0;         // DSR output flow control
 dcb.fDtrControl =  0;//DTR_CONTROL_ENABLE;         // DTR flow control type

 dcb.fDsrSensitivity = 0;      // DSR sensitivity
 dcb.fTXContinueOnXoff = 0;    // XOFF continues Tx
 dcb.fOutX = 0;                // XON/XOFF output flow control
 dcb.fInX = 0;                 // XON/XOFF input flow control

 dcb.fErrorChar = 0;           // enable error replacement
 dcb.fNull = 0;                // enable null stripping
 dcb.fRtsControl = 0;//RTS_CONTROL_ENABLE;          // RTS flow control

 dcb.fAbortOnError = 0;        // abort reads/writes on error
 dcb.XonLim = 0;            // transmit XON threshold
 dcb.XoffLim = 0;            // transmit XOFF threshold
 dcb.ByteSize = byteSize;      // number of bits/byte, 4-8
 dcb.Parity = parity;          // 0-4=no,odd,even,mark,space
 dcb.StopBits = stopBit;       // 0,1,2 = 1, 1.5, 2
 dcb.XonChar = 0;             // Tx and Rx XON character
 dcb.XoffChar = 0;            // Tx and Rx XOFF character
 dcb.ErrorChar = 0;            // error replacement character
 dcb.EofChar = 0;              // end of input character
 dcb.EvtChar = 0;              // received event character
 if ( !SetCommState( hCom, &dcb ) ){
   CloseHandle(hCom);
   return 3;  //SetCommState error
 }
 opened = 1;
 return(0);
}

/* Close Communication port   */
void ComPort::Close (){
 if (opened!=1) return;
 opened = 0;
 CloseHandle( hCom );
}

int ComPort::RxBuffNum(){
 COMSTAT stat;
 unsigned long err;
 ClearCommError(hCom, &err, &stat);
 return stat.cbInQue;
}

int ComPort::Read(char * c,int num){
 DWORD length = 0;
 if( !ReadFile(hCom, c, num, &length, NULL) ) return 0;
 return length;
}

const char * ComPort::Read(int num){
 delete luaBuff;
 luaBuff = new char[num];
 memset(luaBuff, 0, num);
 lastReadNum = Read(luaBuff, num);
 return luaBuff;
}

int ComPort::LastReadNum(){
 return lastReadNum;
}

/*
 Send a character
*/

int ComPort::Write(char *c, int num){
 DWORD length = 0;
 WriteFile(hCom, c, num, &length, NULL);
 return length;
}

int ComPort::Write(char c){
 DWORD length;
 return WriteFile(hCom, &c, 1, &length, NULL);
}

int ComPort::Write(char * c){
 DWORD length;
 int num = 0;
 while (c[num]) num += 1;
 return WriteFile(hCom, c, num, &length, NULL);
}

int ComPort::Writef(char * str, ...){
 char tmpStr[1024];
 va_list args;
 va_start (args, str);
 vsprintf_s (tmpStr, 1024, str, args);
 va_end (args);
 return Write(tmpStr);
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Про скорости - входной сигнал опрашивается не чаще раза в 1 мс (f <= 1000 Гц), при этом первый фронт на одной из линий хотелось бы поймать максимально быстро.

А требование управлять объектом непосредственно от PC чем-то реально обусловлено ? Или только тем, что вы не владеете программированием для МК ? Почему бы не управлять объектом именно от МК, в реальном времени, а уже задания (или уставки) для МК формировать и передавать с PC, не cвязывая себя жесткими временными ограничениями ? Можете рассказать о задаче более подробно ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Доброго времени суток!

 

Возможно ли использовать стандартный персональный компьютер в качестве GPIO-контроллера? Хочу подключить к нему всего 4 линии, на 2 из них подать высокий логический уровень, и 2 другие в программе опрашивать на наличие сигнала.

 

Нужен ли в данном случае нестандартный контроллер (покупной, разрабатываемый) или он уже есть в составе ПК (если да, как к нему подключиться)?

DLP2232 на FTDI2232. Вот только USB - это для несерьезных вещей...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

_pv

спасибо за действительно интересный подход

 

kovigor

необходимости нет, да и об управлении объектом речь не идет. Внешний объект - два концевых выключателя, которые в процессе эксперимента то включают, то выключают. Интерфейс на ПК - 2 линии, чтобы их "входы" запитать, 2 линии, чтобы посмотреть, есть ли сигналы с "выходов", вся остальная логика - графика, логика эксперимента на ПК. Если интересно, могу в личку скинуть о чем идет речь :-)

 

Мне кажется, что ответ на свой вопрос я уже более чем получил, спасибо всем :-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если интересно, могу в личку скинуть о чем идет речь :-)

Мне кажется, что ответ на свой вопрос я уже более чем получил, спасибо всем :-)

Скиньте. Интересно. И еще вот что интересно: на чем вы остановились ?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...