Как сравнить две переменных типа struct

Pavel64
Offline
Зарегистрирован: 14.06.2022

Здравствуйте принимаю данные из can шины сохраняю их в struct can_frame canMsg , жду сообщения с конкретными известными мне данными  эталонный фрейм сохранен в переменной struct can_frame canMsg3;

     canMsg3.can_id  = 0x7E1;

  canMsg3.can_dlc = 8;
  canMsg3.data[0] = 0x2;
  canMsg3.data[1] = 0x21;
  canMsg3.data[2] = 0xA0;
  canMsg3.data[3] = 0x00;
  canMsg3.data[4] = 0x00;
  canMsg3.data[5] = 0x00;
  canMsg3.data[6] = 0x00;
  canMsg3.data[7] = 0x00;    
Принимаю данные пытаюсь сравнить два фрейма и при совпадении передать сообщение &canMsg в can шину.
 
if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    for (int i = 0; i<canMsg.can_dlc; i++)  {
     if (&canMsg == &canMsg3){
mcp2515.sendMessage(&canMsg1);
 
 Контролирую произходящее в шине канхакером Действия не выполняются хотя нужный мне фрейм точно приходит.
Как выполнить действие при получении нужного мне фрейма?

 

rkit
Offline
Зарегистрирован: 23.11.2016

Ты адреса пакетов в памяти сравниваешь, а не содержимое.

Pavel64
Offline
Зарегистрирован: 14.06.2022

rkit пишет:

Ты адреса пакетов в памяти сравниваешь, а не содержимое.

По аналогии с отправкой пакета mcp2515.sendMessage(&canMsg2); думал что &canMsg это все сообщение целиком. Так Id у этих пакетов тоже одинаковые, функция должна все равно выполнится.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

Pavel64 пишет:

rkit пишет:

Ты адреса пакетов в памяти сравниваешь, а не содержимое.

По аналогии с отправкой пакета mcp2515.sendMessage(&canMsg2); думал что &canMsg это все сообщение целиком. Так Id у этих пакетов тоже одинаковые, функция должна все равно выполнится.

сказали же, АДРЕСА, они не могут быть одинаковыми, даже при одинаковых полях Id и остальных.

копать те надо в сторону memcmp.

rkit
Offline
Зарегистрирован: 23.11.2016

Надо было читать учебник, а не думать. memcmp не пойдет, потому что пакеты бывают разной длины, и в хвосте структуры может быть мусор.

Pavel64
Offline
Зарегистрирован: 14.06.2022
Попробывал такую конструкцию не работает.
 
if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    for (int i = 0; i<canMsg.can_dlc; i++)  {
     int n;
     n = memcmp (&canMsg, &canMsg3, size_t (&canMsg));
    }    
if (n == 0){
  mcp2515.sendMessage(&canMsg1);
}
 
}
Есть еще какие мысли?
xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

rkit пишет:

Надо было читать учебник, а не думать. memcmp не пойдет, потому что пакеты бывают разной длины, и в хвосте структуры может быть мусор.

про сравнить пакеты по наименьшей длине, в учебниках не сказано?

sadman41
Offline
Зарегистрирован: 19.10.2016

Что эта конструкция делает?

Pavel64
Offline
Зарегистрирован: 14.06.2022

sadman41 пишет:
Что эта конструкция делает?
Сравнивает &canMsg и &canMsg3 и если они совпадают возвращает 0 присваиваем переменой n = memcmp и если n=0 то.

if (n == 0){

  mcp2515.sendMessage(&canMsg1); // отправляем сообщение
xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

1 - нахера ты это делаешь в цикле

2 - у тя n  совсем не та n после скобок

3 - будешь писать код не как положено, забанят.

https://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukommentarii

Pavel64
Offline
Зарегистрирован: 14.06.2022

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

  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    for (int i = 0; i < canMsg.can_dlc; i++)  {
    }
  }
  int n;
  n = memcmp (&canMsg, &canMsg3, size_t (7));
  if (n == 0) {
    delay(10);
    mcp2515.sendMessage(&canMsg1);
  }

 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

ой господя, исправь size_t(7) на просто 7 и иди с богом...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Не проще ли добавить к struct оператор сравнения и спокойно сравнивать через обычные == или там > / < ?

rkit
Offline
Зарегистрирован: 23.11.2016

Тут нужно сравнивать не всю структуру, а только нагрузку, на самом деле.

Pavel64
Offline
Зарегистрирован: 14.06.2022

ЕвгенийП пишет:

Не проще ли добавить к struct оператор сравнения и спокойно сравнивать через обычные == или там > / < ?


Так ка вы паписали оно не работает, даже компилятор ругается на то что нелзя сравнивать структуры.

Pavel64
Offline
Зарегистрирован: 14.06.2022

rkit пишет:

Тут нужно сравнивать не всю структуру, а только нагрузку, на самом деле.


В 10-м посте правильный кусок кода?

b707
Offline
Зарегистрирован: 26.05.2017

Pavel64 пишет:
В 10-м посте правильный кусок кода?

нет.

как минимум ошибка, про которую сказали в #11

да и вообще код бредятина... зачем там цикл For?  что делает первое if ?

Похоже, код вы пишете методом тыка, не подошло одно слово - меняете на другое...

b707
Offline
Зарегистрирован: 26.05.2017

Pavel64 пишет:
Так ка вы паписали оно не работает, даже компилятор ругается на то что нелзя сравнивать структуры.

не спорьте, вы даже не поняли. о чем речь...

Слушайте. зачем вы в КАН полезли. если ни черта не понимаете в программировании?

rkit
Offline
Зарегистрирован: 23.11.2016
bool can_data_eq(const can_frame &a, const can_frame &b) {
	if (a.can_dlc != b.can_dlc) return false;
	for(uint8_t i = 0; i < a.can_dlc; ++i) {
		if (a.data[i] != b.data[i]) return false;
	}
	return true;
}

 

Pavel64
Offline
Зарегистрирован: 14.06.2022

b707 пишет:

Pavel64 пишет:
Так ка вы написали оно не работает, даже компилятор ругается на то что нельзя сравнивать структуры.

не спорьте, вы даже не поняли. о чем речь...

Слушайте. зачем вы в КАН полезли. если ни черта не понимаете в программировании?

Есть автомобиль  двигатель работает по САN, АКПП по K-line в автомобиле установлен бортовой компьютер мультитроникс который может выводить температуру АКПП работающую по CAN на головное устройство на андройд. То есть подключаюсь к АКПП по K-line запрашиваю нужную мне информацию и отправляю ее в CAN шину где ее ловит мультитроникс и выводит на экран головного устройства.

#include <SPI.h>
#include <mcp2515.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
MCP2515 mcp2515(53);
LiquidCrystal_I2C lcd(0x27, 16, 2);
struct can_frame canMsg;
struct can_frame canMsg1;
struct can_frame canMsg2;
struct can_frame canMsg3;
struct can_frame canMsg4;
unsigned long timing; // Переменная для хранения точки отсчета
byte Init[] = {0x81, 0x18, 0xF1, 0x81, 0x0B};   // Запрос присутствие адаптера
byte Init1[] = {0x81, 0x18, 0xF1, 0x3E, 0xC8};
byte request[] = {0x82, 0x18, 0xF1, 0x21, 0x01, 0xad};
byte answer[112]; // вообще говоря, в ответе 11 байт. Но ещё 7 байт придут перед ответом, это сам запрос, т.к. в протоколе K-Line присутствует эхо
byte answerinit[12];
int temperature = 0;
byte answer_fastinit[12];
byte stage;

void setup() {

  canMsg1.can_id  = 0x7E9;
  canMsg1.can_dlc = 8;
  canMsg1.data[0] = 0x10;
  canMsg1.data[1] = 0x0C;
  canMsg1.data[2] = 0x61;
  canMsg1.data[3] = 0x02;
  canMsg1.data[4] = 0x00;
  canMsg1.data[5] = 0x06;
  canMsg1.data[6] = 0xB0;
  canMsg1.data[7] = 0x00;

  canMsg2.can_id  = 0x7E9;
  canMsg2.can_dlc = 8;
  canMsg2.data[0] = 0x21;
  canMsg2.data[1] = 0xA0;
  canMsg2.data[2] = 0x2C;
  canMsg2.data[3] = answer[20];
  canMsg2.data[4] = stage;
  canMsg2.data[5] = 0x60;
  canMsg2.data[6] = 0x01;
  canMsg2.data[7] = 0x00;

  canMsg3.can_id  = 0x7E1;
  canMsg3.can_dlc = 8;
  canMsg3.data[0] = 0x2;
  canMsg3.data[1] = 0x21;
  canMsg3.data[2] = 0xA0;
  canMsg3.data[3] = 0x00;
  canMsg3.data[4] = 0x00;
  canMsg3.data[5] = 0x00;
  canMsg3.data[6] = 0x00;
  canMsg3.data[7] = 0x00;

  canMsg4.can_id  = 0x7E1;
  canMsg4.can_dlc = 8;
  canMsg4.data[0] = 0x30;
  canMsg4.data[1] = 0x00;
  canMsg4.data[2] = 0x05;
  canMsg4.data[3] = 0x00;
  canMsg4.data[4] = 0x00;
  canMsg4.data[5] = 0x00;
  canMsg4.data[6] = 0x00;
  canMsg4.data[7] = 0x00;

  Serial.begin(9600);       // USB
  //Serial1.begin(10400);     // K-line TX RX (18,19)
  Serial2.begin(9600);      // Bluetooth HC-06 TX RX (16,17)
  mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS, MCP_16MHZ);
  mcp2515.setNormalMode();

  lcd.init();
  lcd.backlight();

  pinMode(18, OUTPUT); // TX1
  digitalWrite(18, HIGH);
  delay(300);
  digitalWrite(18, LOW);
  delay(25);
  digitalWrite(18, HIGH);
  delay(25);
  Serial1.begin(10400);
  Serial1.write(Init, 5);
  delay(40);

  while (Serial1.available() > 0) {
    for (int i = 0; i < 12; i++) {
      answer_fastinit[i] = Serial1.read();
    }
  }
  for (int i = 0; i < 12; i++)

    if (answer_fastinit[8] == 0xC1)
    {

      //Serial2.print("Fast_init OK");
      //  Serial2.print(' ');
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Fast_init OK");
      lcd.setCursor(14, 0);
      lcd.print(answer_fastinit[8], HEX);

    }
    else
    {
      //Serial2.print("Fast_init EROR");
      // Serial2.print(' ');
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Fast_init EROR");
      lcd.setCursor(0, 1);
      lcd.print(answer_fastinit[i], HEX);
    }

  Serial1.write(Init1, 5);
  while (Serial1.available() > 0) {
  }
}

