STM32F103 CAN通信波特率的計算方法


前言

  • 以下的波特率計算和實例僅針對 STM32F1系列
  • 最近看一下CAN通信,翻出來之前做過的STM32 CAN通信的項目代碼,有些概念比較模糊了,如波特率是怎么計算的。
  • 最近接觸rt-thread比較多,想把之前的CAN通信的代碼,移植到RTOS上。

CAN波特率

如果主機與從機,波特率不一致,很難正常的通信。

/*
 * 函數名:CAN_Mode_Config
 * 描述  :CAN的模式 配置
 * 輸入  :無
 * 輸出  : 無
 * 調用  :內部調用
 */
static void CAN_Mode_Config(void)
{
    CAN_InitTypeDef        CAN_InitStructure;
    /************************ CAN通信參數設  *********************************/
    /*CAN寄存器初始化*/
    CAN_DeInit(CAN1);
    CAN_StructInit(&CAN_InitStructure);         /* CAN單元初始化 */
    CAN_InitStructure.CAN_TTCM=DISABLE;         //MCR-TTCM  關閉時間觸發通信模式使能
    CAN_InitStructure.CAN_ABOM=DISABLE;         //MCR-ABOM  自動離線管理 
    CAN_InitStructure.CAN_AWUM=DISABLE;         //MCR-AWUM  使用自動喚醒模式
    CAN_InitStructure.CAN_NART=ENABLE;          //MCR-NART  禁止報文自動重傳 DISABLE-自動重傳   ENABLE-不自動重傳
    CAN_InitStructure.CAN_RFLM=DISABLE;         //MCR-RFLM  接收FIFO 鎖定模式 DISABLE-溢出時新報文會覆蓋原有報文  
    CAN_InitStructure.CAN_TXFP=DISABLE;         //MCR-TXFP  發送FIFO優先級 DISABLE-優先級取決於報文標示符 
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;  	//正常工作模式
 
    /************************ CAN通信波特率設置 **********************************/
    #if 0
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳躍寬度 1個時間單元
    CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;      //BTR-TS1 時間段1 占用了5個時間單元
    CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;      //BTR-TS1 時間段2 占用了3個時間單元
    CAN_InitStructure.CAN_Prescaler =4;         //BTR-BRP 波特率分頻器  定義了時間單元的時間長度 36/(1+5+3)/4=1Mbps
    #endif
 
    #if 0
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳躍寬度 1個時間單元
    CAN_InitStructure.CAN_BS1=CAN_BS1_2tq;      //BTR-TS1 時間段1 占用了2個時間單元
    CAN_InitStructure.CAN_BS2=CAN_BS2_1tq;      //BTR-TS1 時間段2 占用了1個時間單元
    CAN_InitStructure.CAN_Prescaler =9;         //BTR-BRP 波特率分頻器  定義了時間單元的時間長度 36/(1+2+1)/9=1Mbps
    #endif
 
    #if 1
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳躍寬度 1個時間單元
    CAN_InitStructure.CAN_BS1=CAN_BS1_2tq;      //BTR-TS1 時間段1 占用了2個時間單元
    CAN_InitStructure.CAN_BS2=CAN_BS2_1tq;      //BTR-TS1 時間段2 占用了1個時間單元
    CAN_InitStructure.CAN_Prescaler =18;        //BTR-BRP 波特率分頻器  定義了時間單元的時間長度 36/(1+2+1)/18=0.5Mbps
    #endif
 
    #if 0
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳躍寬度 1個時間單元
    CAN_InitStructure.CAN_BS1=CAN_BS1_3tq;      //BTR-TS1 時間段1 占用了2個時間單元
    CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;      //BTR-TS1 時間段2 占用了3個時間單元
    CAN_InitStructure.CAN_Prescaler =12;        //BTR-BRP 波特率分頻器  定義了時間單元的時間長度 36/(1+3+2)/12=0.5Mbps
    #endif
 
 
    #if 0
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳躍寬度 1個時間單元
    CAN_InitStructure.CAN_BS1=CAN_BS1_7tq;      //BTR-TS1 時間段1 占用了7個時間單元
    CAN_InitStructure.CAN_BS2=CAN_BS2_4tq;      //BTR-TS1 時間段2 占用了4個時間單元
    CAN_InitStructure.CAN_Prescaler =6;         //BTR-BRP 波特率分頻器  定義了時間單元的時間長度 36/(1+7+4)/6=0.5Mbps
    #endif
 
    #if 0
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳躍寬度 1個時間單元
    CAN_InitStructure.CAN_BS1=CAN_BS1_13tq;     //BTR-TS1 時間段1 占用了13個時間單元
    CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;      //BTR-TS1 時間段2 占用了2個時間單元
    CAN_InitStructure.CAN_Prescaler =9;         //BTR-BRP 波特率分頻器  定義了時間單元的時間長度 36/(1+13+2)/9=250Kbps
    #endif
 
    #if 0
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳躍寬度 1個時間單元
    CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;      //BTR-TS1 時間段1 占用了8個時間單元
    CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;      //BTR-TS1 時間段2 占用了7個時間單元
    CAN_InitStructure.CAN_Prescaler =9;         //BTR-BRP 波特率分頻器  定義了時間單元的時間長度 36/(1+8+7)/9=250Kbps
    #endif
 
    #if 0
    if (CAN_Init(CAN1, &CAN_InitStructure) == CAN_InitStatus_Failed)
    {
        printf("Initialize CAN failed!\n\r");
    }
    else
    {
        printf("Initialize CAN Success!\n\r");
    }
    #endif
    CAN_Init(CAN1, &CAN_InitStructure);
}

計算方法

這里的500Kbps,是怎么計算出來的?

    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳躍寬度 1個時間單元
    CAN_InitStructure.CAN_BS1=CAN_BS1_2tq;      //BTR-TS1 時間段1 占用了2個時間單元
    CAN_InitStructure.CAN_BS2=CAN_BS2_1tq;      //BTR-TS1 時間段2 占用了1個時間單元
    CAN_InitStructure.CAN_Prescaler =18;        //BTR-BRP 波特率分頻器  定義了時間單元的時間長度 36/(1+2+1)/18=0.5Mbps

通過查看STM32F103 的參考手冊,找到了答案

計算過程

注意STM32 CAN 屬於APB1總線,APB1總線,默認配置最大主頻(36Mhz),而不是72Mhz。

 
位時間 = (1*tq + tbs1 + tbs2),注意,這里與 CAN_SJW_1tq 無關!!
 
如果:tbs1 = 2 , tbs2 = 1,則: 位時間 =  (1+2+1)tq = 4 tq。
 
注意:這里,還有個分頻, 分頻分的不是主頻(71MHz),是CAN總線的APB1 頻率,手冊上寫着,36MHz,也就是 主頻的2分頻。
 
系統默認初始化后,APB1總線頻率,設置為 36MHz。
 
這里CAN控制器,可以把APB1 繼續分頻,如 18,那么,CAN控制器頻率:36Mhz / 18 = 2 Mhz。
 
波特率: =  1 /  4 * (1/2Mhz) = 0.5Mhz = 500 Kbps

總結

CAN通信,是比較好用的串行總線,不僅用於汽車上,一些工業總線場合短距離的通信,也可以說使用。

CAN通信,波特率、濾波器設置,都需要清楚,才能真正用好。

文章轉載自並進行了部分修改: 轉載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM