Получение сообщения длиннее 8 байт с CAN шины через MCP 2515
- Войдите на сайт для отправки комментариев
Добрый день. Буду очень благодарен за подсказку с кодом. Я от программирования довольно далек, но в скетче более-менее разобрался, кроме одного момента.
В целом всё успешно: получаю из КАН-шины ответ на запрос в виде последовательности байт. Затем определенные байты использую для вычисления значений типа RPM, температуры и прочего. Но это работает только с блоками, где ответ на мой запрос не длиннее 8 байт.
Например, я успешно получаю из блока двигателя вот эту строку: 5 62 20 2 B B8. Беру из неё 5 и 6 байты, подставляю в известную мне формулу и всё ок.
float enginePIDs(int parameter) { unsigned char PID[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; float retValue = 9999; // возвращаемое значение (если 9999 - ошибка) long unsigned int moduleIdRequest = 0x7E0; // id модуля в запросе данных long unsigned int moduleIdAnswer = 0x7E8; // id модуля в ответе PID[0] = 0x03; // количество байт в запросе PID[1] = 0x22; // префикс PID для запроса switch (parameter) { case 0: // 2002 - PID RPM PID[2] = 0x20; PID[3] = 0x02; break; } // посылаем запрос ЭБУ CAN1.sendMsgBuf(moduleIdRequest, 0, 8, PID); PID[1] = 0x62; // префикс PID для ответа rxId = 0x000; // обнуляем идентификатор timeOut = millis() + 500; // крайнее время ожидания ответа // ждём нужного ответа while ((rxId != moduleIdAnswer || rxBuf[1] != PID[1] || rxBuf[2] != PID[2] || rxBuf[3] != PID[3]) && millis() < timeOut) { if (CAN_MSGAVAIL == CAN1.checkReceive()) { CAN1.readMsgBuf(&len, rxBuf); // чтение данных: len = data length, buf = data byte(s) rxId = CAN1.getCanId(); // получаем ID сообщения } } if (rxId == moduleIdAnswer && rxBuf[1] == PID[1] && rxBuf[2] == PID[2] && rxBuf[3] == PID[3]) { // вычисляем параметр, A = rxBuf[4], B = rxBuf[5], C = rxBuf[6], D = rxBuf[7] switch (parameter) { case 0: // RPM retValue = (256 * rxBuf[4] + rxBuf[5]) / 4.0; break; } } return retValue; }
Но другой блок отвечает на запрос сообщением из аж 23 байт. И как нарочно, для вычислений мне нужен 18 байт.
что сделать с CAN1.readMsgBuf(&len, rxBuf) чтобы получить все байты ответа? Как вызвать её три раза так, чтобы 1 раз читались первые 8 байт, потом вторые, потом третьи. Это вообще возможно?
Прям так и шлёт, три пакета с одним и тем же ID? В мессейдж мож sequence id засунут?
В CAN 2.0 пакетов с нагрузкой больше 8 байтов не бывает. Либо у тебя устройство с CAN-FD, и тогда 2515 не пойдет, либо ты что-то путаешь.
вот примеры сообщений:
короткое, из блока двигателя: 7E0;222002;62 20 02 0B D8
длинное, из блока климата, в моем случае: 744;2122;61 22 03 00 00 02 20 00 00 00 34 80 FA 09 00 00 38 02 1B 7E 17 8B 00 00 00 00 00
вот в другом немного формате
двигатель
22:26:48.611 -> CAN ID: 7E8
Оно не не лезет в буфер, стандарт не даёт в кадрах передавать более 8 байт. Скорее всего от климата несколько фреймов с одним и тем же ID. Вам нужно просто типа склеить несколько кадров по 8 байт
Макс, а как там последовательность кадров задается, в этих ваших автомобилях?
Не знаю, стандарта нет, это как производителю в голову взбредет. В теле кадра байт на это может быть отведен