Как запрограммировать 2 узла CAN для непрерывной последовательной передачи?

Предположим, у меня есть три узла CAN: A, B и C. Мы знаем, что когда два узла передают одновременно, то узел, имеющий наименьший SID, будет преобладать над шиной, и другой узел должен будет отдать шину первому. узел. Что я хотел бы сделать, так это то, что узлы B и C будут непрерывно отправлять кадр CAN узлу A последовательно (например, узел B -> узел A, узел C -> узел A, узел B -> узел A). Могу ли я просто назначить более низкий SID для B, чем для C, и просто выполнить следующий фрагмент кода?

Узел Б

while(1) sendCANmsg(data, NODE_A, sizeof(data), RTR_OFF);

Узел С

while(1) sendCANmsg(data, NODE_A, sizeof(data), RTR_OFF);

Внутри sendCANmsg есть фрагмент:

TXB0CONbits.TXREQ = 1;  // Request Message Transmission
while (TXB0CONbits.TXREQ); // Wait until message is sent.

Кстати, я использую PIC18F25k80 для реализации этого. Я просто подумал, что после того, как узел B отправил сообщение, когда узел C собирается отправить свое сообщение. Узел B снова выиграет арбитраж шины, что не даст узлу C возможности передачи. Поэтому я исправляю, о чем могу только подумать, это вставить небольшую задержку, например:

while(1) {
    sendCANmsg(data, NODE_A, sizeof(data), RTR_OFF);
    delay_us(10);
}

Или я ошибаюсь? :)

Ответы (2)

Поскольку этот метод позволяет использовать шину почти на 100%, мы предполагаем, что эти 3 узла являются единственными узлами на шине. Основываясь на вашем времени задержки 10 мкс, мы также предполагаем, что скорость шины составляет 500 кбит/с (т. е. 5 бит задержки или 1 бит меньше ожидания после арбитража между сообщениями).

Будет ли этот метод работать или нет, во многом зависит от деталей реализации вашего CAN-драйвера. Более надежным способом добиться этого было бы, чтобы узлы B и C ждали чтения сообщения друг друга перед отправкой (с узлом B, изначально передающим без ожидания). IE:

  1. Проснуться
  2. Узел C ожидает сообщения B
  3. Узел B передает
  4. Узел B ожидает сообщения C
  5. Узел C передает
  6. Узел C ожидает сообщения B
  7. И т. д.

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

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

Обратите внимание, что это нетрадиционное использование CAN. Возможно, вам будет лучше обслуживать более простой протокол, такой как SPI (узел A должен будет опрашивать B и C, но не потребуется арбитража, и все может быть DMA и/или управляемым прерыванием).

Благодарю за ваш ответ. :) Я только что понял, что могу использовать приемные фильтры только для этой реализации (например, для определения, отправил ли другой узел сообщение CAN). Однако в PICf25k80 всего 6 приемных фильтров и 2 приемные маски. Если сеть CAN станет больше, где-то меньше, но около 2^11 - 1, будет ли достаточно приемочных фильтров и масок? Я хотел бы услышать об обычном использовании CAN. :)
Я не уверен, что вы имеете в виду, когда говорите «меньше, но около 2 ^ 11-1». Существует практическое ограничение на количество узлов, которые могут быть подключены к одной шине CAN из-за емкостной нагрузки — обычно это чуть более 100 узлов. Более традиционным использованием CAN может быть среда, управляемая событиями (с вариантами опроса и некоторыми нечастыми сообщениями типа пульса). Идея состоит в том, чтобы максимально снизить использование шины, хотя это становится сложнее по мере добавления к шине новых узлов. Ваш сценарий больше похож на глоток из пожарного шланга, с постоянными пулеметными обновлениями.
Виноват. Я должен был сказать где-то между 0 и 2^11-1. Поскольку SID имеет длину 11 бит, я думаю, что предел сети CAN составляет 2 ^ 11-1. Спасибо, что указали на это. Я просто хочу знать, что произойдет, если он будет стрелять непрерывно. Моя реальная реализация заключается в том, что у меня есть 6 узлов, но только один узел собирает данные с других 5 узлов. Итак, мой план состоит в том, чтобы остальные 5 узлов последовательно отправлять на узел-сборщик каждые n миллисекунд. Что вы думаете? РТР лучше?
Вопрос в том, нужны ли вам обновления так часто. В случае, когда «мастер» (узел сбора данных) нуждается только в спорадических обновлениях и приемлема небольшая задержка, RTR имеет смысл. Если мастеру требуется немедленный доступ к текущему значению, но значения изменяются медленно, тогда другие узлы могут просто запускать сообщения всякий раз, когда происходит изменение. Если значения изменяются достаточно быстро, они увеличивают использование шины, и может быть полезно, чтобы они отправляли циклический стиль, как вы предложили. Просто обратите внимание, что круговой алгоритм — это не тот сценарий, для которого был разработан CAN.
Теперь это имеет смысл. Я забыл, что каждый узел имеет разные процессы перед передачей своих данных на узел-сборщик. Имеет смысл передавать только тогда, когда есть изменение. Спасибо, сэр :)

Во-первых, у узлов нет идентификаторов, а у сообщений есть.

Это сложно, и это не то, для чего CAN был разработан. Это должно работать, если каждый узел преднамеренно немного задерживается после каждой успешной передачи. Я не помню, позволяет ли оборудование PIC 18F25K80 узнать, когда кадр фактически отправлен, но, вероятно, это так. Другому узлу нужно только короткое окно, чтобы увидеть конец кадра и начать передачу. Как только этот второй узел начнет передачу, первый все равно автоматически задержит свое сообщение до следующего конца кадра.

Однако это звучит как злоупотребление шиной CAN, и лучшим ответом может быть переосмысление общей архитектуры.

Благодарю за ваш ответ. Я исправляюсь. Я сделал ошибку, заявив, что узлы имеют идентификаторы. Извини за это. В любом случае, что это будет за архитектура? :)
Кстати, относительно того, что вы сказали, что это должно работать, если каждый узел намеренно немного задерживает после каждой успешной передачи, и как только этот второй узел начинает передачу, первый все равно автоматически задерживает свое сообщение до следующего конца кадра. Означает ли это, что это сработает, если я вставлю небольшую задержку только в узле B, поскольку после передачи сообщения CAN от узла C узел B все равно выиграет арбитраж?
@Xegara: Да, вам не нужно откладывать при попытке отправить сообщение с самым низким приоритетом.
О, классно. Вы упомянули, что такая реализация не предназначена для CAN. Я хотел бы узнать больше о правильной реализации CAN. С чего начать? :)
CAN хорошо спроектирован для нескольких узлов, каждый из которых имеет относительно низкую пропускную способность (по сравнению, например, с Ethernet). Вокруг может летать много сообщений, и каждый узел слушает только то, что ему нужно. Кажется, у вас есть один контроллер и два выделенных узла данных. Это может быть лучше реализовано с помощью чего-то вроде SPI, где мастер напрямую контролирует, когда каждый узел отправляет данные. Почему вы считаете, что CAN подходит для вашего случая?
Я просто привел сценарий, чтобы удовлетворить мой вопрос. Моя реальная реализация заключается в том, что у меня есть 6 узлов, но только один узел собирает данные с других 5 узлов. Итак, мой план состоит в том, чтобы остальные 5 узлов последовательно отправлять на узел-сборщик каждые n миллисекунд. Кроме того, особенность CAN заключается в том, что я могу просто добавить еще один узел, не перепрограммируя CAN других узлов, что делает его очень гибким. Что вы думаете?