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

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

[复制链接]
aimejia 发布时间:2018-6-1 13:47
本帖最后由 aimejia 于 2018-6-1 13:49 编辑
! G9 C/ O, e/ N; c$ v/ j' p7 ?& V% [) A
一. 开发平台与工具:
, z; h' G, k4 y6 u3 e4 |" p
% h1 q( ~: \; e# |& z1 H  D1. 平台: STM32F103C8T6  48PIN工控板和自己设计的STM32开发板
: a, g6 ^; N# f7 J' q6 M
& Y) P% V6 g( Q6 }2. 软件: MDK5 UVision V5.14.0.0
' ~/ G  r; V  V; u: W- v
7 ]7 `! N9 o# q3. PACK: STM32F1xx_DFP——1.0.5(2014-03-14); f. b$ L' P1 s7 P
! l& d( Y8 g  ]- E7 J0 q- N5 s" n
4. 其它:USB转串口,ST-Link下载器,
6 I7 V, f6 i$ ^) E$ ^  W/ N- R; r  }( H* w& a' w
USB-CAN Adapter用于直接监视CAN口发出的数据,上位机有两个,一个是EmbededConfig for USB2CAN 配置串口、串口波特率、CAN速率等,另一个是EmbededDebug V2.0监视CAN口数据;使用顺序是先配置后查看CAN数据。2 U; W/ u! ?5 v( z* c6 f3 p7 a
4 i# H" w7 p# ?$ M3 ~* X
二. CAN总线的介绍简略:3 Q6 U5 J4 k; [5 p# ?
  B) b( N( U9 x  o  I3 j, q; g
bxCAN 是基本扩展 CAN (Basic Extended CAN) 的缩写,它支持 CAN 协议 2.0A 和 2.0B 。它的设计目标是,以最小的 CPU 负荷来高效处理大量收到的报文。它也支持报文发送的优先级要求(优先级特性可软件配置)。3 U+ |; D& @! \, P

+ ^2 @/ L  N" p4 T+ d/ U  M$ g对于安全紧要的应用,bxCAN 提供所有支持时间触发通信模式所需的硬件功能。
2 B% \* c/ l" y/ s) V& B5 g: t+ N7 T4 j( X4 P' V7 i7 m* E
主要特点6 s$ S/ P( B: b0 [2 y0 m% g
· 支持 CAN 协议 2.0A 和 2.0B 主动模式; ?7 Z3 Y  u; X7 [
· 波特率最高可达 1 兆位 / 秒) E# d- W# T: `. [; F
· 支持时间触发通信功能" x* H8 U) F* Y& t. g
/ F! a  B) u* N# L$ h! H
发送
6 Q! A, d4 t* d4 z- U· 3 个发送邮箱# ~9 R7 \! o; }: X  q
· 发送报文的优先级特性可软件配置( B) u7 D/ O- R1 Y8 U. H' J
· 记录发送 SOF 时刻的时间戳9 z. t* O: V) {: G
7 L1 m. X3 j- M( N  S7 Y; b
接收3 I  t$ d- G! T* l8 k0 }/ C
· 3 级深度的2个接收 FIFO
) V4 I) A5 {1 i- |: H· 14 个位宽可变的过滤器组 - 由整个 CAN 共享7 V: F' J3 X  x8 V; [
· 标识符列表
. T; [5 F; U* A/ H6 @( a3 o. ~· FIFO 溢出处理方式可配置
& Y1 b( `- \/ L) S) x3 K- v· 记录接收 SOF 时刻的时间戳$ p: s3 i0 o4 M3 p% r" M) `

: c2 L8 ?) o! }, G可支持时间触发通信模式: J5 P- X& p; O
· 禁止自动重传模式6 l4 j4 v3 X: a9 Z3 t6 M9 F
· 16 位自由运行定时器* n+ W- @  H3 ?, L6 v
· 定时器分辨率可配置' m( A2 t. O, T& q
· 可在最后 2 个数据字节发送时间戳
  b* \4 K/ \% f+ m* m
+ P: c7 e$ L$ ?  F3 C. L管理2 @; _1 Y! m6 @9 [3 O4 D% H. H: I
· 中断可屏蔽( h* k# F. i& ]2 n7 {5 n
· 邮箱占用单独 1 块地址空间,便于提高软件效率
9 c) E9 {) X2 Q3 Q* q2 e% W7 S: v+ ]6 K: j* Y1 }
更多STM32 CAN总线介绍详见:STM32中文参考手册_V10.pdf 或 STM32F10XXX-RM0008 Reference Manual 英文版- p+ z7 p$ m3 a. V

0 j& }9 q! P; b3 I2 X三. 遇到的问题分析与解决:
. ~2 {1 w1 @$ u; N5 u5 s# T2 j( j; J4 O, p8 y# T
手上有两块STM32的板子,一个是网上买的MINI STM32工控板,另一个是自己公司设计的板子。二者有所不同,大致有两点,第一是串口,工控板用的是USART1 且用的是GPIO PA9(TX)和PA10(RX),自设板用的是USART2 且用的是GPIO PA2(TX)和PA3(RX);第二是CAN口管脚不同,工控板用的是复用功能映射到PB8(RX)和PB9(TX),而自设板用的是PA11(RX)和PA12(TX)。下图所示,两块板子部分原理图:/ n/ p1 c" @# R5 \

; C. M! P0 z$ e工控板
' i: D3 m5 x; A+ z* Z
* c; X: {. Y0 H) N
1.jpg
. ]& Y& b* m. z: f% z% M! d* I+ x
自设板
* G- a5 G. p* c0 O+ R% D9 C3 Q* f7 @6 [4 ~5 A, J3 c
2.jpg

! e$ a: J& y! [现在我是在工控板测试代码基础上,用到自设板上,实现PC端串口与STM32 CAN双向通信,要做的是将USART和CAN口的GPIO配置对应到自设板上。
! |. M3 H2 Y; O" G3 U* z  E
% \7 y. ]# N8 b( }首先,串口GPIO配置:
( J$ N5 J' Z/ o! N# q& C% F* _: }0 B6 ], R% N$ b
工控板# p, y  l' j5 i/ G
  1. [objc] view plain copy' B% e! z# o7 V- B5 H0 t: K1 k
  2. void USART1_Config(void)  
    . x$ V( ^. M+ G
  3. {  
    . z8 c) ^- n8 ]5 [; ?  @
  4.     GPIO_InitTypeDef GPIO_InitStructure;  
    5 R0 H! Z9 D3 @; F3 E
  5.     USART_InitTypeDef USART_InitStructure;  , G! B* j, p) C
  6.   ) d- q$ R2 P% p
  7.     /* config USART1 clock */  
    9 ~& S4 V. a9 d; W0 g
  8.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);  
    9 P0 I) H/ F6 \# Q. u5 \0 a% W
  9.       5 [! K/ Y+ e0 S) R
  10.     /* USART1 GPIO config */  
    " i5 Q: L' i, ?; q: g+ s
  11.    /* Configure USART1 Tx (PA.09) as alternate function push-pull */  ; ?# A1 j5 b* I! I
  12.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  
    / t: L8 f" V! I/ c
  13.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  5 q' M3 ~2 I* U5 a+ ]9 I
  14.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  ! F& a: p3 s! g9 V  E; J
  15.   GPIO_Init(GPIOA, &GPIO_InitStructure);        k( m" ^0 v* H+ m# J1 P- Q
  16.   /* Configure USART1 Rx (PA.10) as input floating */  + O# w1 `! n8 `- D+ y4 E; i
  17.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  
    1 W# ]& L; |4 g9 n+ d1 h
  18.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  9 ^2 }! w& K/ U' U. D
  19.   GPIO_Init(GPIOA, &GPIO_InitStructure);  * {% c/ B) S. x) f, N' X1 _
  20.         
      Q: D: O3 ], V( P. m) Q
  21.     /* USART1 mode config */  
    ! ^9 \+ p- i! d! x: l# M
  22.     USART_InitStructure.USART_BaudRate = 115200;  * u1 u# l# _/ `/ V% Q  k& {
  23.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  0 H/ a9 a) H# ^9 I9 W
  24.     USART_InitStructure.USART_StopBits = USART_StopBits_1;  
    $ V9 d% @7 D6 i7 m$ J; @* Y
  25.     USART_InitStructure.USART_Parity = USART_Parity_No ;  : ]5 m" Y1 y$ _% ^, C4 B
  26.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  % u4 u. |% c; V" s; x1 o5 H
  27.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  0 ?3 B2 b" i) T
  28.     USART_Init(USART1, &USART_InitStructure);   
    & v- ]; g6 Z) d* X7 v
  29.   USART_Cmd(USART1, ENABLE);  / Z  `" F  _. Q- G$ k7 Q  `
  30.       . \# h+ a$ |% f! v
  31.     /* Enable the EVAL_COM1 Transmit interrupt: this interrupt is generated when the  
    # x4 n: Y$ z* Y2 s
  32.      EVAL_COM1 transmit data register is empty */    ! `, o! Y% C2 W- a- B' j# u
  33.   //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);  # I4 g; w& }, f
  34.   
    % a; V2 [. |5 K5 i) D4 N
  35.   /* Enable the EVAL_COM1 Receive interrupt: this interrupt is generated when the  
    . ]6 _' V) u4 z' w) r) d! [" R
  36.      EVAL_COM1 receive data register is not empty */  - f; I! r& N0 T  R
  37.   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  . ]7 E4 l7 b  y3 x( V& J
  38. }  ! z9 }; s. ]( }7 L) E
  39.   
    ) Z$ C2 |. A/ i6 ]/ B& P+ R/ I* J
  40. /***************USART1 ÅäÖÃÖжϷ½Ê½·¢ËͽÓÊÕÊý¾Ý******************************/  
    2 O4 A8 N2 D0 O% [, K
  41. void USART1_NVIC_Configuration(void)  ( F6 C. q& K; f1 D; S3 a' m
  42. {  
    0 L' R, q& ?2 X
  43.   NVIC_InitTypeDef NVIC_InitStructure;  " e+ K, F/ }% Y
  44.   & O3 u) n, f! k% c6 C5 j5 G/ h/ }
  45.   /* Enable the USARTx Interrupt */  
    4 W) F/ [: m5 q8 t7 r$ Q! G
  46.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  " j# z. Y; J; O: W  g% p0 Q
  47.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;    `' c$ [' Z) s& G8 L" ?# ^' R3 ?- u- E
  48.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  : ]8 ^; ~/ U& s
  49.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  5 f% w, Y0 _) E. j4 }. n1 s" W/ r
  50.   NVIC_Init(&NVIC_InitStructure);  8 T0 x* n' Z3 s2 X. C7 A5 `. o
  51. }  . o3 q0 Z! F& u: ^+ y
  52.   
    / g* Y0 J: G0 F1 o/ y; {! z
  53. /****************USART1 ÖжϺ¯Êý***************************/  
    $ ]& j( t* l( B( Z
  54. void USART1_IRQHandler(void)    o; @; r9 g3 W) {. d
  55. {  0 f' m3 {: O6 w3 Z
  56.     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  
    2 Y/ V1 m5 X$ Q' j- k
  57.     {  
    / R  F5 `7 @# W( M. N9 {) |
  58.         RxBuffer[RxCounter++] = (USART_ReceiveData(USART1));  
    4 \9 w$ U. c) D( f
  59.     }  
    ( x1 ?  @6 O( b6 U5 y4 o6 s
  60. }  
复制代码
USART1_Config()用于USART1的GPIO配置,配置到
+ h+ a7 [% u. Q; @; O! f: h *          | PA9  - USART1(Tx)      |
3 o$ l( q) ]& z" }/ D+ a* b) T: B *          | PA10 - USART1(Rx)      |- e! A9 J6 r7 Y: `1 M+ h5 D
*           ------------------------" b" M+ }3 Q0 \$ x. f. {) j; v
USART1_NVIC_Configuration() 用于USART1设置中断方式接受发送数据
2 A3 s5 V; j7 j8 P
- @5 O8 i0 |% J$ Q7 R$ _# HUSART1_IRQHandler()用于USART1中断接受函数
% L' t* |( W% R  n& L$ G' T  }" \  n+ ?% @6 Y8 j' Z7 n
自设板" y% z: \# L" a  [8 O
  1. [objc] view plain copy
    , u: }, ?( g3 L9 g, `
  2. void USART2_Config(void)  
    : E  M: t5 V6 {7 w& `; g  }
  3. {  ; W* {/ a. s8 z2 P
  4.     GPIO_InitTypeDef GPIO_InitStructure;  
    2 A7 M7 d: I% y
  5.     USART_InitTypeDef USART_InitStructure;  0 ?+ L2 F  u+ x
  6.   , l5 ~  m' K. ?, H3 {
  7.     /* config USART2 clock */  % F$ N. Q0 O- a1 U* q
  8.     //RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);  
    - C: n! z. |: p! V) K) D
  9.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 , ENABLE);  / I6 ~+ [+ ~0 b2 a' L, D# ?
  10.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  
    ! S$ N, d7 X1 V# T
  11.       3 A4 _  d3 d- Z* v+ Y5 n
  12.     /* USART2 GPIO config */  
    7 W3 a1 O7 n! A' v1 Z, `1 @
  13.    /* Configure USART2 Tx (PA.02) as alternate function push-pull */  + R2 E$ @/ |# D' ~1 r1 ~: P
  14.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;  
    ) b5 D) w0 f2 f; S) K
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
    8 l: J. t+ r7 g2 z7 U$ }
  16.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    8 L# Z& B7 G- W: P. c4 T
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);      5 A, S0 r5 C! G' g
  18.   /* Configure USART2 Rx (PA.03) as input floating */  
    . p7 R3 _! q& p8 s6 z: s0 h3 r
  19.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;  9 h( J2 t1 s7 G/ @
  20.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
    8 u2 k; A' W( N! A" |& }, R3 }; I
  21.   GPIO_Init(GPIOA, &GPIO_InitStructure);  
    : J* k- f8 s& `+ c8 X) v" @7 {
  22.         , j$ g# w# `6 l6 G6 d
  23.     /* USART2 mode config */  & t) Q$ V; L# E8 Q+ s1 u/ t, d
  24.     USART_InitStructure.USART_BaudRate = 115200;  " g2 g) j3 c1 g9 K/ F' m5 M
  25.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  
    7 z) K4 F  d& S9 F4 S1 F8 t
  26.     USART_InitStructure.USART_StopBits = USART_StopBits_1;  3 K7 M6 ]4 D: e6 ~' n
  27.     USART_InitStructure.USART_Parity = USART_Parity_No ;    [, \& F( x# L" c8 d
  28.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  
    3 Y5 V% v2 K& r6 B2 }; f1 l: [
  29.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  
    ( Y* ~* q7 [" N/ r$ C6 `/ z& k
  30.     USART_Init(USART2, &USART_InitStructure);  
    % a6 R! X; P: _
  31.     USART_Cmd(USART2, ENABLE);    c, m- Y5 E3 j
  32.       ) a( ]6 ?3 P2 F' E  {5 L' r' ~
  33.     /* Enable the EVAL_COM1 Transmit interrupt: this interrupt is generated when the  ; m) u- d  w8 Q* o; @( S% X3 G
  34.      EVAL_COM1 transmit data register is empty */   
    % ]3 r7 |+ B6 c0 D' V0 i
  35.   //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);  
    / q! }% V, n' d3 ?. C+ @
  36.   ' M! |3 V- @" U' i, q6 H
  37.   /* Enable the EVAL_COM1 Receive interrupt: this interrupt is generated when the  + T6 O  R' R* E) |/ G8 r
  38.      EVAL_COM1 receive data register is not empty */  
    % l' @" _; g* y. t
  39.   //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  ' Y  J  P! N# [7 Q; s/ x7 K$ M; S6 w
  40.     USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);  , y/ r4 w7 y4 |/ ?: x7 s/ H
  41. }  
    1 e: g# k- J; S' R' b" L5 k- _
  42.   % T! @3 ~% F$ v0 L* g
  43.   
    0 {5 i: T  Z/ \5 }; d0 g$ E
  44. /***************USART2 ÅäÖÃÖжϷ½Ê½·¢ËͽÓÊÕÊý¾Ý******************************/  * W8 i/ D  s8 n# P/ Y/ V
  45. void USART2_NVIC_Configuration(void)  9 w, {) O3 ~6 E
  46. {  . N. y- A0 K. U' g& \! V  m8 o
  47.   NVIC_InitTypeDef NVIC_InitStructure;  
    % O; S& u* ^7 p! ~( ?6 Q2 h
  48.   0 {6 `; ?% F3 `' X- [; E
  49.   /* Enable the USARTx Interrupt */  
    1 {9 P/ K% ]6 N3 N* @
  50.   NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;  
    8 C  a8 }7 c: D: E
  51.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
    , F1 G+ |, E: E1 a3 }0 q, U$ F
  52.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
    ; m& }2 x. D' v0 g' ~& ~/ X
  53.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  9 l6 U4 [' A$ M( q' `& i
  54.   NVIC_Init(&NVIC_InitStructure);  
    ; |$ x- \/ |( ~
  55. }  
      X' [) P/ Q, k5 C2 _( f- J7 G
  56.   
    6 [, J( I+ J2 H$ `1 Z2 J" d% w
  57. /****************USART2 ÖжϺ¯Êý***************************/  
    4 F! v$ I7 |' F9 s4 [
  58. void USART2_IRQHandler(void)  
    2 I( K% c* [  p7 E- m$ R  ?6 P# f
  59. {  
    . G  d! F$ m7 t5 k' T
  60.     if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  5 e8 z5 S+ W. v4 ~
  61.     {  9 e( r% {9 a8 m/ g
  62.         RxBuffer[RxCounter++] = (USART_ReceiveData(USART2));  4 f- W6 p5 }1 I" L. X# q; m& _
  63.     }  ( p- h7 d$ `5 u4 g+ z
  64. }  
复制代码
USART2_Config()用于USART2的GPIO配置,配置到
4 t9 ]4 G( t7 ?. Z' l7 M1 a) |4 E! v9 a *          | PA2  - USART2(Tx)      |
6 L* m9 R- C0 D *          | PA3 - USART2(Rx)      |; N" ?+ h$ V+ s  o# w0 D( w
*           ------------------------' H5 _0 }6 m+ \8 L6 R$ f
2 Z- F- Z0 d/ p& F" m
USART2_NVIC_Configuration() 用于USART2设置中断方式接受发送数据! T: v8 D/ W* ~: [7 _6 o6 H9 g; _

; ]0 a$ F4 x( e& ?USART2_IRQHandler()用于USART2中断接受函数7 V6 c3 b7 J) I
9 ~: f/ X# X2 T- [/ f
然后,配置CAN口GPIO
& h* {1 A: W% X
# m  v8 m. R5 {8 D2 h* m* H# V工控板, L) n8 j, ?1 L( V3 _+ g3 P
  1. [objc] view plain copy8 s0 y( U0 P* a$ \9 \7 s
  2. /*CAN GPIO ºÍʱÖÓÅäÖà */  ) r- k) e9 ^1 x6 D) H7 V
  3. void CAN_GPIO_Config(void)  & \  X$ s# _- o1 p. {
  4. {  # J. S- X5 b& F+ A- o! G
  5.   GPIO_InitTypeDef GPIO_InitStructure;   
    " X' u! Q9 a5 t. S$ b
  6.   /* ¸´Óù¦ÄܺÍGPIOB¶Ë¿ÚʱÖÓʹÄÜ*/     
    ; x+ M* H8 }, h, e& N
  7.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);                                                                          7 _/ Z. p" Q! ?- i
  8.   & k5 |6 r" t% R! d6 {  \
  9.   /* CAN1 Ä£¿éʱÖÓʹÄÜ */  
    . ^& O; u+ I% `$ R4 Z; ~5 y. G
  10.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);   7 h# Y  ?/ ]: Z) m* D5 \7 Y
  11.   
    ) ]0 Y. Y. f, v5 h- p; D- J. ?9 Q
  12.   /* Configure CAN pin: RX */    // PB8  7 q. f% J. |/ J
  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;  
    5 a/ r0 J/ c# C/ t  Q) \7 h* T
  14.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  2 j1 X1 D$ ?4 ]3 |+ ?
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  // ÉÏÀ­ÊäÈë  
    3 }7 o4 j" ]+ Y0 r& Z; G
  16.   GPIO_Init(GPIOB, &GPIO_InitStructure);  ) b/ X$ I9 A6 h. L( j3 \5 l. a7 W7 W7 g. D
  17.     2 r/ s# Z- e' l7 F  A
  18.   /* Configure CAN pin: TX */   // PB9  
    $ j0 p2 K/ }) @" `4 i
  19.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  9 b/ ?5 I1 j8 l) x+ B
  20.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // ¸´ÓÃÍÆÍìÊä³ö  : }' V, Q. ?0 i$ w
  21.   GPIO_Init(GPIOB, &GPIO_InitStructure);  3 A9 g% E9 k- ~! c2 K
  22.    
      ~5 x# ]9 B/ T
  23.     //#define GPIO_Remap_CAN    GPIO_Remap1_CAN1 ±¾ÊµÑéûÓÐÓõ½ÖØÓ³ÉäI/O  ; x2 L, w  J8 p1 u' G. Q0 l
  24.   GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);  
    $ i4 ^( g: p% |7 v: j# t. ]
  25.   
    # M7 I* t; a; h# J2 z% k! M* J
  26.     * w. u, j* W. }4 P/ A
  27. }  
