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

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

[复制链接]
STMCU小助手 发布时间:2022-2-12 18:48
前言  w/ }$ i, z; ]  W" P) P
STM32 NUCLEO 开发平台是 ST 最新发布的易用性好、可扩展性佳的低成本平台。开发平台具有 mbed 功能支持 Arduino 接口,同时还提供 ST Morpho 扩展排针,可连接微控制器的所有周边外设,可以利用 Arduino 巨大生态系统优势,便于快速实现STM32 学习和评估! 这儿我们评估它的 CAN 外设功能。
& e. j5 c! i9 ~# k( m5 W! I7 x4 |& q一、环境搭建
; T7 l$ h) N5 R8 U1 X7 o1、软件:$ L8 M5 [! O3 B1 g9 a( w
STM32Cube\Repository\STM32Cube_FW_F1_V1.3.0\Projects\STM3210E_EVAL\Examples\CAN\CAN_Networking\EWARM
" L: w! V1 |7 ?& N4 b- I$ V2、硬件:
. N/ N, ]! F; i8 Y3 `# J: d% UNUCLEO-F103RB(STM32F103RBT6)
* Y: F% h% l8 V1 A8 W3、原理图如下:/ g( O: F  e& r- S: Z; g( X
# z2 G% W5 T+ l9 W1 F
ZZ]5XV{X7BN4S[QE9CA1F6G.png
. ^' o; p  M8 |& J) O' V) _) r( A) N8 ^
上面原理图是针对 SN65HVD230 的,
4 s+ \+ S4 ^6 i9 p# e6 W: h% n, q因为 PB8 是 CAN_TX,是 MCU 端的发送,需要到 CAN transfer 的输入引脚,即引脚 D(Driverinput);
  @8 v% }3 d- Z) }" b! t- c因为 PB9 是 CAN_RX,是 MCU 端的接收,是 CAN transfer 的输出引脚,即引脚 R(Recv output);
. T# {( N7 T0 B3 A' [3 K  J% c/ b$ G& T" o" c  i% r8 B; @, p
S)3(A{UFVJQQ0LKRP8PCBQ7.png 7 [3 c: i+ \8 z: C- q
! `( E3 x. d7 O7 o# M7 X  t+ Y
二、Porting4 `% [) z- Z: a1 I4 f
由于参考的是 STM3210E_EVAL 的示例程序,在用到 STM32F103RBT6 的 Nucleo 板子上的时候,需要做一些 porting 的工
; _  o2 d# q& Q- ^2 w, ?& {! ^3 ]作。% t0 O& o: v, b1 b) M
1、系统时钟# f" z% l0 P9 v: T$ I/ ]% c4 c9 h
在 10E 的 EVAL 板子上,使用的是 HSE,而 Nucelo 上默认的是没有焊接 HSE,所以使用到的是 HIS;利用 CubeMX 生成代码:系统时钟为 36MHz;
. z1 N9 H& U2 s( m0 n  M: |# ]! W% c5 R( g$ n* D: [
1A(AYMMZY%I4I11OE70N877.png
8 ^$ |1 P8 c$ Y2 N. _  e6 Y/ ~0 C1 I7 Z/ ?) f! L. X2 ~
供给 CAN 外设的时钟:是 APB1 的时钟 18MHz;
$ D1 i2 O1 M5 `% ]2 r
  1. void SystemClock_Config(void)( o3 q1 w8 ]6 K" V7 V% l
  2. {" t/ }) c+ ^; w( a
  3. RCC_OscInitTypeDef RCC_OscInitStruct;
    ! \, I2 i: s+ a7 w1 R
  4. RCC_ClkInitTypeDef RCC_ClkInitStruct;8 E  z5 p/ F$ k5 m
  5. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;+ D9 |. o4 {! u1 N6 c5 s6 C$ y
  6. RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    4 K/ v  Z+ V8 Z* p" j. K* |, s: s
  7. RCC_OscInitStruct.HSICalibrationValue = 16;
    ) z. M3 O3 h6 J$ R6 a
  8. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;! Y/ w+ A/ R2 k( t% B9 I
  9. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
    : H" ^) P8 m7 r! n8 `: z
  10. RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    - h1 [8 c2 m( s) k3 e/ r1 h1 z
  11. HAL_RCC_OscConfig(&RCC_OscInitStruct);, H6 R; P6 p" {  ?8 S! G3 _
  12. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    # ~  N  n3 S; X" r% ^3 `/ F' @
  13. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    : `9 R2 E6 P- Q+ @' l
  14. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;6 C+ u- a& N& V
  15. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    1 `' M# [! ^3 w. ^, X
  16. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;  D5 z, G# f( u) U8 U
  17. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;7 K2 m5 v" r/ L# O
  18. HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);3 F1 Z7 n; c& {- R
  19. HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);0 R; R- b( W( b0 A! a4 \
  20. HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
    1 P7 m& c9 \. |# O" w9 X
  21. /* SysTick_IRQn interrupt configuration */
    " u4 b1 L, b4 n. ^' L% ]& \
  22. HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);0 M0 p* H' f. h& J# Y; Y$ K
  23. }
复制代码

6 C& p. U$ Z% m2、CAN 的接收/发送引脚
9 g) C+ M" @& ?' n% w- R仍然可以都为 PB8 (TX) 和 PB9 (RX) ,不需要改变;1 T0 u7 W3 W7 H, t5 G, x% V9 c
3、CAN 的波特率$ z( R9 U9 P6 ]* U+ w" g: H
(自己想设置的是 500K):6 C: z8 S9 h4 k' B+ X

" P: B5 D' d$ v1 H3 y 3%]@KA5XRL8X0)BS8]@V.png   T3 Q! D  C6 t' I3 C

( j( r# G" G% H) q, {. z5 c @FK:Z$RE2V`4FI06OUD(X.png 8 }- h1 D/ X8 }
# P- j0 b9 B5 a2 g% D9 e# W
  1. CanHandle.Init.Mode = CAN_MODE_NORMAL;8 i0 l. k2 G% K4 n% [3 k* E
  2. CanHandle.Init.SJW = CAN_SJW_1TQ;6 E9 s' L& V& B& O
  3. CanHandle.Init.BS1 = CAN_BS1_3TQ; // TS1[3:0] + 1- X$ u0 H/ T7 h( B+ S
  4. CanHandle.Init.BS2 = CAN_BS2_5TQ; // TS2[2:0] + 1
    + h" j" E7 n# y- y
  5. CanHandle.Init.Prescaler = 4; // BRP[9:0] + 1
    $ y1 o  E. `0 Y& w& |
  6. CanHandle.Init.NART = ENABLE;
复制代码

- G5 u2 N- K5 `* W1 P  O( ^, }8 w所以,理论上,根据计算公式,
6 g. ?; Y% S* w( h$ u- N9 XNominalBitTime = 1 × tq + tBS1 + tBS2 = (TS1[3:0] + 1 + TS2[2:0] + 1 + 1)* (BRP[9:0] + 1) x tPCLK;
0 c2 q! B7 j# P, k6 a9 Q( z所以,NominalBitTime = 9* 4* tPCLK; = Freq(APB1)/36 = 18/36 = 0.5MHz = 500K;
0 W) {5 J3 }) E6 O. l3 E4、User 部分
) h6 h& o5 S8 B& }2 @2 m. ^+ o+ }; N1 X程序中设计到:0 P; m' @) _  g
  1. while (BSP_PB_GetState(BUTTON_KEY) != KEY_NOT_PRESSED)
复制代码
9 |$ q8 E1 ^5 p4 W3 P* j  a& I
在 10E-EVAL 板子上,用到的是 PG.08,而在 nucleo 上使用到的是 PC.13' S& k8 p  Z# X
  1. #if 0
    * P" B( _# T6 h
  2. #define KEY_BUTTON_PIN GPIO_PIN_8 /* PG.08*/# F' h- ]0 g' @
  3. #define KEY_BUTTON_GPIO_PORT GPIOG
    9 t7 \$ X- W7 g
  4. #define KEY_BUTTON_GPIO_CLK_ENABLE() __HAL_RCC_GPIOG_CLK_ENABLE()- L. F7 j$ k: I$ X; {
  5. #define KEY_BUTTON_GPIO_CLK_DISABLE() __HAL_RCC_GPIOG_CLK_DISABLE()
    # n& D3 D2 k  R. z  I6 I  |  Q
  6. #define KEY_BUTTON_EXTI_IRQn EXTI9_5_IRQn% O' i1 I# v" H" J5 @7 S: o
  7. #endif
    # M" u; N7 \% n- Z6 m9 T
  8. #if 1
    ) i3 d! E. f; t' a. b5 h9 y
  9. #define KEY_BUTTON_PIN GPIO_PIN_13 /* PC.13*/
    5 @) z( j! \1 c  U( \
  10. #define KEY_BUTTON_GPIO_PORT GPIOC* X- j  T. m( e4 ~' V
  11. #define KEY_BUTTON_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()3 _" {' `" |1 \' G. N& S6 w
  12. #define KEY_BUTTON_GPIO_CLK_DISABLE() __HAL_RCC_GPIOC_CLK_DISABLE()
    6 s% _' L9 `/ k! C! s% p* |  I
  13. #define KEY_BUTTON_EXTI_IRQn EXTI15_10_IRQn
    1 _0 h, M, \" i9 X) w
  14. #endif
复制代码
& o7 [/ N: J, n% D8 e
RMDZ8MBAIQQD(NT`5EGYU.png 7 X( p" [8 `( R; `- j8 f/ j6 |

7 s9 P5 S# J" ~. M$ i8 G! a  R至此,移植好了;+ }. T; ?+ [2 ?  P
1 G+ a  J, {# v7 x4 r- m
三、全速运行
* b4 u; }: I4 P+ O, e- A: [1、按下 USER Button,会发出 CAN 报文,CAN 的 PC 端软件能够收到。
( H' T0 k' @" N7 {) S& J
6 q) H7 b  |& p5 |% }& ` SH[I_1~IWL[]C98HQ59CY8S.png $ ]# T2 J1 k0 l! n1 G& }8 X& L/ F
4 l6 g. k! j( D8 O* k2 ]! q1 y
2、CAN 的 PC 端软件发送报文,软件中的中断函数也会进入中断。
. j$ }3 ~" z, d5 f, t5 v0 S5 P) k
7 a4 z( V! k9 c: z+ k9 I; n6 I$ ] (3H6T$R@C`Q@~UH(_UCBE(O.png
/ J) Z4 @& D1 R3 ~7 g+ F/ I- m' R, Y$ F3 x
说明,CAN 的发送和接收这一基本的操作已经完成了。对于 CAN 的复杂的运用特点,可以在该基础上进一步衍生。( ^/ Z$ Y" N: u9 a
附录:
! @& X. t2 z  k; \6 u1、针对现有的 CAN 的总线协议:在数据区域只有固定的 8Byte;也就是说一个 CAN 报文发送的数据只有 8 个,我们的单片机的寄存器也只提供了 8 个寄存器,符合当前的 CAN 的协议;如果客户想发送多个>8 的数据,需要在其上层协议中,用软件去多次发送。也许在下一代的 CAN 总线中,会对这一特点进行改变。
1 R3 b, u% ^# H' ~1 r( U/ e! q$ c" B1 {9 J
SDWPZ(GFX74NPP]IX$SB~SW.png , s8 l* o5 |8 O0 j$ A$ _6 _
/ ?+ j3 q+ C( c. F* b! M4 k
2、CanHandle.Init.NART = ENABLE 的说明;" \8 D8 w. g; [8 }8 O/ a
在基于"STM32Cube_FW_F4_V1.10.0
5 U5 O- X* [4 x  _5 a2 E1 U$ o* }\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。
( N4 d( H( E9 ~  \. B! Q* \; W
) o3 I! |2 ^" a, W$ q) p0 t" Z; J3 D
收藏 评论0 发布时间:2022-2-12 18:48

举报

0个回答

所属标签

相似分享

官网相关资源

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