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

【经验分享】STM32 基于 Nucleo 板 CAN 总线的建立

[复制链接]
STMCU小助手 发布时间:2022-2-12 18:48
前言
; |- z- Y  G# P5 X1 U3 pSTM32 NUCLEO 开发平台是 ST 最新发布的易用性好、可扩展性佳的低成本平台。开发平台具有 mbed 功能支持 Arduino 接口,同时还提供 ST Morpho 扩展排针,可连接微控制器的所有周边外设,可以利用 Arduino 巨大生态系统优势,便于快速实现STM32 学习和评估! 这儿我们评估它的 CAN 外设功能。
# k! n" c( [# T! Y一、环境搭建
0 o; D2 _. C, a% I4 R. |1、软件:
' R5 Z, f, w- W8 PSTM32Cube\Repository\STM32Cube_FW_F1_V1.3.0\Projects\STM3210E_EVAL\Examples\CAN\CAN_Networking\EWARM
2 [7 ?, V) r9 y, {) t/ |& o2、硬件:9 H: J) e& Z, R9 }$ P2 Q9 ?
NUCLEO-F103RB(STM32F103RBT6)
9 e& s9 t) b' Y( m3、原理图如下:
8 E+ b, _+ Q, q0 m6 D
2 ?4 S/ G) b4 t2 y% g4 q9 q! v ZZ]5XV{X7BN4S[QE9CA1F6G.png / F* t1 |0 C3 J6 f9 O

% E( |& f; ?0 X) D  W上面原理图是针对 SN65HVD230 的,
' i: ~$ B7 C% z因为 PB8 是 CAN_TX,是 MCU 端的发送,需要到 CAN transfer 的输入引脚,即引脚 D(Driverinput);
! x9 z1 L; B" G- P* m* Q因为 PB9 是 CAN_RX,是 MCU 端的接收,是 CAN transfer 的输出引脚,即引脚 R(Recv output);! s+ N& S- J% r0 w7 H5 |

: c! ]: ~: K3 j5 L) h S)3(A{UFVJQQ0LKRP8PCBQ7.png * [: J8 n/ L; u7 R0 M9 I& M

+ N! P# M5 ]& |! g' L' I; @0 @二、Porting
" o. ~$ w) z% \- @6 ]由于参考的是 STM3210E_EVAL 的示例程序,在用到 STM32F103RBT6 的 Nucleo 板子上的时候,需要做一些 porting 的工; m3 y8 `/ h" m0 A1 }3 q- d0 N
作。
1 f  U9 F3 N8 [) `1 w7 [* u1、系统时钟
# O5 I6 l3 h0 u3 o4 d在 10E 的 EVAL 板子上,使用的是 HSE,而 Nucelo 上默认的是没有焊接 HSE,所以使用到的是 HIS;利用 CubeMX 生成代码:系统时钟为 36MHz;0 Q0 F9 B' Y, l/ z# n+ Y" N$ O

) V2 }' b0 i! F/ L 1A(AYMMZY%I4I11OE70N877.png / O/ Q! {0 Z; a8 R, O" E4 T& p

  F5 d* M1 ?& x  M% [供给 CAN 外设的时钟:是 APB1 的时钟 18MHz;
7 ]4 h: k1 e7 d4 B; C4 ^
  1. void SystemClock_Config(void)5 N8 [  P) `6 U8 j
  2. {" Q$ c# G* J# E" `: Q: U* p
  3. RCC_OscInitTypeDef RCC_OscInitStruct;7 [$ H  J9 {* x/ p' G; u* _0 W7 c
  4. RCC_ClkInitTypeDef RCC_ClkInitStruct;7 d0 r2 J5 n5 v' A
  5. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    : I: T$ b$ t# ~9 J6 E' y! h( {
  6. RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    9 B; ]& f* ]# K. t, ?6 F7 ~9 q
  7. RCC_OscInitStruct.HSICalibrationValue = 16;
    / ~  e! _  D! r
  8. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;- V1 E5 m, w5 H6 I/ O. C, e  A' {
  9. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;  M' R9 s. y3 E
  10. RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    7 D5 W! C8 S; H7 E$ c' ]( i
  11. HAL_RCC_OscConfig(&RCC_OscInitStruct);' e  |2 f, z/ N: O+ k( n+ E' I, g
  12. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    : w. P9 i# T! \/ l' F
  13. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    - e* w+ ?4 h) l/ T& i/ t
  14. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;! A6 r3 @( x: v, P: u# u
  15. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;4 Q- O  Q2 F6 J4 z. e% x* r( G
  16. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    + a% e1 J4 K" ?1 y2 S( \. O
  17. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;1 E0 E) q' Y" B4 A2 w6 L" I
  18. HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);+ R; a; d) m& H) S4 h
  19. HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
    8 I3 t4 D; l1 C. R4 L0 W
  20. HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
    9 b0 y# Z7 }% Z. U1 p+ g. \
  21. /* SysTick_IRQn interrupt configuration */
    . ?# W$ s( Y% }6 S" @' x# M
  22. HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);9 H- W$ ?# r# l( [  L6 p
  23. }
复制代码
; S6 O  t( ?( F7 Z$ F5 @0 `% {
2、CAN 的接收/发送引脚
' Q. s8 c6 J3 P; F5 b仍然可以都为 PB8 (TX) 和 PB9 (RX) ,不需要改变;( s1 q1 ?  L0 y. l- v
3、CAN 的波特率
3 o) O1 R! @, Z# J4 c9 z(自己想设置的是 500K):6 d! @( u- `6 I0 }

# H6 z0 r0 d5 @2 C$ [: Q$ U 3%]@KA5XRL8X0)BS8]@V.png " u# X* F# Y' f: F; s
) x! f# W' V& q6 s- J
@FK:Z$RE2V`4FI06OUD(X.png
$ s0 t7 z& b8 w. l
- H8 R) v8 H8 b; }) ~0 _
  1. CanHandle.Init.Mode = CAN_MODE_NORMAL;
    / ~0 z9 u; g" _; m; o/ _+ J7 @
  2. CanHandle.Init.SJW = CAN_SJW_1TQ;# M3 W& D2 W. W, ~
  3. CanHandle.Init.BS1 = CAN_BS1_3TQ; // TS1[3:0] + 1
    : L# }" ^$ u6 D: R$ P4 _% f0 [' Z: W
  4. CanHandle.Init.BS2 = CAN_BS2_5TQ; // TS2[2:0] + 1
    " n/ K: m+ {- J- }. Q9 m
  5. CanHandle.Init.Prescaler = 4; // BRP[9:0] + 1
    ; `3 @  b$ I, [/ G
  6. CanHandle.Init.NART = ENABLE;
复制代码
! q( h, O& w! i& d% }3 R8 s) A
所以,理论上,根据计算公式,
; X0 W0 @* ~3 lNominalBitTime = 1 × tq + tBS1 + tBS2 = (TS1[3:0] + 1 + TS2[2:0] + 1 + 1)* (BRP[9:0] + 1) x tPCLK;: y9 ?0 `. R5 t/ p% m7 b
所以,NominalBitTime = 9* 4* tPCLK; = Freq(APB1)/36 = 18/36 = 0.5MHz = 500K;, w& n6 \  c: l- f) ?
4、User 部分
# j/ R2 L  q8 }8 x' r6 {: I  h' {程序中设计到:
' }5 r8 i9 m8 `5 T/ u
  1. while (BSP_PB_GetState(BUTTON_KEY) != KEY_NOT_PRESSED)
复制代码

9 ]# }; C: }/ o7 l8 \. m在 10E-EVAL 板子上,用到的是 PG.08,而在 nucleo 上使用到的是 PC.13% `5 k% [6 F% o6 n
  1. #if 0; H! D1 U& t8 H' v
  2. #define KEY_BUTTON_PIN GPIO_PIN_8 /* PG.08*/2 b: @  C5 b. E0 _: }! v
  3. #define KEY_BUTTON_GPIO_PORT GPIOG
    + C0 A- Q$ z$ {* G; i( r+ t$ V
  4. #define KEY_BUTTON_GPIO_CLK_ENABLE() __HAL_RCC_GPIOG_CLK_ENABLE()
    % e+ n- V, c; N0 n
  5. #define KEY_BUTTON_GPIO_CLK_DISABLE() __HAL_RCC_GPIOG_CLK_DISABLE()
    4 C. P0 ?7 f( t) \: U9 M! d! ^
  6. #define KEY_BUTTON_EXTI_IRQn EXTI9_5_IRQn: }$ |, `% ]( s
  7. #endif
    3 S8 o4 O$ _8 K" t6 s# w. v; J
  8. #if 1
    % r# S4 J# ]6 Y% v
  9. #define KEY_BUTTON_PIN GPIO_PIN_13 /* PC.13*/  b, u( T  }) j' c
  10. #define KEY_BUTTON_GPIO_PORT GPIOC* x8 ?: ?0 ~. \+ \: J/ k: E
  11. #define KEY_BUTTON_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
    : g& X* n6 D. E- o
  12. #define KEY_BUTTON_GPIO_CLK_DISABLE() __HAL_RCC_GPIOC_CLK_DISABLE()
    . J# B7 {, R; I
  13. #define KEY_BUTTON_EXTI_IRQn EXTI15_10_IRQn
    3 r9 K, L+ ~- H
  14. #endif
复制代码

* W8 a( G7 c) v. s1 v, G9 ^4 F/ t RMDZ8MBAIQQD(NT`5EGYU.png
* G0 z( X$ ]7 X% I; }: b! p  Q
  s- S  m. y+ b' X" v至此,移植好了;
$ }0 j# b+ p, M
4 `. e7 I% ?6 j* Q1 }三、全速运行+ y+ @+ r1 C0 t) d0 f" h+ C7 q2 P* F
1、按下 USER Button,会发出 CAN 报文,CAN 的 PC 端软件能够收到。/ T4 }2 ^, j6 _5 U" X& {0 c% l

, Z! q' i7 w+ z  Y7 T7 b. F SH[I_1~IWL[]C98HQ59CY8S.png ( e- F8 M) f9 |7 L$ A. D! K% S# U

$ Y# L! @; ?0 E0 e" F* y& G2、CAN 的 PC 端软件发送报文,软件中的中断函数也会进入中断。$ s0 h4 Z4 M. J9 ]5 _3 T: O

$ w3 I3 s, l# A; d2 V$ M (3H6T$R@C`Q@~UH(_UCBE(O.png ; B6 {! r* \3 Z& @
  n  Y) v: s3 l5 O