复制代码
自设板) W9 s2 D1 W0 @$ f1 G$ t1 s$ h
  1. [objc] view plain copy" S  l2 K" \2 u8 j0 u8 V+ R3 [
  2. void CAN_GPIOA_Config(void)   
    2 z. K0 q" _* [, _0 s
  3. {    & H. z7 f2 m" g0 V) n  B9 W
  4. GPIO_InitTypeDef GPIO_InitStructure;      
    6 F5 x3 A/ m. [9 @) I! q4 w
  5. /* CAN Periph clock enable */    * Z2 @8 u& y+ w$ ]
  6.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);    1 w. H, d& T$ U4 u' g
  7. // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);    4 N/ `7 K7 }/ ?+ Q9 t
  8.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);      v) V% l" k# l$ q+ D6 w
  9.    
    $ x5 U3 w" d. d% u( ~. e2 k9 }6 x" W
  10.   /* Configure CAN pin: TX */   
    5 h1 Y. l# E/ h# {5 A
  11.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;   
    # A3 D* E( ?! H$ u: B  a4 [
  12.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    + ~% H: j& `6 H+ I: p( H
  13.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   
    7 C  {% t# H% h% F
  14.   GPIO_Init(GPIOA, &GPIO_InitStructure);      
    / c. A* }+ h7 F8 o* P" k7 }
  15. /* Configure CAN pin: RX */    6 {3 B& X1 a( q4 c  @
  16.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;  
    . F/ z3 }# \9 a1 \0 }
  17.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     - Y! G8 K0 R0 ?/ V7 s
  18.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;     / F& K) Z5 T) T8 t
  19.   GPIO_Init(GPIOA, &GPIO_InitStructure);       3 B1 h) [+ Z  i! C1 i
  20.   //GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE);   
    9 h, [4 X5 \/ h1 v4 G
  21. }   
复制代码
/******************************************************************************************/
9 \1 H: a* Z5 d$ [6 q就是这里!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!) |- Q7 e! T" M- ~
出现几个小问题,但是却是致命的问题!!!!!!!!!!!!!!!!!!!! r1 S! w4 e! _" d' D2 ?6 \; g
9 I2 Z, v: y8 d! {8 b2 E4 D
/******************************************************************************************/6 K) n& P2 B2 b

4 k; N/ p4 e* e' j, T# I4 t# K第一配置GPIO_Speed:
1 T/ E7 y( a- p, P
# u0 c' E. l1 }/ y0 X  O[objc] view plain copy- T; A3 ~! V% c5 e1 C) D7 Q* j
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  //配置GPIO_Speed为50MHz  8 x& {; R3 {! k, O
如果配置GPIO时,省略这一步,会导致CAN口发送不出数据,工控板的配置是放在LED 的GPIO配置中,一开始忽略了这一点,之后用排除法试出来的;( ]3 _9 D* ]2 l  s" A) y* h0 @0 ?

4 k; l: L  ~9 g* F第二配置复用功能和映射与否:7 \. k1 z" B4 s* G) u
  1. [objc] view plain copy
    # {5 O" ], h7 \# J& X
  2. // RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //复用功能时钟使能  
复制代码
  1. [objc] view plain copy
    ' ^# g0 T. A; r
  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
复制代码
上面两个被注释掉了,是由于:  
8 r" |& y# g5 o. Y) ^3 M) s4 U& t2 g用PA11和PA12 用的是CAN的默认端口,而用PB8和PB9是用CAN的复用功能重映射端口。
1 P1 \2 w: G( c' B
0 `% U6 @+ c$ d6 m1 G/ x/ U
  1. [objc] view plain copy- N: ?- c) @& G) D0 C+ ?& \
  2.   
