PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Datenstrom aus I2C-Bus mit PC nach I2C-Bus-Adapter auslesen



E-Donni
16.06.2006, 19:49
Hallo!

Über einen PC nach I2C-Bus-Adapter möchte ich den Datenstrom des I2C-Busses protokollieren, ohne jedoch Einfluss auf die Daten zu nehmen.
Der I2C-Bus erhält die Datenbytes aus einer anderen Quelle, deren Inhalt auf diese Weise aufgezeichnet werden soll.
Das Programm soll in Visual Basic erstellt werden.

Hat jemand Erfahrungen, geht dies überhaupt?
Über Beispielcode würde ich mich sehr freuen.

Vielen Dank!

E-Donni

linux_80
16.06.2006, 21:22
Hallo,

es gibt doch hier den I2C-Adapter:
http://www.shop.robotikhardware.de/shop/catalog/product_info.php?cPath=73&products_id=68
und da ist auch ein VB beispiel dabei,
hab da aber selber noch nix damit gemacht.

E-Donni
18.06.2006, 11:09
Hallo,

es gibt doch hier den I2C-Adapter:
http://www.shop.robotikhardware.de/shop/catalog/product_info.php?cPath=73&products_id=68
und da ist auch ein VB beispiel dabei,
hab da aber selber noch nix damit gemacht.

Hallo,

genau diesen Adapter möchte ich für die Überwachung des I2C-Datenstromes nutzen. Jedoch hat dieser Adapter beim Versuch ohne selbst Daten zu senden, sondern nur zu empfangen, trotzdem Daten abgesendet.

Vielleicht kann mir jemand helfen.

Gruß
E-Donni

linux_80
18.06.2006, 12:10
Das kleine Beispiel, mit den Funktionen zum senden oder empfangen, ist so ausgelegt, das der PC der Master ist, das müsste man umbauen, sodass der PC auf den Takt lauscht, und nicht selber generiert.
Dann könnte man unanghängig von der Slaveadresse alles mitloggen.

E-Donni
18.06.2006, 13:04
Das kleine Beispiel, mit den Funktionen zum senden oder empfangen, ist so ausgelegt, das der PC der Master ist, das müsste man umbauen, sodass der PC auf den Takt lauscht, und nicht selber generiert.
Dann könnte man unanghängig von der Slaveadresse alles mitloggen.

Hallo Linux_80!

Vielen Dank für Deinen Hinweis.
Leider habe ich Schwierigkeiten, Deinen Tip umzusetzen. Ein paar Codeschnipsel würden mir sehr helfen.

Vielen Dank!
Gruß
E-Donni

PicNick
18.06.2006, 16:42
Der PC/ I2C Adapter ist für flottere Bus-geschwindigkeiten nicht optimal, wenn er als Slave (oder Sniffer) arbeitet.
Zumindest, wenn man mit der üblichen Schnittstelle arbeitet.
Da müßte man weiter runter ins System, denk' ich.

