gpt4 book ai didi

c - 尝试将 AT 命令写入 USB 转 OBDii 电缆,使用 FT232R 读取 ECU 数据 (ISO 9141-2)

转载 作者:行者123 更新时间:2023-11-30 14:50:02 25 4
gpt4 key购买 nike

我正在尝试使用 ISO 9141-2 协议(protocol)从 ECU 读取数据。我使用的电缆是OBD2转USB,使用FT232R芯片。我正在运行的程序是用 C 编写的。

当我向串行端口(ttyUSB0)写入命令时,它写入得很好,但是当它读回接收到的数据时,它只返回相同的数据。我不确定它为什么要这样做,而不是从 ECU 返回数据。

任何帮助都很棒,谢谢。

示例代码 - 尝试设置波特率等,但也没有成功。

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
char *port = "/dev/ttyUSB0";
char receivedData[100];

int n, fd;

fd = open(port, O_RDWR | O_NOCTTY);

if(fd > 0){
n = write(fd, "AT I\r\n", 10);
read(fd, receivedData, 10);
printf("%s\n", receivedData);

close(fd);
}
else{
printf("failed to open device\n");
}

return 0;
}

最佳答案

尽管这不是问题的直接答案,但这么多代码不适合评论部分。

我使用这些函数来初始化串行线:

#include <stdio.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>


struct baud_map {
int baud;
speed_t speed;
};

struct baud_map baudmap[] = {
{ 50 , B50 },
{ 75 , B75 },
{ 110 , B110 },
{ 134 , B134 },
{ 150 , B150 },
{ 200 , B200 },
{ 300 , B300 },
{ 600 , B600 },
{ 1200 , B1200 },
{ 1800 , B1800 },
{ 2400 , B2400 },
{ 4800 , B4800 },
{ 9600 , B9600 },
{ 19200 , B19200 },
{ 38400 , B38400 },
{ 57600 , B57600 },
{ 115200 , B115200 },
{ 230400 , B230400 },
{ 0, 0 }
};

int dbits_map[] = { 0, 0, 0, 0, 0, CS5, CS6, CS7, CS8 };

enum parity_t {
PARITY_NO_PARITY,
PARITY_ODD,
PARITY_EVEN
};

int baud_to_speed(int baud, speed_t *speed)
{
if(speed == NULL)
return 0;

struct baud_map *map = baudmap;
while(map->baud)
{
if(map->baud == baud)
{
*speed = map->speed;
return 1;
}

map++;
}

return 0;
}

/*
* tty: "/dev/ttyUSB0"
* baud: baudrate, for example 9600
* parity: see enum parity_t
* stop_bits: 1 or 2
* data_bits: [5-8]
*
* return the fd on success, -1 on failure
*/
int openSerial_long(const char *tty, int baud, enum parity_t parity, int stop_bits, int data_bits)
{
int fd;

speed_t speed;

if(baud_to_speed(baud, &speed) == 0)
{
fprintf(stderr, "Invalid baudrate %d\n", baud);
return 0;
}

fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK);

if(fd == -1)
{
fprintf(stderr, "Could not open %s as a tty: %s\n", tty, strerror(errno));
return -1;
}

struct termios termios;

if(tcgetattr(fd, &termios) == -1)
{
fprintf(stderr, "Could not get tty attributes from %s: %s\n", tty, strerror(errno));
close(fd);
return -1;
}

// setting common values
termios.c_iflag &= ~ICRNL; // do not translate \r into \n
termios.c_oflag &= ~OPOST; // do not map \n to \r\n
termios.c_cflag |= (CREAD | CLOCAL); // enable receiver & ignore model ctrl lines
termios.c_lflag |= (ISIG | ICANON); // enable signals and noncanonical mode
termios.c_lflag &= ~ECHO; // disable echo


cfsetispeed(&termios, speed);
cfsetospeed(&termios, speed);

switch(parity)
{
case PARITY_NO_PARITY:
termios.c_cflag &= ~PARENB;
break;
case PARITY_ODD:
termios.c_cflag |= PARENB;
termios.c_cflag |= PARODD;
break;
case PARITY_EVEN:
termios.c_cflag |= PARENB;
termios.c_cflag &= ~PARODD;
break;
default:
fprintf(stderr, "invalid parity\n");
break;
}