复制代码

/ {% }2 r  o: S1 f& t) l
3.jpg
3 j7 e4 j/ X' F2 U
具体:
  B, W1 S# f  w( R) d; P! Z& P-------------------------------------------------------------------------0 {3 |+ J( D- s% }8 Z0 ~8 `% c; H6 ?

4 l8 _2 C8 e# B默认模式
9 O% i9 U1 f7 [% U1 g! a3 h
7 l( _# _6 [0 P7 |   /* Configure CAN pin: RX */
3 O% Z7 V& ]' x5 b
. q& o' K9 ~+ O! w+ n2 J7 }GPIO( i9 m! K) F+ ?
9 ]5 N- s* v2 c7 W
_InitStructure.GPIO_Pin = GPIO_Pin_11;
; j' ~9 ]# X$ p* q6 P9 i& y; K4 D4 Z- ^( M: s0 [+ R
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;7 o, H" X" c& Z

4 J( E+ B4 E% U8 z   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
8 F& n: X( `/ B  G- c
5 G, _/ T0 i2 t( Z( x% Z8 a6 v4 D  I   GPIO_Init(GPIOA, &GPIO_InitStructure);
. C1 ^+ P# g# C1 s* G) c+ v$ `; R7 R9 A! m/ b' w; W$ P; w
   /* Configure CAN pin: TX */
6 r$ ]0 [3 q8 K' g, g1 p0 x
0 j6 m- z$ a, |   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
" s& Q! F/ S; g, S  [5 C
; z- d' ^& v; g   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
) c& Q9 O" w3 f; l8 P
5 l. j6 y# B7 |' Z9 f0 j6 \" a   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;3 ^3 y6 D2 N9 l' G+ f

5 H4 a2 l, E2 |8 s" f   GPIO_Init(GPIOA, &GPIO_InitStructure);% U2 |; E) m0 ~% j- r$ ]+ g  Q
------------------------------------------------------------------------! I# A# N# v9 y: y0 r

/ H9 r) _. e+ R$ I4 }; ]重定义地址1模式
1 t: W" L  G& Y
+ a3 l8 T/ @3 V! K0 D) ^/* Configure CAN pin: RX */: N6 p+ L2 ~9 H" ^8 K

