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

STM32 CAN总线调试的一点心得总结

[复制链接]
aimejia 发布时间:2018-6-1 13:47
本帖最后由 aimejia 于 2018-6-1 13:49 编辑 . K" Z, s4 T: ~7 f
2 a2 h4 I2 _2 A
一. 开发平台与工具:
0 P, [5 x" ]* ]$ j! D" X* K1 W7 F6 C1 k; X( F, G+ C. U: Z! B8 A
1. 平台: STM32F103C8T6  48PIN工控板和自己设计的STM32开发板  v: h) a+ f0 A( n/ D

- ]2 S0 i0 s  T3 k2. 软件: MDK5 UVision V5.14.0.03 m- }: [" n/ M) P0 k) m5 z9 K
7 {* Z% _' }) g' r- J1 `5 Z$ b
3. PACK: STM32F1xx_DFP——1.0.5(2014-03-14)
! }1 C& r, K8 z4 a* }
  j" O: s7 g' e/ W. y4. 其它:USB转串口,ST-Link下载器,
( h8 o1 w$ M1 ^  `
8 C3 B# w$ K7 `2 M; z' g  NUSB-CAN Adapter用于直接监视CAN口发出的数据,上位机有两个,一个是EmbededConfig for USB2CAN 配置串口、串口波特率、CAN速率等,另一个是EmbededDebug V2.0监视CAN口数据;使用顺序是先配置后查看CAN数据。
, O/ [  F; @6 ~
! f/ f- Q7 |5 }# h! ^: h0 D( w二. CAN总线的介绍简略:- f$ B  P  M; I3 ~' g" [# m% z/ j
) w/ T* T  S9 D) ^6 M
bxCAN 是基本扩展 CAN (Basic Extended CAN) 的缩写,它支持 CAN 协议 2.0A 和 2.0B 。它的设计目标是,以最小的 CPU 负荷来高效处理大量收到的报文。它也支持报文发送的优先级要求(优先级特性可软件配置)。5 z+ c. Q& A1 {! @" W

" N- l9 w6 F3 O: H# i7 k对于安全紧要的应用,bxCAN 提供所有支持时间触发通信模式所需的硬件功能。5 f. q& E2 V* U1 ?5 q1 A

) U( `8 H) Q* u' v4 H% x* W3 ]# |( y主要特点
- h$ h, v: ~. ~" B· 支持 CAN 协议 2.0A 和 2.0B 主动模式2 [6 j( ^0 e4 \+ m& K# V
· 波特率最高可达 1 兆位 / 秒
% O" G; @, K9 x% U8 P· 支持时间触发通信功能
' `# H5 e2 Y0 _0 F, ~/ F
5 l4 s+ o5 |- b2 s发送
& P& o0 ~' K3 D) q6 x/ b. [* `4 m· 3 个发送邮箱
& n; L$ }/ g% o8 p0 m· 发送报文的优先级特性可软件配置
% q. I# A+ J! R5 v· 记录发送 SOF 时刻的时间戳" y1 X: ]) F8 F7 g' n
1 ~7 I0 `& W# [
接收
, i( f1 Y* ^8 V· 3 级深度的2个接收 FIFO+ ]* f! c: @8 v2 u
· 14 个位宽可变的过滤器组 - 由整个 CAN 共享
' Q1 _: s, s+ J2 N· 标识符列表' t3 d; S: N+ |. ]
· FIFO 溢出处理方式可配置
4 C( e+ Q! u4 ~· 记录接收 SOF 时刻的时间戳
( a- w' B" r5 p* X1 P
9 f7 O7 K$ M( t3 Z) i. d" g4 L3 W0 _0 _可支持时间触发通信模式
1 g( F9 R# ]" v! O4 n· 禁止自动重传模式
  y: i) `2 S" O+ E1 w· 16 位自由运行定时器+ C# G+ l4 M4 t/ }* U, ^
