RT-Thread / RT-Thread/rt-thread

[Feature] 自动配置can波特率的可行性

Open
#10,455 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
12.2k
Forks
5.4k
Avg merge
4d 12h
Merged PRs (30d)
40

Description

Describe problem solved by the proposed feature

Image
目前的bsp配置CAN通信波特率时使用了大量预定义的表格 不同的芯片如果当前不支持 就要新增宏定义
是否可以考虑实现一个函数自动计算适配的波特率参数呢 例如

#include <math.h>
#include <float.h>
#include <stdint.h>
#include <stdio.h>

typedef struct
{
    uint32_t prescaler;
    uint8_t  bs1;
    uint8_t  bs2;
    float    baud_error;
    float    sample_point;
} CAN_TimingConfig;

/**
 * @brief 
 * 
 * @param F_pclk CAN的APB1时钟
 * @param target_baudrate 目标波特率
 * @return CAN_TimingConfig 
 */
CAN_TimingConfig calculate_can_timing(uint32_t F_pclk,
                                      uint32_t target_baudrate)
{
    CAN_TimingConfig best                = {0};
    float            min_error           = FLT_MAX;
    float            target_sample_point = 0.8f;
    const uint8_t    tq_min = 8, tq_max = 25;
    const uint8_t    bs1_max = 16, bs2_max = 8;

    // 扩展分频范围避免遗漏
    uint32_t prescale_max = (F_pclk + target_baudrate * tq_min - 1) / (target_baudrate * tq_min);
    uint32_t prescale_min = F_pclk / (target_baudrate * tq_max);
    prescale_min          = prescale_min > 0 ? prescale_min : 1;
    prescale_max          = prescale_max > 1024 ? 1024 : prescale_max;

    // 逆序循环优先大分频值
    for (uint32_t prescale = prescale_max; prescale >= prescale_min; --prescale)
    {
        float   total_tq = (float)F_pclk / (target_baudrate * prescale);
        uint8_t tq       = (uint8_t)(total_tq + 0.5f);

        if (tq < tq_min || tq > tq_max) continue;

        uint8_t bs1 = (uint8_t)(target_sample_point * tq - 1 + 0.5f);
        uint8_t bs2 = tq - 1 - bs1;

        if (bs1 < 1 || bs1 > bs1_max || bs2 < 1 || bs2 > bs2_max) continue;

        float actual_baud  = (float)F_pclk / (prescale * (1 + bs1 + bs2));
        float baud_err     = fabsf(actual_baud - target_baudrate) / target_baudrate;
        float sample_point = (1.0f + bs1) / (1 + bs1 + bs2);
        float sample_err   = fabsf(sample_point - target_sample_point);
        float total_err    = 0.6f * baud_err + 0.4f * sample_err;

        // 误差更小 或 误差相同但分频更大 或 分频相同但TQ更小
        if ((total_err < min_error) || (total_err == min_error && ((prescale > best.prescaler) || (prescale == best.prescaler && tq < (best.bs1 + best.bs2 + 1)))))
        {
            min_error         = total_err;
            best.prescaler    = prescale;
            best.bs1          = bs1;
            best.bs2          = bs2;
            best.baud_error   = baud_err;
            best.sample_point = sample_point;
        }
    }
    return best;
}

int main()
{
    CAN_TimingConfig cfg = calculate_can_timing(36000000, 500 * 1000);
    printf("Prescaler: %u\nBS1: %u\nBS2: %u\nSample: %.1f%%\nBaud error: %.4f%%\n",
           cfg.prescaler, cfg.bs1, cfg.bs2,
           cfg.sample_point * 100, cfg.baud_error * 100);
}

这个函数可以考虑放在dev_can.c中 给drv_can.c传参时只需要相应的分频值和两个bs的TQ数(默认SWJ 1TQ)

Describe your preferred solution

No response

Describe possible alternatives

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the existing CAN baud-rate tables and the CAN configuration flow in dev_can.c and drv_can.c. Check how prescaler, BS1, and BS2 values are passed to the driver, then define how the proposed calculation should work across supported chips. Done means a validated approach replaces or supplements the duplicated predefined parameters without breaking existing CAN configurations.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
embedded-iot
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.