7 ~4 H! a' g  X) [4 b   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
. c8 |2 e7 m" |3 N$ }7 m% m* L* c6 Z4 N* N( A* U, C# v' f
   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;+ g! e2 Z. r1 a+ G

  V4 z7 @( X0 G9 w   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;0 g* f' |0 U1 J" Y

+ G9 T1 Z8 ?6 q! w# ^. V* x   //GPIO_Init(GPIOB, &GPIO_InitStructure);0 E8 Y) R7 K& m# f) i
8 y& k9 R2 P' j) z% S# G
   /* Configure CAN pin: TX */  
1 C, w% ]. H: z1 K
* K  P5 ~. m6 u8 k5 f! {* l# Q   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;, M$ H& m# f4 n' F# V

+ I5 y1 U7 I3 C; k   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;* K+ f: E! G: L5 Z/ o; f

" p( }5 ^" I/ T$ U   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;7 f' F. ^! f% [. C3 G  ~
, i+ m+ l) p0 z& K% Y6 A# c: C
   //GPIO_Init(GPIOB, &GPIO_InitStructure);
7 |$ E8 m* y3 E! |" m6 ~- {  U* E6 c+ k" a2 s
   /* Configure CAN Remap   重影射 */
: w" p3 l  I& r: X/ x8 X  l# M0 q6 F- S4 h
   //GPIO_PinRemapConfig(GPIO_Remap1_CAN, ENABLE);- D! v( ~  _4 K' P( `9 ~
