Jump to content
    

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

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

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

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

Share this post


Link to post
Share on other sites

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:

Share this post


Link to post
Share on other sites

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 минут" не получится.

Share this post


Link to post
Share on other sites

Цитата

Все получил, кроме 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 если первые два сегмента в одно поле)

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

Share this post


Link to post
Share on other sites

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

Цитата

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

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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

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

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

Share this post


Link to post
Share on other sites

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

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

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...