说明,CAN 的发送和接收这一基本的操作已经完成了。对于 CAN 的复杂的运用特点,可以在该基础上进一步衍生。+ M  D$ W4 U+ m6 O
附录:5 C6 C. C- T8 Y, I6 q& [, s
1、针对现有的 CAN 的总线协议:在数据区域只有固定的 8Byte;也就是说一个 CAN 报文发送的数据只有 8 个,我们的单片机的寄存器也只提供了 8 个寄存器,符合当前的 CAN 的协议;如果客户想发送多个>8 的数据,需要在其上层协议中,用软件去多次发送。也许在下一代的 CAN 总线中,会对这一特点进行改变。
3 @( t% S7 `8 R' S& G, T3 A- Z/ e5 o/ O: k) z
SDWPZ(GFX74NPP]IX$SB~SW.png 9 z4 B, I1 L- P+ R. t5 G: ~4 M$ W
0 k0 a7 N' Z4 W3 {/ ?
2、CanHandle.Init.NART = ENABLE 的说明;9 y3 a4 [' _+ M5 n
在基于"STM32Cube_FW_F4_V1.10.0
+ k& ]0 d6 h0 G; {4 o$ l\Projects\STM324x9I_EVAL\Examples\CAN\CAN_Networking" , 如果只用一块 STM32F429-EVAL 调用HAL_CAN_Transmit()的发送函数,会发现 CAN Controller 会不断的发送数据, 这是因为在我们提供的示例中,是需要两块板子互联的,在 CAN 协议中,如果消息没有被正确的接收,它将会 be retransmitted infinitely by the transmitter until it will be acknowledged by the receiver ,而正我们的环境中,只有一块板子,而没有 receiver。* f3 M9 Q9 E; K( v& m. u

& @: ~1 |7 T) ]) B
赞 收藏 评论0 发布时间:2022-2-12 18:48

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版