$ l' k( z1 Z4 n- S  T
-------------------------------------------------------------------------  5 S' u9 e4 K$ K! n

1 Q3 y5 N, P2 }重定义地址2模式- M' y; D, i( P- }

* Z9 w/ h) L4 e   /* Configure CAN pin: RX */
; j. z, }0 n' v. U7 P" `2 R% a
3 ]7 O1 P0 l' v4 I8 w* ~   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;$ I; w6 j1 B8 _8 u! G  d
9 t& @. s5 X7 W
   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
, F! U8 O* c5 v
  v; g5 q+ d. S4 ^/ c- ?& `   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
' t0 z3 |7 Y: a2 D; \: Z6 Q- C: k/ z
   //GPIO_Init(GPIOD, &GPIO_InitStructure);: \% R# e% o2 T; S; Y, Y" O
4 ^. _8 L, _4 u7 r' i

' b  {/ ~% m2 p8 ^* Y   /* Configure CAN pin: TX */
2 o0 P& J  a: W/ J2 M" e, c# X5 F/ j  ]  Z  I
   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
9 V' G7 z+ w5 {/ _
1 x; u' D3 \" w# u( R   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;' y+ M/ k0 \; K( c. z

3 N" F/ @2 c! R- W8 b   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
; x7 [3 O* T; O; k
1 w- B4 ]' S6 q- _; c   //GPIO_Init(GPIOD, &GPIO_InitStructure);
0 f: K- M8 M6 d# ?0 {! e2 Y+ f+ O1 O$ a) ~5 [
9 G: T6 ?8 N7 {" ]
   /* Configure CAN Remap   重影射 */& c3 `2 m* `: q

! h9 t: f8 J9 @: G, V" H0 Y# w   //GPIO_PinRemapConfig(GPIO_Remap2_CAN, ENABLE);# Y0 o3 d; A- ~$ U. {4 e
4 l; g$ y& ?3 ^0 L+ c: L
-------------------------------------------------------------------------
3 f% C9 g6 h6 Q9 B1 I# U
! R6 q1 X( C% N1 a) T设置完 CAN 的引脚之后还需要打开 CAN 的时钟:2 [; T* p& K7 S6 F2 m

$ c4 x5 B2 Z/ v, G. f) |/* CAN Periph clock enable */
' i; e) q3 o6 [. W% g" M, }+ Q
7 m: {, v- g1 x: J& A$ w, h" b  v: B   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);4 `" P4 o' y: `  E4 B# i# p) y

