你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
STMCU-管管 发布时间:2021-2-20 13:29
STM32F103 CAN通信波特率的计算方法
0 {# t; ^/ J7 y+ K
最近看一下CAN通信,翻出来之前做过的STM32 CAN通信的项目代码,有些概念比较模糊了,如波特率是怎么计算的。
( e' g/ {9 F( }# R1 F/ R$ x
: Q1 o6 z8 J( \/ ^1 Y4 Y
( y- U% z  e3 G( S& L0 t
最近接触rt-thread比较多,想把之前的CAN通信的代码,移植到RTOS上。( ~5 r6 T% t5 o" N# X7 ?

; r) _9 b' y3 t
: O0 X3 I) b2 ^# S; D( {' M
$ Q$ D: ]/ b' l! H2 \
CAN波特率$ b5 e' o. ~- k( K. J8 V6 ^
如果主机与从机,波特率不一致,很难正常的通信。8 o" C; a$ m! z% `
, m) D& Z7 |! R4 Q3 \4 P9 H
计算方法
, t' Z7 E( S. V) ~+ k( p
2 q- X3 T& s7 s1 \这里的500Kbps,是怎么计算出来的?/ D% ]3 H( J* G' }4 x$ m9 X
/*" F) q# ]0 f$ h0 B( t) \
* 函数名:CAN_Mode_Config" Q  m$ Z6 b/ l
* 描述  :CAN的模式 配置
2 M% ^8 P2 i( j/ `6 z" { * 输入  :无. ~* E' \$ @( N% v
* 输出  : 无4 v# `+ E) z, ]0 A; b
* 调用  :内部调用) {& C5 |3 \1 v6 T+ S5 E
*/
0 R9 T9 N6 S; S4 e! @static void CAN_Mode_Config(void)! `2 @+ e% ]$ ?8 M! M
{
& K; _' t, }0 Q/ P; ]2 a& W6 v! i7 E    CAN_InitTypeDef        CAN_InitStructure;
' c! A% Y) s9 K' P0 u6 \  q3 s    /************************ CAN通信参数设  *********************************/( |2 @% T( r0 M' N# E3 J
    /*CAN寄存器初始化*/
1 Q- _' _/ V- ]1 U    CAN_DeInit(CAN1);5 ~$ |5 h) c* k5 w& l5 K9 ~
    CAN_StructInit(&CAN_InitStructure);         /* CAN单元初始化 */4 q9 `! |& p, c2 Z
    CAN_InitStructure.CAN_TTCM=DISABLE;         //MCR-TTCM  关闭时间触发通信模式使能, s; x) f0 v* _( k
    CAN_InitStructure.CAN_ABOM=DISABLE;         //MCR-ABOM  自动离线管理 2 A2 F, [) A/ J$ L! L! k
    CAN_InitStructure.CAN_AWUM=DISABLE;         //MCR-AWUM  使用自动唤醒模式
5 {1 l: J! i6 L8 k    CAN_InitStructure.CAN_NART=ENABLE;          //MCR-NART  禁止报文自动重传 DISABLE-自动重传   ENABLE-不自动重传" ^8 X1 y7 Z1 r$ A
    CAN_InitStructure.CAN_RFLM=DISABLE;         //MCR-RFLM  接收FIFO 锁定模式 DISABLE-溢出时新报文会覆盖原有报文  0 _7 T9 D$ [. `
    CAN_InitStructure.CAN_TXFP=DISABLE;         //MCR-TXFP  发送FIFO优先级 DISABLE-优先级取决于报文标示符 % h3 C. V9 V* C) g( I+ v; q; ^
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;    //正常工作模式8 ?' z& s; `  k' e0 q
  q! P5 j& x2 ~# G
    /************************ CAN通信波特率设置 **********************************/0 U$ H2 s5 T. v) Z/ y6 R# S
    #if 0
  T; q* U, u* t5 U8 \, h    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳跃宽度 1个时间单元! C3 N. G( k7 O5 }% S! Y
    CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;      //BTR-TS1 时间段1 占用了5个时间单元
1 ^/ j( D' X; z5 K2 ^9 g    CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;      //BTR-TS1 时间段2 占用了3个时间单元/ x5 v! l/ ^$ B$ g1 a1 V' L4 J8 L
    CAN_InitStructure.CAN_Prescaler =4;         //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+5+3)/4=1Mbps
  u) h. [3 A1 @; J: ?; k    #endif; A9 l+ Y# l- ~2 i8 P. o7 z# ?( y4 ~
$ O- L5 W0 t4 H4 z8 m
    #if 0% R. l# x3 N! Q
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳跃宽度 1个时间单元
! x" l  M# _8 u9 b9 p    CAN_InitStructure.CAN_BS1=CAN_BS1_2tq;      //BTR-TS1 时间段1 占用了2个时间单元
) q( A5 L8 f9 k3 ]  G4 G+ K2 D    CAN_InitStructure.CAN_BS2=CAN_BS2_1tq;      //BTR-TS1 时间段2 占用了1个时间单元
9 B8 r! Y& W0 ]& N9 d5 P    CAN_InitStructure.CAN_Prescaler =9;         //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+2+1)/9=1Mbps. f" p6 O/ A6 ~! P" g, U6 t) M' m
    #endif
: e7 n1 p; E8 N, T3 z( J
0 P# E' G( [$ ^0 ~    #if 1
5 J- y$ i# _. m" w    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳跃宽度 1个时间单元
: @* x# m" P# ^, W# q1 d. ?# L+ q    CAN_InitStructure.CAN_BS1=CAN_BS1_2tq;      //BTR-TS1 时间段1 占用了2个时间单元
/ P$ c5 N3 }; r9 w4 ~* O5 x    CAN_InitStructure.CAN_BS2=CAN_BS2_1tq;      //BTR-TS1 时间段2 占用了1个时间单元
. U" @' E2 Z, K" d& c    CAN_InitStructure.CAN_Prescaler =18;        //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+2+1)/18=0.5Mbps
; d8 y, h  R7 B. D( d( H  [    #endif
& s  s- N- t! _- R9 s% |& x
9 Q3 @3 B8 ?& f4 R    #if 04 v2 y" t5 L$ d. Z
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳跃宽度 1个时间单元
8 [6 O9 c! ]1 _0 ^' D& @    CAN_InitStructure.CAN_BS1=CAN_BS1_3tq;      //BTR-TS1 时间段1 占用了2个时间单元4 V: E; k: ?) W; y( G
    CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;      //BTR-TS1 时间段2 占用了3个时间单元
8 J- N+ k3 q$ k" d- ~  g2 h' K. S, g    CAN_InitStructure.CAN_Prescaler =12;        //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+3+2)/12=0.5Mbps0 ^& ?/ e) I- Y3 a
    #endif
7 X* x8 O# v+ Y% g# G5 X
' ^, y' }2 H' @0 i $ y! _' v: z7 j% B) F9 ?
    #if 0
' {$ B: m) s! m7 R/ \6 N    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳跃宽度 1个时间单元4 }3 F: M" k& @% U; O
    CAN_InitStructure.CAN_BS1=CAN_BS1_7tq;      //BTR-TS1 时间段1 占用了7个时间单元" R/ ~6 `$ r2 y) Y
    CAN_InitStructure.CAN_BS2=CAN_BS2_4tq;      //BTR-TS1 时间段2 占用了4个时间单元
9 s4 Q3 r9 W) c$ T: ?, ~2 L$ F; B    CAN_InitStructure.CAN_Prescaler =6;         //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+7+4)/6=0.5Mbps
, V8 D: y6 f. U/ M6 d, ^- W    #endif
/ W& b) ?- z: B) }0 R# Y
6 P# T$ o6 Y- h0 }0 ^6 ?, r    #if 0
' J7 W8 i3 {2 D  q9 f2 r8 L    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳跃宽度 1个时间单元
  t5 l5 G( S: m4 D) S    CAN_InitStructure.CAN_BS1=CAN_BS1_13tq;     //BTR-TS1 时间段1 占用了13个时间单元) J1 P& y% I. |) w
    CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;      //BTR-TS1 时间段2 占用了2个时间单元- b* z- A+ s2 P, w  i3 Q
    CAN_InitStructure.CAN_Prescaler =9;         //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+13+2)/9=250Kbps