· 定时器分辨率可配置
5 e4 b% S; B. Y- @( O2 t# v· 可在最后 2 个数据字节发送时间戳. [$ j) M1 u7 S' D

* l) K$ t- z* S. u! }% X( ^* w管理0 o" N7 k0 j1 a* w1 a% |% ]$ U
· 中断可屏蔽
+ Z, t% n6 ~- _' y· 邮箱占用单独 1 块地址空间,便于提高软件效率
, o, \, |$ {- l. f4 _2 h  m" n3 V/ y
更多STM32 CAN总线介绍详见:STM32中文参考手册_V10.pdf 或 STM32F10XXX-RM0008 Reference Manual 英文版8 P) U& \& v6 u7 {  t3 v

$ Y; b* N/ p0 t% Z三. 遇到的问题分析与解决:/ V5 x+ e; b* Z& ~; Y5 u0 L
* _0 v9 N' }6 k
手上有两块STM32的板子,一个是网上买的MINI STM32工控板,另一个是自己公司设计的板子。二者有所不同,大致有两点,第一是串口,工控板用的是USART1 且用的是GPIO PA9(TX)和PA10(RX),自设板用的是USART2 且用的是GPIO PA2(TX)和PA3(RX);第二是CAN口管脚不同,工控板用的是复用功能映射到PB8(RX)和PB9(TX),而自设板用的是PA11(RX)和PA12(TX)。下图所示,两块板子部分原理图:) d, o" s. {1 H7 G" K  M

3 j) Y. o5 B8 \4 C0 ]工控板
* W( A/ {9 n5 w- m, M8 w, Z( y. J# F
1.jpg

4 V: j& k1 M7 E, y/ g自设板' R  D1 ~7 J  a, P! W
" N6 u0 e# w0 R- l* t* H0 t
2.jpg

7 `, a, d, Y) z现在我是在工控板测试代码基础上,用到自设板上,实现PC端串口与STM32 CAN双向通信,要做的是将USART和CAN口的GPIO配置对应到自设板上。: j1 t+ `, O! G3 W5 Q! X" J
. c/ l4 X5 u3 X# F6 }& n; m
首先,串口GPIO配置:
) k$ I9 p, s# y" l" P6 E6 ~0 c& t
( q) l* f/ i8 t" x+ t工控板1 P3 ~% N: e, m6 D' `# M/ V
  1. [objc] view plain copy
    ! P9 t+ J) e: r0 W
  2. void USART1_Config(void)  . k9 [! r* G" T4 f+ g! I
  3. {  $ h8 E1 A2 s3 @/ x$ I% K. b1 e
  4.     GPIO_InitTypeDef GPIO_InitStructure;  
    ! {) |5 ^3 z8 j9 B
  5.     USART_InitTypeDef USART_InitStructure;  
    9 q" j+ }/ V% X
  6.   
    9 k3 q# e# O1 a9 k6 U
  7.     /* config USART1 clock */  
    ' w& d) `* m+ }! c/ A( L" F  W
  8.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);  0 f2 [% c# M' R* [1 _( R5 b, W
  9.       % Q2 U% x8 ]2 `+ p8 |9 R
  10.     /* USART1 GPIO config */  
    6 I! ~- y, |2 b4 H3 u% l# Y6 `
  11.    /* Configure USART1 Tx (PA.09) as alternate function push-pull */  
    7 U% f0 K, o) Q4 K
  12.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  
    - `3 K* b* k6 X: m; ]- r$ O$ _
  13.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  & r$ j* ]- n7 n: ]$ u% j$ b
  14.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  % |# [* a' A$ i9 L- D# V0 D
  15.   GPIO_Init(GPIOA, &GPIO_InitStructure);      
    8 i' }% q5 H1 J: C
  16.   /* Configure USART1 Rx (PA.10) as input floating */  
      S9 k# I% b6 ?4 u6 E
  17.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  
    / D/ q% L# G* D* a7 Q6 @
  18.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
    & C$ g$ s7 M) [8 F
  19.   GPIO_Init(GPIOA, &GPIO_InitStructure);  
    9 B: @: I( x1 W% @8 H
  20.         , y; `8 E( h' m4 j& T1 p7 Z- j
  21.     /* USART1 mode config */  
    ' L" u+ _/ K/ Q9 _
  22.     USART_InitStructure.USART_BaudRate = 115200;  
    : Z4 n% ^0 w1 @% ]- s2 M
  23.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  5 _; ^2 X2 {4 e9 l
  24.     USART_InitStructure.USART_StopBits = USART_StopBits_1;  
    . L6 k& U& W2 O) \$ k
  25.     USART_InitStructure.USART_Parity = USART_Parity_No ;  % ]7 _5 N" m( ], o) }; I
  26.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  
    3 L: H) Z6 P! e
  27.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  
    / k- n7 \5 b5 x  z0 g5 ]# `4 E) x3 Z
  28.     USART_Init(USART1, &USART_InitStructure);   ! m- \( o. \2 J; n  ]
  29.   USART_Cmd(USART1, ENABLE);  
    % @. q" X0 `+ i" [2 L) R9 G
  30.       ( f# s/ v# z8 c- u* {$ V1 b
  31.     /* Enable the EVAL_COM1 Transmit interrupt: this interrupt is generated when the  
    ( {; i% E2 L* V% M5 \$ w
  32.      EVAL_COM1 transmit data register is empty */    7 d" k' u& @- A6 W
  33.   //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);    ^0 Q0 |" Y& t( G2 i4 c
  34.   
    - \+ P9 Y; l+ f* e7 a3 W) F
  35.   /* Enable the EVAL_COM1 Receive interrupt: this interrupt is generated when the  
    , c" h$ |- p5 j7 e
  36.      EVAL_COM1 receive data register is not empty */  7 ?% }- W' }. \/ Q# }3 U% B
  37.   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  
    % A- z5 a$ u) h
  38. }  * r/ [; `. W3 H4 [
  39.   
    4 g2 @1 }: J1 Y6 @% ^9 S$ t
  40. /***************USART1 ÅäÖÃÖжϷ½Ê½·¢ËͽÓÊÕÊý¾Ý******************************/  + u! `3 T: R6 [( C* S* c  K- b2 A& d
  41. void USART1_NVIC_Configuration(void)  
    0 j8 ^1 Y  m# G+ P/ K! b
  42. {  + n2 n- V0 u" Q$ @
  43.   NVIC_InitTypeDef NVIC_InitStructure;  
    & f; f0 b; t9 K7 G- l: J0 u
  44.   
    7 M( |5 X5 w; L8 a- U; P4 H
  45.   /* Enable the USARTx Interrupt */  ! X! U9 ~9 o) c
  46.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  # B  T" I  a" o3 j2 C$ f, H
  47.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
    1 N: |' [& y+ q4 z. l
  48.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  " S6 Y9 t0 e0 a- ^
  49.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    % _1 E) g" s4 S, w7 g9 \! y3 K7 f
  50.   NVIC_Init(&NVIC_InitStructure);  
    5 @' L% a  H4 }: S% E
  51. }  
    ) |9 S$ |" [# c+ e! X
  52.   2 \+ z( l) y$ B
  53. /****************USART1 ÖжϺ¯Êý***************************/  
    & G7 v3 r% e. i) D& X% `
  54. void USART1_IRQHandler(void)  
    ; p0 W0 [% d: x* G$ |/ I  l" ~
  55. {  # G8 X: f1 h6 }  N" {9 |2 S! E
  56.     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  
    ! R7 k0 |+ |# S0 j
  57.     {  
    * M5 A& t; X  T2 |% |
  58.         RxBuffer[RxCounter++] = (USART_ReceiveData(USART1));  . J$ _1 I. R- a9 N# Q3 j1 ^
  59.     }  : ]7 Q+ I( T' P
  60. }  
复制代码
USART1_Config()用于USART1的GPIO配置,配置到
2 k% N/ i; C; Q4 n *          | PA9  - USART1(Tx)      |* o7 ?  N$ K# a4 M2 {# Z: b; s  n
*          | PA10 - USART1(Rx)      |1 g3 D. z2 C0 o6 r3 n! @
*           ------------------------. e, d6 m. o0 V; p$ w: F# [
USART1_NVIC_Configuration() 用于USART1设置中断方式接受发送数据
: [: l9 b2 f; N& F* l% H; l2 P3 I1 B3 j9 B" X
USART1_IRQHandler()用于USART1中断接受函数: j) b$ D9 D) N  n# y* [
4 ~4 K  \2 a6 }5 _" u6 l( A
自设板: D' I# }9 _& h; y
  1. [objc] view plain copy
    ( W* n2 o2 n' p0 J& Q6 T3 C# ~
  2. void USART2_Config(void)  , c2 |! X- ~: m3 Z
  3. {  0 P, D9 X, c: @7 _, }) l$ z
  4.     GPIO_InitTypeDef GPIO_InitStructure;  
    ! T& ?& \# t# F' }. t$ h" x
  5.     USART_InitTypeDef USART_InitStructure;  
    - I0 W5 C' e- ^7 z: W( O( Y/ Q
  6.   0 b( e' _2 I- V4 m/ B
  7.     /* config USART2 clock */  7 X, E" F" @! A. Y* |+ }. y
  8.     //RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);  7 Q# J- Y7 v# C, O6 X; p
  9.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 , ENABLE);  5 l8 A, ~5 r" S$ Y
  10.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  
    3 s. f* u8 T4 Z2 k; M
  11.       
    4 d# P- E( A1 M
  12.     /* USART2 GPIO config */  
    9 ^' S! ]  m; m4 X/ l  ~1 v7 u& G
  13.    /* Configure USART2 Tx (PA.02) as alternate function push-pull */  
    * v; r9 a3 v* U8 G$ M, G3 E4 x
  14.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;  8 i! J6 B- f+ p, x2 l. `* C) B
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  % A1 b$ m7 ]  }- Y
  16.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    , X* M4 L6 |: d7 b( ~: ~% Y9 H
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);      / |/ v9 ?* s6 D3 D& r1 y3 v
  18.   /* Configure USART2 Rx (PA.03) as input floating */  
    ; w- M, r2 h0 q: @$ M
  19.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;  ; ~( i$ ]/ J8 Q3 _9 w
  20.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  ; M, ]5 \, ]1 @
  21.   GPIO_Init(GPIOA, &GPIO_InitStructure);  
    ) P9 v( |' L* ~: h/ R
  22.         
    ) h4 k. A/ P' a' Q9 S
  23.     /* USART2 mode config */  
    7 N& o2 }3 L% W' q
  24.     USART_InitStructure.USART_BaudRate = 115200;  ' U' s0 @8 E1 q( G8 ?" u
  25.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  
    ! t# l$ p3 O; @* N' Q
  26.     USART_InitStructure.USART_StopBits = USART_StopBits_1;    L' z$ S$ L6 s% {
  27.     USART_InitStructure.USART_Parity = USART_Parity_No ;  # [. j2 [+ L) M0 c) u( l
  28.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  
    8 r4 {( S0 Y% h! I7 ]% b# q3 F
  29.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  
    , O) Z$ K8 r% P& P
  30.     USART_Init(USART2, &USART_InitStructure);  
    1 k' o. h- N. _/ @0 ]
  31.     USART_Cmd(USART2, ENABLE);  6 Y8 u- Q0 x$ r$ f7 s, Q
  32.       
      {# u/ T) h3 ^5 C' t
  33.     /* Enable the EVAL_COM1 Transmit interrupt: this interrupt is generated when the  
    : X  M/ i6 z3 L; ?
  34.      EVAL_COM1 transmit data register is empty */   
    ) U0 d5 Z. D% f% I; @+ B+ `
  35.   //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);  
    , f1 \/ K& V! S- r
  36.   
    ' M  s- K/ V- v6 a! ~4 p4 }
  37.   /* Enable the EVAL_COM1 Receive interrupt: this interrupt is generated when the  
    3 G" @/ g1 q& k
  38.      EVAL_COM1 receive data register is not empty */  8 M: O0 B7 U$ L; F* x
  39.   //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  
    ( l& D/ p$ L/ W# Q
  40.     USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);  - g- A0 ~6 l8 u  J, B8 i
  41. }  9 Z) G$ k/ a9 \% Z# E* U
  42.   % I6 q' m1 ?3 p, W: t! x; O
  43.   4 b$ A4 C0 ^9 i) S! [! p7 D+ R# G
  44. /***************USART2 ÅäÖÃÖжϷ½Ê½·¢ËͽÓÊÕÊý¾Ý******************************/  * U" C6 t$ H( W  p9 A
  45. void USART2_NVIC_Configuration(void)  
    ' c; @5 s0 }( b. [' X
  46. {  * A# b' T5 ~/ z
  47.   NVIC_InitTypeDef NVIC_InitStructure;  # z$ M9 B' P; Z5 P- l
  48.   . A5 d2 X1 m, F) R$ X
  49.   /* Enable the USARTx Interrupt */  
    : R3 O8 q( y7 P0 ~
  50.   NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;    \$ T- A& L# m  |" [0 m0 Z" L' |
  51.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
    % r. ^, b6 ?, i; L# E
  52.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
    0 e: s; X. T! k3 P1 {' m- {8 h
  53.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    l2 M3 _+ w  N: z$ y- A
  54.   NVIC_Init(&NVIC_InitStructure);  
    + u& e1 y' J3 W5 r$ Y3 E4 f
  55. }  7 Y3 S& R$ V; t0 }1 k+ S
  56.   , \* J+ w4 ?; x
  57. /****************USART2 ÖжϺ¯Êý***************************/  
    ) H# N& C( E* H% N9 c# d
  58. void USART2_IRQHandler(void)  1 P3 Q6 }% b/ B2 h
  59. {  
    1 d, i( c6 t+ X5 m1 _/ ~
  60.     if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  - G' Y/ D' E7 s. p, x
  61.     {  / n4 ~3 v$ j) H7 t0 K3 E: W( r5 K
  62.         RxBuffer[RxCounter++] = (USART_ReceiveData(USART2));  
    ' Y: {1 ]' @$ f% i
  63.     }  
    , n$ |! W% G/ X% g5 ?5 Y/ E4 k
  64. }  
复制代码
USART2_Config()用于USART2的GPIO配置,配置到& y2 U0 R" W$ a9 W$ S- [3 b
*          | PA2  - USART2(Tx)      |
% a1 O+ v( A! Q! k# J *          | PA3 - USART2(Rx)      |
7 A8 N: z/ U% ^  x' u *           ------------------------  ~: @6 C' W- l, @. T( y

6 ]" o* D1 J( B  ZUSART2_NVIC_Configuration() 用于USART2设置中断方式接受发送数据& L! Y  R1 ]* u, O/ n! b/ _: Q

% m+ U# o, X3 ^9 i4 d) [USART2_IRQHandler()用于USART2中断接受函数7 S1 O# x# v( E; V' s
# @0 {  h) F# D% _0 e2 y
然后,配置CAN口GPIO4 f- b. O; t" J. M+ M" `
, m; d5 O7 n& j- S
工控板
4 y9 o) P! u; _! ?8 T4 l  {% e
  1. [objc] view plain copy' v, i' F& V$ e# T' J. m+ n
  2. /*CAN GPIO ºÍʱÖÓÅäÖà */  * T! t9 E  u) c$ e
  3. void CAN_GPIO_Config(void)  
    & I9 O; S8 K1 T" v8 z
  4. {  
    * H4 |* p3 O! w+ H: Q6 R
  5.   GPIO_InitTypeDef GPIO_InitStructure;   
    0 d% j. K5 N$ e3 v4 I7 [! ]; G, G$ z3 _9 {. N
  6.   /* ¸´Óù¦ÄܺÍGPIOB¶Ë¿ÚʱÖÓʹÄÜ*/     
    . V- L* U  Y- R8 h* X
  7.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);                                                                          & w" c" n1 |- S' F8 _/ k! e- w
  8.   
    0 T" b" {0 _* n2 a  W
  9.   /* CAN1 Ä£¿éʱÖÓʹÄÜ */  
    1 |6 g0 x( @. ~% y- y
  10.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);   
    2 ^' F& _% j( _* U
  11.   / {# O# \' I( x8 q" w
  12.   /* Configure CAN pin: RX */    // PB8  
    : h; r- ^) b. E/ d
  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;  5 }% Q% b5 i& \; _4 g7 `+ O
  14.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  ! R$ v+ G; [7 o+ T- O! z2 V+ O8 m
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  // ÉÏÀ­ÊäÈë  
    2 A1 {' E! L1 V# U1 K3 D( B
  16.   GPIO_Init(GPIOB, &GPIO_InitStructure);  ' a6 |( ]6 H( Z; F
  17.     , g% R. u+ p0 R) [7 `1 o& Y: F, }
  18.   /* Configure CAN pin: TX */   // PB9  
    4 }$ O! `1 H/ o7 J& R. Z
  19.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  8 j3 v# ]. N7 F9 }: T$ J7 y& e
  20.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // ¸´ÓÃÍÆÍìÊä³ö  
    * t: ~, W) s& v  I4 z
  21.   GPIO_Init(GPIOB, &GPIO_InitStructure);  
    ) e. `% D8 `  ^4 s1 T
  22.    
    3 D5 t; M( a6 w( P, {, F) ~6 L5 f
  23.     //#define GPIO_Remap_CAN    GPIO_Remap1_CAN1 ±¾ÊµÑéûÓÐÓõ½ÖØÓ³ÉäI/O  
    2 v% B4 L. G1 m
  24.   GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);  . m( Y, |+ X2 M/ G7 G4 C. T: z
  25.   - W" k) _2 b; Y$ j
  26.    
    ; O6 W$ d' f0 [2 x+ r3 f' B) q
  27. }  
复制代码
自设板
& J& V, ?  Y4 o) j; q- z
  1. [objc] view plain copy  c! V1 O9 @4 l) \  `, L& y/ ~/ Z
  2. void CAN_GPIOA_Config(void)    4 V! w4 m$ W( m9 I* [; K1 U8 T
  3. {    5 g7 Q2 g  x4 y& U3 A  K# r& n
  4. GPIO_InitTypeDef GPIO_InitStructure;       ! Y" L2 r2 Y4 J% w( S8 a
  5. /* CAN Periph clock enable */    # M4 b; \1 P& k$ Y% K  [& i! }
  6.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);    ) V$ @% J1 ?% S% }
  7. // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);   
    % m7 a. |1 N1 g3 d4 }
  8.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);      t" }. U5 m5 ?# Z; R% m* z* f
  9.     # i5 r& W& K% l
  10.   /* Configure CAN pin: TX */    ' H" D6 l, F, u) m
  11.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;   
    4 }* `/ A5 f- w: \1 k- l9 Y. D
  12.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    ! i* D3 _. U% E* R
  13.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   
    + a7 M6 `- B( m* c
  14.   GPIO_Init(GPIOA, &GPIO_InitStructure);       ! t" t, |8 j$ a" }: r; Y: i' m
  15. /* Configure CAN pin: RX */   
    $ W# ?# I/ ~9 B
  16.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;  
    * [  K2 Y9 D. x+ Z5 q
  17.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     1 h4 h1 x: f7 A& U9 g1 v
  18.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;     - {( `  T3 p, l/ a1 M) b
  19.   GPIO_Init(GPIOA, &GPIO_InitStructure);      
    ; \; J3 a& A6 D7 k" Z$ X+ J2 x" z
  20.   //GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE);    , z! S9 t+ d' u
  21. }   
复制代码
/******************************************************************************************/
  `9 S4 w2 f* i3 E就是这里!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  G, o3 F2 ?, ?- V出现几个小问题,但是却是致命的问题!!!!!!!!!!!!!!!!!!!
; J8 a* |9 @$ M3 b8 V
( z% ^% b% R5 P# @. ]1 I/******************************************************************************************/
7 E* B/ r' e0 V* N' d9 X  K/ \: e( L6 y4 v2 ~
第一配置GPIO_Speed:
  A7 Q# ]7 q2 Y" m. E* X2 Y+ K3 K9 Y2 j3 w4 S+ f; N
[objc] view plain copy
3 |8 H- [9 i4 eGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  //配置GPIO_Speed为50MHz  5 Z/ \. j* C# q; ?1 n0 O
如果配置GPIO时,省略这一步,会导致CAN口发送不出数据,工控板的配置是放在LED 的GPIO配置中,一开始忽略了这一点,之后用排除法试出来的;& H' _: s0 f+ u, L

+ E, ]4 t( X- T, a1 z. U第二配置复用功能和映射与否:
9 v+ ?2 E; G- H, e7 [/ i
  1. [objc] view plain copy7 _# o) b3 t: y' M7 U; T
  2. // RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //复用功能时钟使能  
复制代码
  1. [objc] view plain copy, t5 j2 F$ ?" N. J& R; |, w
  2. //GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE); //重映射I/O CAN使能
复制代码
  1. [objc] view plain copy
复制代码
  1. [objc] view plain copy
复制代码
  1. [objc] view plain copy
复制代码
上面两个被注释掉了,是由于:  * x8 l- r. }$ o$ P$ m! C# ^# h
用PA11和PA12 用的是CAN的默认端口,而用PB8和PB9是用CAN的复用功能重映射端口。
0 ^: _$ l7 f% ]; W) \: w5 O4 T& b, E/ C& W- q# z4 ?# J
  1. [objc] view plain copy) O$ h) Y, ]% v, q5 Q
  2.   
复制代码

1 E5 V$ d) O; y( n' f1 c; W
3.jpg
0 P+ Y, h3 \0 E- }$ c
具体:
9 y( Q& D9 N$ ]& g-------------------------------------------------------------------------
! u& Q/ A0 M8 F. Q" I, g* j2 E+ `$ a3 I$ p6 k, [
默认模式
/ p4 W" s) ^4 Y# F' U) F- I8 c% u4 N  h  c# u! y$ U. B  x
   /* Configure CAN pin: RX */; Z' \- Q" @) m" l- E, ^  o