void loop() {
  Serial1.write(request, 6);

  while (Serial1.available() > 0) {
    for (int i = 0; i < 112; i++) {

    }
  }

  for (int i = 0; i < 112 ; i++) {

    //  Serial2.print(answer[20], HEX);
    //  Serial2.print(' ');
    delay(1);

    temperature = (answer[20] - 40);
    stage = (answer[61] + 1);
  }
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Temp:");
  lcd.setCursor(5, 0);
  lcd.print(temperature);
  lcd.setCursor(10, 0);
  lcd.print("Step:");
  lcd.setCursor(15, 0);
  lcd.print(stage);

  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    for (int i = 0; i < canMsg.can_dlc; i++)  {
    }
  }
  int n;
  n = memcmp (&canMsg, &canMsg3, (7));
  if (n == 0) {
    mcp2515.sendMessage(&canMsg1);
  }
  n = memcmp (&canMsg, &canMsg4, (7));
  if (n == 0) {
    mcp2515.sendMessage(&canMsg2);
  }

}

//Serial.print(canMsg.can_id, HEX); // print ID
//Serial.print(" ");
// Serial.print(canMsg.can_dlc, HEX); // print DLC
// Serial.print(" ");

// for (int i = 0; i<canMsg.can_dlc; i++)  {  // print the data
// Serial.print(canMsg3.data[i],HEX);
// Serial.print(" ");
//}
//}

 

Pavel64
Offline
Зарегистрирован: 14.06.2022

Может есть желающие помочь на коммерческой основе. frolov.pavel.64@mail.ru

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Пиши в Ищу исполнителя тогда.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Pavel64 пишет:
ЕвгенийП пишет:

Не проще ли добавить к struct оператор сравнения и спокойно сравнивать через обычные == или там > / < ?

Так ка вы паписали оно не работает, даже компилятор ругается на то что нелзя сравнивать структуры.

Нет, как раз так, как  я написал работает.

Вы начало фразы не прочитали.