реклама на сайте
подробности

 
 
> ПК и GPIO-интерфейс
Andrey Pesoshin
сообщение Oct 18 2012, 13:16
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 51
Регистрация: 5-07-10
Пользователь №: 58 297



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

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

Нужен ли в данном случае нестандартный контроллер (покупной, разрабатываемый) или он уже есть в составе ПК (если да, как к нему подключиться)?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
kovigor
сообщение Oct 18 2012, 13:41
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(Andrey Pesoshin @ Oct 18 2012, 16:16) *
Возможно ли использовать стандартный персональный компьютер в качестве GPIO-контроллера? Хочу подключить к нему всего 4 линии, на 2 из них подать высокий логический уровень, и 2 другие в программе опрашивать на наличие сигнала.
Нужен ли в данном случае нестандартный контроллер (покупной, разрабатываемый) или он уже есть в составе ПК (если да, как к нему подключиться)?

Все зависит от скорости. У обычного LPT-порта есть целых пять (если не ошибаюсь) линий, способных работать на ввод. Пример такого решения - всем известный AvReal. А вот статья, одна из нескольких, как минимум:
http://www.pcports.ru/articles/2.php
Еще способ, сравнительно простой - использовать обычную PCI-ную сетевую карточку. У таких карточек есть загрузочное ПЗУ или хотя бы панелька для него, вот к ней и можно подключиться:
http://fpga-faq.narod.ru/
Ну и, наконец, можно сделать простейший адаптер на МК, подключаемый к COM - порту. И к этому адаптеру подключить ваши линии (это, если скорости небольшие, наиболее предпочтительный вариант) ...
Go to the top of the page
 
+Quote Post
Andrey Pesoshin
сообщение Oct 18 2012, 17:41
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 51
Регистрация: 5-07-10
Пользователь №: 58 297



Цитата(kovigor @ Oct 18 2012, 17:41) *
Все зависит от скорости. У обычного 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
Go to the top of the page
 
+Quote Post
_pv
сообщение Oct 18 2012, 18:10
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(Andrey Pesoshin @ Oct 18 2012, 23:41) *
спасибо за ответ! Видимо, действительно, штатной возможности у ПК нет

такая штатная возможность есть у последовательных портов. или переходников 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

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

Go to the top of the page
 
+Quote Post
Andrey Pesoshin
сообщение Oct 19 2012, 08:58
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 51
Регистрация: 5-07-10
Пользователь №: 58 297



Цитата(_pv @ Oct 18 2012, 22:10) *
такая штатная возможность есть у последовательных портов. или переходников 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?
Go to the top of the page
 
+Quote Post
_pv
сообщение Oct 19 2012, 09:59
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(Andrey Pesoshin @ Oct 19 2012, 15:58) *
Про скорости - входной сигнал опрашивается не чаще раза в 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:
CODE
#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:
CODE
#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);
}
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 28th July 2025 - 09:21
Рейтинг@Mail.ru


Страница сгенерированна за 0.01443 секунд с 7
ELECTRONIX ©2004-2016