(Ich hab mit damals mit VC++ gespielt, vielleicht find' ich noch Spuren davon, wenn es hülfe)

E-Donni
18.06.2006, 17:24
Der PC/ I2C Adapter ist für flottere Bus-geschwindigkeiten nicht optimal, wenn er als Slave (oder Sniffer) arbeitet.
Zumindest, wenn man mit der üblichen Schnittstelle arbeitet.
Da müßte man weiter runter ins System, denk' ich.

(Ich hab mit damals mit VC++ gespielt, vielleicht find' ich noch Spuren davon, wenn es hülfe)

Hall PicNick,

wenn Du Spuren Deines Codes noch auftreiben könntest, wäre das sehr hilfreich!
Schon mal besten Dank!

Viele Grüße
E-Donni

shaun
18.06.2006, 19:25
Wie schnell hast Du es denn geschafft? Ich habe seinerzeit auch mal an sowas gearbeitet, damals waren 200MHz-CPUs aktuell, unter DOS mit C-Code und inline-Assembler bin ich nie wirklich bis an die 400kHz für schnelles I2C gekommen, zumindest nicht, wenn auch noch auf Plausibilität des Timings geprüft wurde. Auf irgendeiner Seite, die irgendwas mit warmen Katzen oder so im Namen hat (oder war es Katzenmilch?) wird eine Sniffer-Lösung vorgestellt, die unter Linux läuft und sich volle Priorität krallt, aber wohl auch nicht alle Geschwindigkeiten packt. Daher liegt hier seit einiger Zeit ein CPLD herum, auf dem ich sowas mal implementieren wollte, aber so dringend war es dann doch nie. Mein DOS-PC-basierter Logic Analyzer sollte sich dazu auch gebrauchen lassen (vielleicht einen der mitgelieferten Disassembler umschreiben oder sowas), aber wie gesagt: keine Zeit, wenig Bedarf.

PicNick
19.06.2006, 09:41
Ich stell mal den Part mit Senden da rein. Zur Erläuterung: das Open & close ist einfach abgeschrieben (Comtools), ist ja für I2C auch ziemlich egal.
Alle Calls haben also als Argument daher immer die Nummer des Handles. Die Windows-Port-Funktionen werdet ihr ja eh kennen.



#define MAX_COM_PORTS 32

#define SCL_ON MS_CTS_ON
#define SDA_ON MS_DSR_ON

static HANDLE hComFile[MAX_COM_PORTS];
static BOOL bIsOpen [MAX_COM_PORTS];
static DCB sDcb [MAX_COM_PORTS];
static int iMsk [MAX_COM_PORTS];

//************************************************** ***************************
//*
//* ComOpen
//*
//************************************************** ***************************
// Öffnet eine serielle Verbindung
// Nr : Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
// Baud : Ist die Bautrate
// Parity : 0 = kein Parity Bit
// 1 = gerade
// 2 = ungerade
// 3 = immer 0
// 4 = immer 1
// Stopbits : 0 = Ein Stopbit
// 1 = Ein/einhalb Stopbits
// 2 = Zwei Stopbits
// Bits : 0 = 7 Datenbits
// 1 = 8 Datenbits
// 7 = 7 Datenbits
// 8 = 8 Datenbits
// Ergibt 1 wenn eine Schnittstelle geöffnet wurde
int CRtport::CRtPortOpen (unsigned Nr,int Baud,int Parity,int Stopbits,int Databits)
{
static const int iPMode[] = {NOPARITY, EVENPARITY, ODDPARITY, SPACEPARITY, MARKPARITY};
static const int iSMode[] = {ONESTOPBIT, ONE5STOPBITS, TWOSTOPBITS};
char cName[]="\\\\.\\COM1";
HANDLE hFile;
COMMTIMEOUTS sTo;

if (Nr >= MAX_COM_PORTS) return 0;
if (bIsOpen[Nr]) return 0;
cName[7]='1' + Nr;
hFile = CreateFile (cName, GENERIC_READ|GENERIC_WRITE,0,0,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if (hFile==INVALID_HANDLE_VALUE)
{
hFile=0;
return 0;
}
if (Databits == 7)
Databits = 0;
memset(&sDcb[Nr],0,sizeof(sDcb[Nr]));
sDcb[Nr].DCBlength = sizeof(sDcb[Nr]);
sDcb[Nr].BaudRate = Baud;
sDcb[Nr].fParity = (Parity!=0)? TRUE:FALSE;
sDcb[Nr].fBinary = TRUE;
sDcb[Nr].Parity = iPMode[Parity];
sDcb[Nr].StopBits = ONESTOPBIT;
sDcb[Nr].fOutxCtsFlow = FALSE;
sDcb[Nr].fOutxDsrFlow = FALSE;
sDcb[Nr].fDtrControl = DTR_CONTROL_ENABLE;
sDcb[Nr].fRtsControl = RTS_CONTROL_ENABLE;
sDcb[Nr].fDsrSensitivity= FALSE;
sDcb[Nr].fAbortOnError = FALSE;
sDcb[Nr].ByteSize = (Databits)? 8:7;
if (!SetCommState(hFile,&sDcb[Nr]))
{
CloseHandle(hFile);
return 0;
}
sTo.ReadIntervalTimeout = MAXDWORD; // 0 ms Read-Timeout
sTo.ReadTotalTimeoutMultiplier = 0;
sTo.ReadTotalTimeoutConstant = 0;
sTo.WriteTotalTimeoutMultiplier= 1; // 1*2 ms Write Timeout
sTo.WriteTotalTimeoutConstant = 2;
if (!SetCommTimeouts((HANDLE)hFile,&sTo))
{
CloseHandle(hFile);
return 0;
}
hComFile[Nr] = hFile;
bIsOpen [Nr] = TRUE;
return 1;
}

//************************************************** ***************************
//*
//* ComClose
//*
//************************************************** ***************************
int CRtport::CRtPortClose (unsigned Nr)
{
if (Nr >= MAX_COM_PORTS) return 0;
if (!bIsOpen[Nr]) return 0;
CloseHandle(hComFile[Nr]);
hComFile[Nr]=0;
bIsOpen [Nr]=FALSE;
return 1;
}
//************************************************** ***************************
int CRtport::CRtPortI2CStop (unsigned Nr)
{
if (CRtPortCheckNr(Nr)) return(CRtPortStopNr(Nr));
else return(0);
}
//************************************************** ***************************
//*
//* Send Bytes
//*
//************************************************** ***************************
int CRtport::CRtPortCheckNr (unsigned Nr)
{
if (Nr >= MAX_COM_PORTS) return 0;
if (!bIsOpen[Nr]) return 0;
GetCommState(hComFile[Nr],&sDcb[Nr]);
return(1);
}
//************************************************** ***************************
int CRtport::CRtPortGetLine (unsigned Nr)
{
int iModem = 0;
if (!CRtPortCheckNr(Nr)) return 0;
if (!GetCommModemStatus(hComFile[Nr], (unsigned long*)&iModem))
return 0;
return(iModem);
}
//************************************************** ***************************
//*
//* Set DRS CTS
//*
//************************************************** ***************************
int CRtport::CRtPortSCLNr (unsigned Nr, int Val)
{
if (Val) sDcb[Nr].fRtsControl = RTS_CONTROL_ENABLE;
else sDcb[Nr].fRtsControl = RTS_CONTROL_DISABLE;
return (SetCommState(hComFile[Nr],&sDcb[Nr]));
}
//************************************************** ***************************
int CRtport::CRtPortSDANr (unsigned Nr, int Val)
{
if (Val) sDcb[Nr].fDtrControl = DTR_CONTROL_ENABLE;
else sDcb[Nr].fDtrControl = DTR_CONTROL_DISABLE;
return (SetCommState(hComFile[Nr],&sDcb[Nr]));
}
//************************************************** ***************************
static void _delay(void)
{
int iX;
for (iX = 0; iX < 255;iX++)
{
}
}
//************************************************** ***************************
int CRtport::CRtPortStopNr (unsigned Nr)
{
CRtPortSDANr(Nr, 0);
_delay();
CRtPortSCLNr(Nr, 1);
_delay();
CRtPortSDANr(Nr, 1);
_delay();
return (1);
}
//************************************************** ***************************
int CRtport::CRtPortStartNr (unsigned Nr)
{
CRtPortSDANr(Nr, 0);
_delay();
CRtPortSCLNr(Nr, 0);
_delay();
return (1);
}
//************************************************** ***************************
int CRtport::CRtPortTickNr (unsigned Nr)
{
int iNew;
int iAck;
CRtPortSCLNr (Nr, 1);
do { GetCommModemStatus(hComFile[Nr], (unsigned long*)&iNew);
} while (!(iNew & SCL_ON));
if (iNew & SDA_ON) iAck = 1;
else iAck = 0;
_delay();
CRtPortSCLNr (Nr, 0);
_delay();
return(iAck);
}
//************************************************** ***************************
int CRtport::CRtPortI2CSendByte (unsigned Nr, int Val)
{
int iCnt;
int iByte = Val;
for (iCnt = 0; iCnt < 8; iCnt++)
{
if (iByte & 0x80) CRtPortSDANr(Nr, 1);
else CRtPortSDANr(Nr, 0);
_delay();
CRtPortTickNr (Nr);
iByte <<= 1;
}
CRtPortSDANr(Nr, 1);
_delay();
return(CRtPortTickNr (Nr));
}
//************************************************** ***************************
int CRtport::CRtPortI2CStart (unsigned Nr)
{
int iNew = 0;
if (!CRtPortCheckNr(Nr)) return 0;
CRtPortSDANr(Nr, 1);
CRtPortSCLNr(Nr, 1);
do { GetCommModemStatus(hComFile[Nr], (unsigned long*)&iNew);
} while (!(iNew & SCL_ON) || !(iNew & SDA_ON));
return(CRtPortStartNr(Nr));
}

Das Senden hat im Prinzip ja geklappt.

Ich stell' dann noch die Versuche des "sniffens" rein, zur allgemeinen Erheiterung. ICh muß mir das aber nochmal durchlesen, damit ich mich wenigsten selbst auskenne, was ich da herumgewurstelt habe.