$ k$ ^- _) E6 ~5 V
GPIO+ _) P# Q/ v  t7 O) S/ a' h- Y

( k& [" E% Q0 e4 \+ j/ t& r_InitStructure.GPIO_Pin = GPIO_Pin_11;6 l$ k* [! l% a! v$ W/ f
1 B; M: e7 D* q$ v4 r
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
* B% r# q2 L# g' G9 h7 T  S* b- c7 B, `, m- T$ k* m! g$ m" ~8 E/ N* R& \5 S
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
7 s3 T% S$ O* S# J& H: |  u1 k/ v
" o+ |- {+ ~) |/ w+ t. @1 Q9 d( j   GPIO_Init(GPIOA, &GPIO_InitStructure);
1 Y" q& v7 }+ r( ?3 B) ?- Z* G; a4 q8 b- \: {; k7 f
   /* Configure CAN pin: TX */' e9 E0 U$ r( W' z
4 P2 C: K# ?, C: k" L2 d, T
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
0 q9 O1 Z5 c0 s4 Q7 E( h
, k3 H) @; f4 ]/ F. d   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;: _7 f/ h& g0 f3 V

* Y& {2 d' E& _. v) R9 {   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;7 }6 i  ~" H1 Q+ z2 A- |* Q
4 B5 J1 @. j5 F$ U2 a' L
   GPIO_Init(GPIOA, &GPIO_InitStructure);, t' [' G! f; v& D
------------------------------------------------------------------------7 {; X3 G% m( ^  \* h

# j. p' h' P* ~, i( X4 \1 I# V重定义地址1模式$ W; z$ g1 F% P' @- q, @4 |

# Z* D  u3 N/ Z* L/* Configure CAN pin: RX */
: L7 l8 g& E8 }7 @- C; x- k/ r2 b* O0 h4 ]$ ^" E, E
   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
% z! p7 v# }( b% C  P) v, R* K/ m) `2 J2 F8 V/ [$ ]
   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
1 L6 k  [0 T% k9 n0 R4 A$ I4 m0 c, c# J
   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
. V. Z# X& ?3 W6 |9 {5 n' b6 G$ g8 Z3 ]# c& T
   //GPIO_Init(GPIOB, &GPIO_InitStructure);
" e: V- N3 E: \
7 T" ^. r% H! ]4 Y   /* Configure CAN pin: TX */  4 p9 h, ]" B( ^

( [% g! p/ a3 O5 b8 X: y6 Y' v   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;* ?/ ~) F6 [. M

% I5 N, Z3 o; _3 B# }: Y5 i- {4 Y9 i   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
) J; o5 i+ r" Z2 r4 W
: S  d0 `1 r' l) H; O0 y6 X   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;; L* h5 C. e/ @
) Y( _+ a( g- F! Q- O' o- u
   //GPIO_Init(GPIOB, &GPIO_InitStructure);
, O+ i  G$ X6 C1 A8 c) d% ]6 e5 b5 H6 L
   /* Configure CAN Remap   重影射 */
2 o8 [4 K0 I6 u+ p# L' {4 v7 b. `3 h( M
   //GPIO_PinRemapConfig(GPIO_Remap1_CAN, ENABLE);
! O  [' T( a. h- D- G9 Y, n1 A
. U* z3 P/ |3 p, G; N7 A-------------------------------------------------------------------------  
2 G/ q4 }9 n/ d5 ]. z4 C5 W
" L; R% b4 [" R$ h# n0 q8 |重定义地址2模式, E+ T0 w0 {" Q1 i+ F2 R
) _  u7 Q0 e8 q( X8 F
   /* Configure CAN pin: RX */
: [% d# p7 f2 u, P- g+ e1 _+ |% n8 ~  B7 T2 X
   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
5 r3 X3 r. G+ D  k$ w4 h, C- s0 p3 R) F7 D6 ?
   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  E* N: y3 Y1 L& \! Y7 e0 @1 J. w: V" f4 C4 _; m
   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;, Q7 @4 `8 C* S) M

( e8 R$ ]. N) m! M1 X   //GPIO_Init(GPIOD, &GPIO_InitStructure);
! g0 w: l" h5 J. ]  {8 e& `) r# H4 Q. A8 G$ a# e7 Z0 ^' o
. a; @! O' A9 K' k/ A/ U$ y
   /* Configure CAN pin: TX */0 D! C9 H$ I7 U; V
2 o. Q$ Q- d& a& |9 \
   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;9 @# e+ t0 d5 w- Q% i
8 x% z7 ~$ F- `' H7 p1 s8 Q
   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  Q7 p3 f, g5 z& u- `- ^& A% z2 _8 D/ e1 F% |! x
   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;/ t; |6 b% B/ S/ j

1 R: E) @' ^6 R$ n  S6 I# m   //GPIO_Init(GPIOD, &GPIO_InitStructure);+ l$ G8 w  `9 Z( t

