Получение сообщения длиннее 8 байт с can шины через mcp 2515

Тема в разделе "Arduino & Shields", создана пользователем Br1ght, 30 апр 2021.

  1. Br1ght

    Br1ght Нуб

    Добрый день. Буду очень благодарен за подсказку с кодом. Я от программирования довольно далек, но в скетче более-менее разобрался, кроме одного момента.

    В целом всё успешно: получаю из КАН-шины ответ на запрос в виде последовательности байт. Затем определенные байты использую для вычисления значений типа RPM, температуры и прочего. Но это работает только с блоками, где ответ на мой запрос не длиннее 8 байт.

    Например, я успешно получаю из блока двигателя вот эту строку: 5 62 20 2 B B8. Беру из неё 5 и 6 байты, подставляю в известную мне формулу и всё ок.
    Код (C++):
    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 байт, потом вторые, потом третьи. Это вообще возможно?
     
  2. parovoZZ

    parovoZZ Гуру

    ну так в указанной функции необходимо первым аргументом указать длину сообщения в байтах, а вторым аргументом буфер. Буфер должен быть такой длины, чтобы уместились все байты.