Nicht besonders ordentlich, aber damit bekomme ich zumindest schonmal die Messwertblöcke von einem Kombiinstrument ausgelesen. (wer mit einer ECU testet muss natürlich die Adresse ändern)
Code:
#include <stdio.h>
#include <sys/signal.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#define kw1281_debug_dev
//#define kw1281_debug_dev_all
class kw1281{
private:
int fd;
int counter; /* kw1281 protocol block counter */
public:
int fetchGroup(unsigned char groupID){
#ifdef kw1281_debug_dev
printf("kw1281_fetchGroup: Requesting a Data Group {0x%d}\n", groupID);
#endif
kw1281_request_group(groupID);
usleep(10000);
kw1281_recv_group();
}
int fetchBlock(void){
#ifdef kw1281_debug_dev
printf ("kw1281_fetchBlock: Requesting Block %d\n", counter);
#endif
kw1281_send_ack();
usleep(10000);
kw1281_recv_block();
}
void destroy(void){
close(fd);
}
void kw1281_start(char *serialDevice){
unsigned char c;
struct termios oldtio, newtio;
struct sigaction saio;
fd = open (serialDevice, O_SYNC | O_RDWR | O_NOCTTY);
if (fd < 0) {
printf("kw1281: couldn't open serial device");
}
tcgetattr (fd, &oldtio);
newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR; // ICRNL provokes bogus replys after block 12
newtio.c_oflag = 0;
newtio.c_cc[VMIN] = 1;
newtio.c_cc[VTIME] = 0;
tcflush (fd, TCIFLUSH);
tcsetattr (fd, TCSANOW, &newtio);
#ifdef kw1281_debug_dev_all
printf("kw1281: serial device opened");
#endif
}
/* manually set serial lines */
void _set_bit(int bit)
{
int flags;
ioctl (fd, TIOCMGET, &flags);
if (bit) {
ioctl (fd, TIOCCBRK, 0);
flags &= ~TIOCM_RTS;
} else {
ioctl (fd, TIOCSBRK, 0);
flags |= TIOCM_RTS;
}
ioctl (fd, TIOCMSET, &flags);
}
/* receive one byte and acknowledge it */
unsigned char kw1281_recv_byte_ack()
{
unsigned char c, d;
read (fd, &c, 1);
d = 0xff-c;
usleep (10000);
write (fd, &d, 1);
read (fd, &d, 1);
if (0xff-c != d)
printf ("kw1281_recv_byte_ack: echo error (0x%02x != 0x%02x)\n", 0xff-c, d);
return c;
}
/* send one byte and wait for acknowledgement */
int kw1281_send_byte_ack(unsigned char c)
{
unsigned char d;
int retValue = 1;
usleep (10000);
write (fd, &c, 1);
read (fd, &d, 1);
if (c != d){
printf ("kw1281_send_byte_ack: echo error (0x%02x != 0x%02x)\n", c, d);
retValue = -1;
}
read (fd, &d, 1);
if (0xff-c != d){
retValue = -2;
printf ("kw1281_send_byte_ack: ack error (0x%02x != 0x%02x)\n", 0xff-c, d);
}
return retValue;
}
/* write 7O1 address byte at 5 baud and wait for sync/keyword bytes */
void kw1281_init(int address)
{
int i, p, flags;
unsigned char c;
int out,in;
/* prepare to send (clear dtr and rts) */
ioctl (fd, TIOCMGET, &flags);
flags &= ~(TIOCM_DTR | TIOCM_RTS);
ioctl (fd, TIOCMSET, &flags);
usleep (200000);
_set_bit (0); /* start bit */
usleep (200000); /* 5 baud */
p = 1;
for (i=0; i<7; i++) { /* address bits, lsb first */
int bit = (address >> i) & 0x1;
_set_bit (bit);
p = p ^ bit;
usleep (200000);
}
_set_bit (p); /* odd parity */
usleep (200000);
_set_bit (1); /* stop bit */
usleep (200000);
/* set dtr */
ioctl (fd, TIOCMGET, &flags);
flags |= TIOCM_DTR;
ioctl (fd, TIOCMSET, &flags);
/* read bogus values, if any */
ioctl(fd, FIONREAD, &in);
while (in--) {
read (fd, &c, 1);
#ifdef kw1281_debug_dev_all
printf ("ignore 0x%02x\n", c);
#endif
}
read (fd, &c, 1);
if (c != 0x55)
printf ("kw1281_init: sync error (0x55 != 0x%02x)\n", c);
read (fd, &c, 1);
if (c != 0x01)
printf ("kw1281_init: keyword error (0x01 != 0x%02x)\n", c);
c = kw1281_recv_byte_ack ();
if (c != 0x8a)
printf ("kw1281_init: keyword error (0x8a != 0x%02x)\n", c);
counter = 1;
usleep(10000);
kw1281_recv_block();
fetchBlock(); /* controller ID */
fetchBlock(); /* component # */
fetchBlock(); /* software coding */
fetchBlock(); /* dealer part # */
fetchBlock();
}
/* receive a complete block */
void kw1281_recv_block()
{
if(counter > 256) counter = 1;
int i=0;
unsigned char c, l, t;
char buf[256];
/* block length */
l = kw1281_recv_byte_ack();
l -= 2;
c = kw1281_recv_byte_ack();
if (c != counter) {
printf ("kw1281_recv_block: counter error (%d != %d)\n", counter, c);
printf ("IN OUT\t(block dump)\n");
printf ("0x%02x\n", l);
printf (" 0x%02x\n", 0xff-l);
printf ("0x%02x\n", c);
printf (" 0x%02x\n", 0xff-c);
while (1) {
c = kw1281_recv_byte_ack();
printf ("0x%02x\n", c);
printf (" 0x%02x\n", 0xff-c);
} }
t = kw1281_recv_byte_ack();
#ifdef kw1281_debug_dev
switch (t) {
case 0xf6:
printf ("kw1281_recv_block: got ASCII block %d\n", counter);
break;
#ifdef kw1281_debug_dev_all
case 0x09:
printf ("kw1281_recv_block: got ACK block %d\n", counter);
break;
default:
printf ("kw1281_recv_block: block title: 0x%02x (block %d)\n", t, counter);
#endif
}
#endif
while (--l) {
c = kw1281_recv_byte_ack();
buf[i++] = c;
#ifdef kw1281_debug_dev
printf ("0x%02x ", c);
#endif
}
buf[i] = 0;
#ifdef kw1281_debug_dev
if (t == 0xf6) printf ("= \"%s\"\n", buf);
else printf ("\n");
#endif
/* read block end */
read (fd, &c, 1);
if (c != 0x03) printf ("kw1281_recv_block: block end error (0x03 != 0x%02x)\n", c);
counter++;
}
/* send an ACK block */
void kw1281_send_ack() {
unsigned char c;
/* block length */
kw1281_send_byte_ack (0x03);
kw1281_send_byte_ack (counter++);
/* ack command */
kw1281_send_byte_ack (0x09);
/* block end */
c = 0x03;
usleep (10000);
write (fd, &c, 1);
read (fd, &c, 1);
if (c != 0x03) printf ("echo error (0x03 != 0x%02x)\n", c);
}
/* request Data Group */
void kw1281_request_group(unsigned char groupID)
{
unsigned char c;
/* send block length */
kw1281_send_byte_ack(0x04);
/* send counter */
kw1281_send_byte_ack(counter);
/* send block title command */
kw1281_send_byte_ack(0x29);
/* send group number */
kw1281_send_byte_ack(groupID);
/* block end */
c = 0x03;
usleep(10000);
write(fd, &c, 1);
read (fd, &c, 1);
if (c != 0x03)
printf("kw1281_request_group: echo error (0x03 != 0x%d)\n" ,c);
}
// Receives one Data Group
void kw1281_recv_group()
{
int i=0;
unsigned char c, l, t;
unsigned char buf[256];
/* block length */
l = kw1281_recv_byte_ack();
l -= 3;
c = kw1281_recv_byte_ack();
t = kw1281_recv_byte_ack();
#ifdef kw1281_debug_dev_all
switch (t){
case 0xe7:
printf("recv_group: got group block\n");
break;
case 0x09:
printf("recv_group: got ACK block\n");
break;
default:
printf("recv_group: block title: 0x%d (l: %d c: %d)\n",t, l, c);
break;
}
#endif
for (int z = l; z > 0; z--){
c = kw1281_recv_byte_ack();
buf[i++] = c;
if (t == 0xe7){
printf("(%3d) 0x%02x ", c, c);
if(i%3 == 0) {
buf[i] = 0;
#ifdef kw1281_debug_dev
if (t == 0xe7) printf ("=\"%s\"", buf);
#endif
printf("\n");
i=0;
}
}
}
#ifdef kw1281_debug_dev
if (t == 0xe7) printf("\n");
#endif
/* read block end */
read (fd, &c, 1);
if (c != 0x03) printf("recv_group: block end error (0x03 != 0x%c\n", c);
#ifdef kw1281_debug_dev_all
else printf("recv_group: -- group block end reached --\n");
#endif
}
};
int main(void) {
kw1281 diags;
diags.kw1281_start((char *) "/dev/ttyUSB0");
int groupCounter = 0;
diags.kw1281_init (0x17); /* send 5baud address, read sync byte + key word, ECU: 0x01, CLUSTER: 0x17 */
printf ("main loop\n");
while (1) {
if(groupCounter > 255) groupCounter = 0;
diags.fetchBlock();
diags.fetchGroup((char) groupCounter++);
}
diags.destroy();
}