Перейти к содержанию
    

Калькулятор битовой скорости

Приветствую!

Поделитесь, пожалуйста, адекватным калькулятором битовой скорости CAN 2.0B.
Перепробовал кучу - во всех разные косяки: какие-то не могут расчитать для < 50кбит/с, какие-то просто не работают.

Нужно получить таблицу настроек скоростей, поэтому под рукой хотелось бы иметь удобный калькулятор.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Arlleex сказал:

Нужно получить таблицу настроек скоростей, поэтому под рукой хотелось бы иметь удобный калькулятор.

Вы бы хоть указали для какого МК.... А то у меня в XMC4xxx как-то так:

Скрытый текст

#define CLKKIT2(tseg1, tseg2) \
  ((((tseg2 > 4) ? 3: tseg2 - 2) | tseg1 - 1 << 2 | tseg2 - 1 << 6) * \
  assert_static(1 + tseg1 + tseg2 > 7 && tseg1 > 2 && tseg1 < 17 && tseg2 > 1 && tseg2 < 9))
#define CLKKIT(tq) CLKKIT2(tq)

//CAN.NODE[].BTR: TSEG1, TSEG2
#define BIT_TQ_12  7,  4
#define BIT_TQ_13  8,  4
#define BIT_TQ_15  10, 4
#define BIT_TQ_16  10, 5
#define BIT_TQ_18  11, 6
#define BIT_TQ_20  13, 6
#define BIT_TQ_22  14, 7
#define BIT_TQ_24  15, 8
#define BIT_TQ_25  16, 8

#define FDR_STEP_72000000   4
#define FDR_STEP_80000000   4
#define FDR_STEP_100000000  5
#define FDR_STEP_108000000  9
#define FDR_STEP_120000000  6
#define FDR_STEP_128000000  8
#define FDR_STEP_132000000  11
#define FDR_STEP_140000000  7
#define FDR_STEP_144000000  9

//наборы для инициализации CAN.NODE[].BTR для разных PBCLK_MH
#define CANCLKKIT_1M0_72000000   CLKKIT(BIT_TQ_18)
#define CANCLKKIT_1M0_80000000   CLKKIT(BIT_TQ_20)
#define CANCLKKIT_1M0_100000000  CLKKIT(BIT_TQ_20)
#define CANCLKKIT_1M0_108000000  CLKKIT(BIT_TQ_12)
#define CANCLKKIT_1M0_120000000  CLKKIT(BIT_TQ_20)
#define CANCLKKIT_1M0_128000000  CLKKIT(BIT_TQ_16)
#define CANCLKKIT_1M0_132000000  CLKKIT(BIT_TQ_12)
#define CANCLKKIT_1M0_140000000  CLKKIT(BIT_TQ_20)
#define CANCLKKIT_1M0_144000000  CLKKIT(BIT_TQ_16)

#define CANCLKKIT_0M8_72000000   CLKKIT(BIT_TQ_18)
#define CANCLKKIT_0M8_80000000   CLKKIT(BIT_TQ_25)
#define CANCLKKIT_0M8_100000000  CLKKIT(BIT_TQ_25)
#define CANCLKKIT_0M8_108000000  CLKKIT(BIT_TQ_15)
#define CANCLKKIT_0M8_120000000  CLKKIT(BIT_TQ_25)
#define CANCLKKIT_0M8_128000000  CLKKIT(BIT_TQ_20)
#define CANCLKKIT_0M8_132000000  CLKKIT(BIT_TQ_15)
#define CANCLKKIT_0M8_140000000  CLKKIT(BIT_TQ_25)
#define CANCLKKIT_0M8_144000000  CLKKIT(BIT_TQ_20)