- u/ k# i( ?4 s, v" r3 d: C% M$ L4 F7 J& r
   /* Configure CAN Remap   重影射 */
0 F: ~& V0 E0 n& \# j
# r6 g; g& p- f) ^+ {& W   //GPIO_PinRemapConfig(GPIO_Remap2_CAN, ENABLE);6 T# t$ g9 a. Z- [: Z# [' F6 d2 b

: n3 @8 F9 J" W* t% ]7 O( ^-------------------------------------------------------------------------6 D) Q1 `( {7 ^* ?/ I7 z
! f2 _8 ^0 i/ m8 C
设置完 CAN 的引脚之后还需要打开 CAN 的时钟:
) S7 g" x5 Y7 E/ T: L7 {! w# s% f, k' d0 k$ K, |3 x& @0 Z$ W/ D
/* CAN Periph clock enable */
! I1 }9 O  y% B5 q, d: t( b% n! n
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);: O% F& u0 T. `- @9 Z6 X
+ f" T: E8 N9 u" S9 S, e% S
第三CAN硬件部分:
8 @/ Y& Q$ U; v2 C7 R+ f* Y
! i/ Z$ f8 c3 p" x# @一开始对CAN硬件部分没有过多的了解,后面经过一系列的试验,发现:$ E' S! b5 c9 n4 u& X6 E
  O: l; [: p& c" b/ W# N
1. 如果STM32 CAN TX和RX没有和CAN收发器连接的情况下,STM32的CAN TX和RX是没用数据发出的;
' ?+ \9 i( i- K  Y0 v; n) O/ P6 Y/ E( j( O2 l8 }! z
2. STM32 CAN TX和RX必须要与CAN收发器的TX和RX对应,即TX接TX,RX接RX,否则CAN没有数据发出,说明:之所以说这个问题,不知道你们有没有注意到,我的自设板CAN收发器TX和RX是反接的;
! ]0 @( d9 k  J! i+ y+ m* q) q* b! q5 [) N; N
3. STM32F103C8T6-LQFP48 的CAN口和USB口复用,即用CAN口是需要将USB口断开,防止有所影响;8 i9 C: a  @1 \$ _7 ]
% V. P; V9 A. c! V
4. 是我本身设备问题,我的自设板用的12V电源是我自己焊接的,不太可靠,电源12V时有时无的,所以最好烧写程序的时候点亮一个LED灯,可以显示板子的工作状态;' v9 Y4 @6 f- b2 ^, g  [

( W. }- ]. _5 E) w! @, B2 e: ^5. 工控板上CAN收发器是用TJA1050 是5V供电的,自设板用SN65HVD234 3.3-V CAN Bus Transceivers,之前有所顾虑,怕CAN收发器不一样会导致其它后果,之后发现没有问题。' h; K- i6 M; P& w( l/ E
1 V$ y  m2 ?' ]/ K, X
9 d# K( G, D" g1 ^; \+ O$ y/ D9 h

3 Z" M  [/ @+ W  U( m/ j, a) ~2 I以上为本人的一点心得,走了很多弯路。。。记录点滴,以此自励。
4 B1 k, y& o0 B$ [4 k4 K$ b9 f4 C' _6 x+ n# n) ]

8 T8 w0 N* y* K" i, a$ B' {/ f' t1 i
2 g3 G1 [8 S3 ]; M6 I

7 {% J% y% b# B转载自sunnyhyh
% T" ^* S. C$ F- ?( ]/ c' [) X! q. B9 p% ^
) g% M; L! X# T

评分

参与人数 2 ST金币 +3 收起 理由
STMCU + 5
50031185 -2 转载请注明出处

查看全部评分

收藏 评论4 发布时间:2018-6-1 13:47

举报

4个回答
samhong 回答时间:2018-6-2 06:56:45
谢谢分享!
KEY1 回答时间:2018-6-2 10:08:11
转载别人的文章 没有在标题注明 啥意思? 盗文吗?
飞鱼大炮 回答时间:2019-6-17 19:49:25
感谢分享实战例程学习学习
未来,我来 回答时间:2019-6-17 19:57:31
感谢分享实战例程学习学习

所属标签

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