4 V3 L3 M5 `& B' _. Z    #endif, `- y2 n1 O0 n; ]6 h' K, b8 k' g
2 D' C& f+ Z" o$ m9 U
    #if 03 w3 R) g/ [7 s- z# l+ G
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳跃宽度 1个时间单元
4 A- M. f6 a8 c* {; N" d    CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;      //BTR-TS1 时间段1 占用了8个时间单元
! y+ z7 E2 B/ q$ k- e6 w- S    CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;      //BTR-TS1 时间段2 占用了7个时间单元
' F* Z# [2 F9 y2 Z    CAN_InitStructure.CAN_Prescaler =9;         //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+8+7)/9=250Kbps
. e. n- C+ y) s, _. i    #endif
& l; Q1 o' f  n6 d
( f# B+ {0 y/ |! ^  c2 Y0 _    #if 0
4 M, K( }' j' p2 ?3 X' [    if (CAN_Init(CAN1, &CAN_InitStructure) == CAN_InitStatus_Failed)/ T* s& q# U: _( f
    {: O$ ^! p! @5 h; O# {" h$ O$ P) e
        printf("Initialize CAN failed!\n\r");( I- X* ?2 S  Q: c  D6 D
    }6 [( v7 ?: B+ j
    else, L9 a& ~( r2 M, }
    {! h, ~& B+ R! p, l  D4 b8 h; q
        printf("Initialize CAN Success!\n\r");: w( \2 F3 ?+ K% k7 N9 n1 x9 ?
    }5 Q( R1 E( a- {& R
    #endif
) h& J) _+ Y& `  }/ T' m    CAN_Init(CAN1, &CAN_InitStructure);" e) ^3 _# E1 i9 x
}
通过查看STM32F103 的参考手册,找到了答案
1 a6 s4 |2 d3 y! @/ M
21.png
计算过程
: \2 J) w* D. p1 r
- J4 L0 D* |& N  h8 U8 L; \) d注意STM32 CAN 属于APB1总线,APB1总线,默认配置最大主频(36Mhz),而不是72Mhz。
5 C- B) |  T9 L0 y
22.png

  1. , H) E2 H$ @" U8 m% R
  2. 波特率 = 1 / 位时间* h! d, f* L! y- ]/ d* R/ n/ F
  3. ) Q) n; m5 L; ?+ C" G, I* |2 n
  4. 位时间 = (1*tq + tbs1 + tbs2),注意,这里与 CAN_SJW_1tq 无关!!, m) v/ {7 b. p6 {& D: }8 r- p2 K( F

  5. ) x7 w. d' R% {1 P
  6. 如果:tbs1 = 2 , tbs2 = 1,则:位时间 =  (1+2+1)tq = 4 tq。* C& g/ g5 @. c; q4 L( S
  7. ; |/ h/ y- T2 K8 K# m/ N+ Y
  8. 注意:这里,还有个分频, 分频分的不是主频(71MHz),是CAN总线的APB1 频率,手册上写着,36MHz,也就是 主频的2分频。
    & v+ u( ?! N0 Y/ D0 C  S: E  u4 J

  9. + H/ l0 m9 ^0 T' x; g3 ]6 R2 n3 U! o
  10. 系统默认初始化后,APB1总线频率,设置为 36MHz。
    + U; T1 o. F. ?; [0 @6 L2 }

  11. $ A1 s$ c: b- `( u& G2 n
  12. 这里CAN控制器,可以把APB1 继续分频,如 18,那么,CAN控制器频率:36Mhz / 18 = 2 Mhz。
    . D" P' S. L: l* b, M' Q4 {- H

  13. 1 X( \. ~1 M! E" [6 t7 z) `4 X# P: x
  14. 波特率:=  1 /  4 * (1/2Mhz) = 0.5Mhz = 500 Kbps
复制代码
总结
. ~/ B/ x4 q( ^5 R
- u" K* v- B) W6 h, E# ]( tCAN通信,是比较好用的串行总线,不仅用于汽车上,一些工业总线场合短距离的通信,也可以说使用。
7 r9 b, ]" ]- O2 j% p1 w" u1 J' @7 J5 v+ C* v
# y$ }: }7 F. r9 m4 f
CAN通信,波特率、滤波器设置,都需要清楚,才能真正用好。) i9 S& f# n" H9 ?' k  t# `5 i
2 l% Z$ g+ m- z+ B- _+ E

7 Z" J; E9 r) A3 I1 O: v
0 }+ V% b1 Z# Z( k% _8 l/ S- {
$ F, `/ z5 k' `8 F
收藏 1 评论1 发布时间:2021-2-20 13:29

举报

1个回答
小小超 回答时间:2021-2-20 13:41:30
谢谢分享!

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版