#define CLKKIT_SELECT(pbclk, base) ( \
  (pbclk == 144000000) ? CANCLKKIT_##base##_144000000: \
  (pbclk == 140000000) ? CANCLKKIT_##base##_140000000: \
  (pbclk == 132000000) ? CANCLKKIT_##base##_132000000: \
  (pbclk == 128000000) ? CANCLKKIT_##base##_128000000: \
  (pbclk == 120000000) ? CANCLKKIT_##base##_120000000: \
  (pbclk == 108000000) ? CANCLKKIT_##base##_108000000: \
  (pbclk == 100000000) ? CANCLKKIT_##base##_100000000: \
  (pbclk == 80000000)  ? CANCLKKIT_##base##_80000000:  \
  (pbclk == 72000000)  ? CANCLKKIT_##base##_72000000:  \
  assert_static(0))

#define FDR_STEP(pbclk) ( \
  (pbclk == 144000000) ? FDR_STEP_144000000: \
  (pbclk == 140000000) ? FDR_STEP_140000000: \
  (pbclk == 132000000) ? FDR_STEP_132000000: \
  (pbclk == 128000000) ? FDR_STEP_128000000: \
  (pbclk == 120000000) ? FDR_STEP_120000000: \
  (pbclk == 108000000) ? FDR_STEP_108000000: \
  (pbclk == 100000000) ? FDR_STEP_100000000: \
  (pbclk == 80000000)  ? FDR_STEP_80000000:  \
  (pbclk == 72000000)  ? FDR_STEP_72000000:  \
  assert_static(0))

#define TQ_SJW(clkkit)   (((clkkit) >> 0 & 3) + 1)
#define TQ_TSEG1(clkkit) (((clkkit) >> 2 & 15) + 1)
#define TQ_TSEG2(clkkit) (((clkkit) >> 6 & 7) + 1)
  
__packed struct CfgCan { //конфиг CAN
  enum { //[бод] возможные скорости
    RATE_1M, RATE_800K, RATE_500K, RATE_250K, RATE_200K,
    RATE_125K, RATE_100K, RATE_62K5, RATE_50K, RATE_40K,
    RATE_n};
  ...
};  

static u32 const canRates[] = {1000000, 800000, 500000, 250000, 200000, 125000, 100000, 62500, 50000, 40000};
...
static void CanOn(CfgMain const *cfg, int ix)
{
  enum {CLKKIT_0M8 = CLKKIT_SELECT(PBCLK_MH, 0M8), CLKKIT_1M0 = CLKKIT_SELECT(PBCLK_MH, 1M0)};
  uint i, i1, rate;
  canCurRate[ix] = rate = cfg->can.port[ix].baud;
  HwRegsCAN::T_NODE volatile *node = &CAN.NODE[(ix == CfgCan::IX_INT) ? nCAN_int: nCAN_ext];
  node->CR = B0 | B6;
  u32 j = PBCLK_MH / FDR_STEP(PBCLK_MH) / (1 + TQ_TSEG1(CLKKIT_1M0) + TQ_TSEG2(CLKKIT_1M0));
  i = CLKKIT_1M0;
  if (rate == CfgCan::RATE_800K) {
    j = PBCLK_MH / FDR_STEP(PBCLK_MH) / (1 + TQ_TSEG1(CLKKIT_0M8) + TQ_TSEG2(CLKKIT_0M8));
    i = CLKKIT_0M8;
  }
  node->BTR = j / canRates[rate] - 1 | i << 6;
  node->SR = 0;
  node->ECNT = 96 << 16;
  node->FCR = 3 << 19;
  ...

 

но что-то сомневаюсь, что Вам поможет...  :unknw:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

STM32F4. К сожалению, выяснил, что 800кбит/с не получится задать при своей частоте шины.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, jcxz сказал:

На XMC4xxx можно и 1000кбод и 800кбод хоть на 144МГц хоть на 120МГц.  :wink:

Ну, в свой девайс лапы в лапы XMC4 вместо STM32 я не запаяю:biggrin:

В XMC, как я понял, есть дробный предделитель на входе baudrate-делителя CAN-периферии.

В моем случае я просто откажусь от реализации данной битовой скорости (позволительно).

Вообще у меня список скоростей из 10к-, 20к-, 50к-, 100к-, 125к-, 250к-, 500к-, 800к- и 1000кбит/с. Все получил, кроме 800.
Можно, конечно, частотой APB поиграться, но что-то уже лень. Глядишь, какая-нибудь другая битовая скорость отвалится:smile:

Пока что, в общем, отложу этот вопрос на попозже. Может и реализую.

P.S. А вообще, мудреный он, этот XMC. Гибкий это, конечно, да, но на фоне других МК "поднять UART за 10 минут" не получится.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Цитата

Все получил, кроме 800.

Если тактовая 72 МГц - 800К - вроде кратная частота - должно получиться. Я с STM не работал, но вроде принцип у всех похожий, только по регистрам по разному раскидывают.

Попробуйте след. метод.

72М/800К = 90 - один бит CAN должен быть 90 тактов кварца. Эти 90 тактов нужно разбить на кванты (Tq) должно получиться от 4 до 24 квантов

для целочисленного деления подходят значения 5*18, 9*10, 15*6

Удобнее выбрать пару 18*5 (чем больше сегментов - тем больше вариантов распределения), Тогда предделитель BRP должен быть 5 (в регистр чаще всего записывается N-1)

1 квант - это синхроимпульс (обязательный), оставшиеся 17 квантов нужно распределить по сегментам, Чаще всего увеличивают первые два сегмента, чтобы сместить точку выборки к концу посылки. Как выбирают SJW не помню на вскидку. Не нужно забывать что длина сегментов ограничена (в регистрах либо 3 поля по 3 бита - каждый сегмент от 1 до 8, либо первые 2 сегмента объединяют и тогда первое поле 4 бита от 1 до 16, второе поле от 1 до 8).

17 квантов я бы распределил так 8 - PROP, 6 - SEG1, 3 - SEG2. Точка выборки получается - около 83% (1 - SEG2/18) (или 14 + 3 если первые два сегмента в одно поле)

Попробуйте. Удачи.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо конечно, но все это я и сам понимаю. Я не просто так написал

Цитата

STM32F4. К сожалению, выяснил, что 800кбит/с не получится задать при своей частоте шины.

Частота шины APB у меня не может быть произвольной: на нее завязано много чего:wink:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16.02.2022 в 18:57, Arlleex сказал:

В XMC, как я понял, есть дробный предделитель на входе baudrate-делителя CAN-периферии.

Имеется, но я его не использую. Так как он задаёт общую частоту для всех CAN-интерфейсов МК, а они у меня в устройстве работают на независимых скоростях.

Да и без дробного нормально получается - не нужен он для 1000 / 800 кбод.

При старте ПО:

  CAN.FDR = 1 << 14 | 1024 - FDR_STEP(PBCLK_MH);
  { u32 dummy = CAN.FDR; }

и больше CAN.FDR не трогается. Не зависимо от изменения bitrate на любом CAN-интерфейсе.

 

Цитата

Вообще у меня список скоростей из 10к-, 20к-, 50к-, 100к-, 125к-, 250к-, 500к-, 800к- и 1000кбит/с. Все получил, кроме 800.
Можно, конечно, частотой APB поиграться, но что-то уже лень. Глядишь, какая-нибудь другая битовая скорость отвалится:smile:

А я получил и 1000 и 800 и все производные вниз от 1000. При одной и той частоте периферийной шины (у меня это PBCLK_MH).

Я специально привёл кусок инициализации CAN-интерфейса где это делаю. Со всеми макросами. Но Вы похоже не смотрели его. :unknw:

Конкретно: расчёт содержимого node->BTR (CAN_NBTRx).

Ничего там сложного нет. И не дробный делитель не нужен, ни менять частоту шины тоже не нужно. По-крайней мере в XMC с евойным CAN_NBTRx.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 часов назад, jcxz сказал:

А я получил и 1000 и 800 и все производные вниз от 1000. При одной и той частоте периферийной шины (у меня это PBCLK_MH).

Частота APB у меня 42МГц. 42/0.8 = 52.5 -> не целое.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Arlleex сказал:

Частота APB у меня 42МГц. 42/0.8 = 52.5 -> не целое.

Ну так поменять её на 40 или 44 или любую другую, кратную 4МГц. Неужели так сложно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...