if(stop_bits == 1)
termios.c_cflag &= ~CSTOPB;
else if(stop_bits == 2)
termios.c_cflag |= CSTOPB;
else
fprintf(stderr, "Invalid stop bit\n");

int bits;

switch(data_bits)
{
case 5:
case 6:
case 7:
case 8:
bits = dbits_map[data_bits];
break;

default:
bits = -1;

}

if(bits != -1)
{
termios.c_cflag &= ~CSIZE;
termios.c_cflag |= bits;
} else
fprintf(stderr, "Invalid data size\n");


if(tcsetattr(fd, TCSANOW, &termios) == -1)
{
fprintf(stderr, "Could not get tty attributes from %s: %s\n", tty, strerror(errno));
close(fd);
return -1;
}


return fd;
}

/**
* tty: "/dev/ttyUSB0"
* baud: baudrate, for example 9600
* mode: a string like 8N1 where
* the first character is the number of data bits (range from 5-8)
* the second character is N (no parity), O (odd), E (even)
* the third character is the number of stop bits (1 or 2)
*/
int openSerial(const char *tty, int baud, const char *mode)
{
if(tty == NULL || mode == NULL)
return -1;

if(strlen(mode) != 3)
{
fprintf(stderr, "invalid mode\n");
return -1;
}

int stop_bits = mode[2];
if(stop_bits != '1' && stop_bits != '2')
{
fprintf(stderr, "Invalid stop bits\n");
return -1;
}

stop_bits -= '0';

enum parity_t parity;
switch(mode[1])
{
case 'n':
case 'N':
parity = PARITY_NO_PARITY;
break;
case 'o':
case 'O':
parity = PARITY_ODD;
break;
case 'e':
case 'E':
parity = PARITY_EVEN;
break;
default:
fprintf(stderr, "Invalid parity\n");
return -1;
}

int data_bits = mode[0] - '0';

if(data_bits < 5 || data_bits > 8)
{
fprintf(stderr, "invalid data bits\n");
return -1;
}

return openSerial_long(tty, baud, parity, stop_bits, data_bits);
}

最常见的模式是“8N1”(8位数据,无奇偶校验,1个停止位),我打开串行线与

int fd = open("/dev/ttyUSB0", 9600, "8N1");

if(fd == -1)
{
fprintf(stderr, "Error, could not initialize serial line\n");
exit(EXIT_FAILURE);
}

我不知道您必须使用哪些串行设置,请在手册中查找。

还要注意这样的事情

n = write(fd, "AT I\r\n", 10);

是错误的,这是未定义的行为,因为 write 读取超出了范围字符串文字的。最好这样做:

const char *cmd = "AT I\r\n";
n = write(fd, cmd, strlen(cmd));

然后您将写入正确的数据量。

就像我在评论中所说的,我已经对 ISO 9141-2 进行了谷歌搜索,我可以没有找到任何关于它是否使用AT命令的可靠信息。所以,请检查您正在尝试阅读的 OBDII 芯片的手册。

Wikipedia says

ISO 9141-2. This protocol has an asynchronous serial data rate of 10.4 kbit/s. It is somewhat similar to RS-232; however, the signal levels are different, and communications happens on a single, bidirectional line without additional handshake signals. ISO 9141-2 is primarily used in Chrysler, European, and Asian vehicles.

在我看来,这个协议(protocol)只是类似于RS232,也许你需要支持此波特率的另一个转换器(FT232R 除外)。 This页面还指出波特率为 10400 位/秒,这不是默认支持。我找到了这个post这也表明你应该使用两个转换器,一个用于OBD2和转换器之间的通信以 10.4 kbit/s 传输,转换器和 PC 之间以标准波特率传输比如 19.2 kbits/s。

或者,您可以尝试设置自定义波特率,如 here 中所述。和 here 。我从来没有使用过自定义波特率,所以我不知道这是否有效。

关于c - 尝试将 AT 命令写入 USB 转 OBDii 电缆,使用 FT232R 读取 ECU 数据 (ISO 9141-2),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49221630/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com