$ d8 B) N+ F4 o+ u4 l第三CAN硬件部分:
8 h7 {$ c( T5 v0 p/ X
' L+ {- O. W  r0 D一开始对CAN硬件部分没有过多的了解,后面经过一系列的试验,发现:
. @) p0 }( ~; H: v, t  N
2 g4 P# C% }5 @1. 如果STM32 CAN TX和RX没有和CAN收发器连接的情况下,STM32的CAN TX和RX是没用数据发出的;
/ k2 i  N* W% f* I& k; F9 v' _3 V/ G0 m
2. STM32 CAN TX和RX必须要与CAN收发器的TX和RX对应,即TX接TX,RX接RX,否则CAN没有数据发出,说明:之所以说这个问题,不知道你们有没有注意到,我的自设板CAN收发器TX和RX是反接的;
& Z8 O, V/ J% k9 |  [1 `4 X# n' J0 t" U+ e9 O1 _
3. STM32F103C8T6-LQFP48 的CAN口和USB口复用,即用CAN口是需要将USB口断开,防止有所影响;0 K3 G" k3 e4 K' ]' o

7 G' q0 N5 v, w7 @; x5 l& g+ i4. 是我本身设备问题,我的自设板用的12V电源是我自己焊接的,不太可靠,电源12V时有时无的,所以最好烧写程序的时候点亮一个LED灯,可以显示板子的工作状态;1 o! |0 _- ?2 f$ }: o$ E% Y

  A( D( }4 K" ^0 v5. 工控板上CAN收发器是用TJA1050 是5V供电的,自设板用SN65HVD234 3.3-V CAN Bus Transceivers,之前有所顾虑,怕CAN收发器不一样会导致其它后果,之后发现没有问题。" N# J4 k6 r/ r& \
# z& \, j+ D; c$ z; Y* X

- B. v/ Y1 S: O, K3 G  G7 X/ G0 v7 q% \1 Q
以上为本人的一点心得,走了很多弯路。。。记录点滴,以此自励。
$ Y3 `" }& u+ S5 n9 Q% Q; y
( v" O1 m/ E7 r( ?& O
1 v) p" M2 {3 g7 G: ]  Z
9 [( U" j# J9 ^; [3 [
7 R1 `6 a1 |  p! P# e+ ?9 A4 s$ E: f
转载自sunnyhyh; N% }+ _! j+ S/ J6 r9 i
' q5 S1 w" R) A- l5 u! b! B

3 X3 r5 j! A0 G

评分

参与人数 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管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版