关于CAN总线仲裁问题
) d% m& x, |; V! Z4 E1 {" N4 z0 O% I' K) ~5 F1. 硬件配置. M$ w$ b- g3 S$ t2 X9 V1 C+ e
单片机 stm32F412ret6% R3 \( v; G' i7 b3 c/ _6 I
CAN接口芯片 SN65HVD230DR% V: t" i0 g8 C: _
外部晶振 8M
8 O. |6 M( d5 [9 g, _2 l
5 h& x1 A* k& w2 芯片CAN初始化
0 t( s7 J( o4 }5 g Y& c/ d系统时钟配置使用cubeMX进行配置,按照最大时钟速度进行配置,can系统时钟频率为50MHz
6 E- |1 @8 E, l# n. x
# o2 v. z. w) f: S" o. _: ~重点:
$ `6 C; Q5 t! y5 E' y4 P1 u n之前can速率使用250kHz,两台设备对着发送数据,总线仲裁总是出现问题) X6 a: E! l; F$ K6 i
后来看过一篇MCP2517的文章9 _3 W& ?' k2 y' {3 h* S N( w
* O7 o' M6 b, J
9 C! c* v: V9 p, y2 N0 Z& m2 N1 N& L$ U& e* D% M7 J5 E
1 g8 V, o) X6 s这篇文章提到 1Mbps的仲裁比特率,8Mbps的数据比特率。" d; t+ Z1 ]+ M5 ~5 c
也就是说不是所有时钟都可以有仲裁功能,can时钟越低,总线仲裁成功率越高。
% E: s- `! f1 p* U+ }: C后来,我将stm32F4的can总线时钟改成125kHz,两台设备对着发送,数据就不会相互冲突0 H( y5 ?2 P9 d
3 q' }% t# |, q1 c( f
9 ]- p6 J# C7 G" p" J' e) K" N# F" e) d7 b. t
电平略高的是用TJF1051T/3的接口芯片发送的,连续发送3组数据
- h- L0 {( i; B8 k* o/ a' s* y电平略低的是用SN65HVD230DR的接口芯片发送的,连续发送3组数据4 l n* |5 ?) W7 A1 A
从波形上看,2对数据在can总线上,数据相互穿插,可以表明stm32f4芯片互相之间可以有效的进行仲裁- B' f& c, q! Q
7 l6 Q. n( d5 p1 ~- /* USER CODE END CAN1_Init 1 */
+ ?8 K5 T! j& ]+ g& l) z0 ^! C( } - hcan1.Instance = CAN1;
" I ~1 {3 D7 p' S J - hcan1.Init.Prescaler = 25;
. n* W' q" D+ @( z' S - hcan1.Init.Mode = CAN_MODE_NORMAL;6 j5 |5 H1 v7 k; {6 j# |
- hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;//CAN的时钟配置为 125kHz
L% c8 x( U4 C+ C7 n( @* p - hcan1.Init.TimeSeg1 = CAN_BS1_13TQ;
6 g0 c, I) z% h2 w0 A - hcan1.Init.TimeSeg2 = CAN_BS2_2TQ;
+ n/ X: l1 j% Q# e0 ~ - hcan1.Init.TimeTriggeredMode = DISABLE;//启用或禁用时间触发的通信模式* `1 Z/ I7 O. n1 t* A( @
- hcan1.Init.AutoBusOff = DISABLE;//总线自动关闭) V$ U, [8 m% _4 y" J$ k) `9 w- d4 G
- hcan1.Init.AutoWakeUp = DISABLE;//启用或禁用自动唤醒模式" U5 O; C' |2 I1 i7 k, E. \
- hcan1.Init.AutoRetransmission = ENABLE;//启动自动重传模式+ d+ K$ j- B5 i$ \9 N0 f& f
- hcan1.Init.ReceiveFifoLocked = DISABLE;//启用或禁用接收FIFO锁定模式5 n% D+ B0 q- Y9 z2 p+ T; @
- hcan1.Init.TransmitFifoPriority = DISABLE;//启用或禁用传输FIFO优先级; B2 D- c/ b& d
- if (HAL_CAN_Init(&hcan1) != HAL_OK)
6 Q. e' p/ x0 q# ^7 C) G - {
$ S& g% m6 H. |) C - Error_Handler();' u6 i2 f2 `4 f, g
- }
* X r# s( J( t: D' {+ H - /* USER CODE BEGIN CAN1_Init 2 */
! g$ J( k5 S* g2 x3 J2 T9 S2 x
复制代码
; m, r# H# i( J O. f" }) ?9 H4 u* x
& z* [5 \: ] d. A ~3. 启动总线错误中断
+ w$ ~' n2 A" \ m$ w/ u# D( I' e& k如果不启动总线错误中断,有可能出现错误,通过函数查不到相应的错误
( h; @/ @, H2 G6 z% v. j1 ^3 Q- HAL_CAN_ActivateNotification(&hcan1,CAN_IT_ERROR_WARNING);( M) s% `' S. a# \/ K% {' }7 `
- HAL_CAN_ActivateNotification(&hcan1,CAN_IT_ERROR_PASSIVE);
+ Q; p6 T' ?) ~5 C( _) \ g/ q- J - HAL_CAN_ActivateNotification(&hcan1,CAN_IT_BUSOFF);
& k/ y2 Z8 r$ b+ ^/ \ - HAL_CAN_ActivateNotification(&hcan1,CAN_IT_LAST_ERROR_CODE);
$ {8 P# u$ b! \ P6 t' v9 z) M; [ - HAL_CAN_ActivateNotification(&hcan1,CAN_IT_ERROR);, C+ b) S* Q* [7 h& G: [5 S
复制代码 9 y2 R' f$ F; M" \
4当总线出现故障后,系统内部复位错误,修复故障方法
. @2 H: t( B7 \- ]2 s3 \& [& V- bCANGetError = HAL_CAN_GetError(&hcan1);//查询can错误代码& q3 |7 i/ S* ~( g+ A3 V* X
- bCanGetState = HAL_CAN_GetState(&hcan1); + K3 c u4 U; D$ n3 P+ M
- if( bCANGetError!=0 ) //当系统出现错误,错误修复
% {, z/ k- F! u$ N0 i7 P* o - {0 L2 n) B8 G1 D/ J
- HAL_CAN_ResetError(&hcan1);0 t; B. w+ h' p. A, ]2 w/ u
- }
A% n. h) r! }. @
复制代码
- u1 }0 c+ R9 |/ [
* _- N" Z$ p/ P( V. ^; c5. 发送代码
- q$ m) I5 G1 n& x' Q- CAN_TxHeaderTypeDef TxHeader;//发送配置结构体2 l2 K V- ]7 M' j( q
- TxHeader.StdId = 0x121;//标准帧地址
0 @3 X4 o9 E5 C! m! k& U8 E - TxHeader.ExtId = 0x01;//扩展帧发送地址4 i2 Z0 h+ ]' q3 U
- TxHeader.RTR = CAN_RTR_DATA;//发送数据
/ S$ l/ _" j% j7 I$ J - TxHeader.IDE = CAN_ID_EXT;//扩展帧$ c% w( I6 U6 k% G) G) m. }0 H0 `& j
- TxHeader.DLC = 8;//发送8个字节数据* z0 M3 n: F/ ^. k
- TxHeader.TransmitGlobalTime = DISABLE; //启动时间戳 ENABLE DISABLE
% @% a. P8 k. F( E$ F$ [4 b
' }3 W3 E" q$ a2 g- for(;HAL_CAN_GetTxMailboxesFreeLevel(&hcan1)==0;);//检查发送邮箱是否有空闲
( c* g D- Y9 \4 @9 g6 b - TxHeader.ExtId = 0x100001;//扩展帧地址3 a7 t8 }3 s; U+ K
- bCAN_Tx = HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TxData, &TxMailbox);//发送
7 B' e5 w, e0 e$ H+ U - __nop();6 d% O5 D( w ]! ?
9 V5 G; Q6 r5 r% y" G- for(;HAL_CAN_GetTxMailboxesFreeLevel(&hcan1)==0;);//检查发送邮箱是否有空闲1 O! p4 g( w) M' m& l* c+ d) E5 }
- TxHeader.ExtId = 0x100002;//扩展帧地址9 d" W# E8 O! D3 f( b
- bCANGetError = HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TxData, &TxMailbox);//发送. D& a/ E9 x: G( ^, D
- __nop();
1 g" f) T* ^) J) |: |
: Y3 V) d' K+ N- for(;HAL_CAN_GetTxMailboxesFreeLevel(&hcan1)==0;);//检查发送邮箱是否有空闲
& |% ]+ i+ v: K8 o3 V2 @0 d - TxHeader.ExtId = 0x100003;//扩展帧地址
7 L0 |5 {; Q7 }7 w3 g - bCANGetError = HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TxData, &TxMailbox);//发送
& t6 N6 ~7 ?- T6 V7 l - __nop();
$ ]# P; ~. [7 ^! J# Q2 K
复制代码 # b7 E) G' V9 N* A- u
8 t T" P- T5 T" T. l4 ]; _
6. 关于can接口芯片的问题1 P4 j# c8 k3 e3 h- N9 p- W
当使用两种不同电压的接口芯片,会出现杂波
% D0 q q, C5 C0 L5 t9 m一种是TJF1051T/3的接口芯片,5v CAN接口芯片" n$ b7 W& _0 W/ f
一种是SN65HVD230DR的接口芯片,3.3v CAN接口芯片
+ b1 [) n' h6 c9 ]0 \4 K$ {3 Z$ D6 ]3 d, I P% O# U8 P
2 J `" ~0 j. Z0 x- P8 ]3 z$ F; I& |) v3 o2 q! E
当使用同一种接口芯片TJF1051T/3
" D3 v1 E; m' a% @
% i, w4 k( [' ^- ^5 `- J
8 D- a( I( n! O0 ?5 X ~9 G: ]9 V5 E/ ?- Z* {4 ?
从波形上看,杂波明显消失! r* R8 B7 a& [2 Q f5 f
虽然可以同时使用5v或者3.3v的can接口芯片,但是使用5v的接口芯片,杂波明显消失
4 O& T0 T8 m0 G1 d- p+ h( e: I————————————————/ j, k" {' ?; `
版权声明:xyang18
& q) }8 U7 i6 m: q* s# j0 j7 Q# D
. V/ f0 [+ t H4 r, h. b
+ a1 X* a$ L$ o+ q: d2 u4 V( }: i |