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

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

[复制链接]
aimejia 发布时间:2018-6-1 13:47
本帖最后由 aimejia 于 2018-6-1 13:49 编辑 % u. C1 {! k/ W3 {/ H3 c+ Z

5 \+ q! L/ }) G; r8 s4 Z一. 开发平台与工具:. x! b7 K" x5 O$ y
4 c$ v0 g3 `! g6 y* \) s; _' D
1. 平台: STM32F103C8T6  48PIN工控板和自己设计的STM32开发板) L# ~% S( s3 Y
/ _$ q8 M) _6 S9 {
2. 软件: MDK5 UVision V5.14.0.0
( G2 M' F1 p1 K* S! F! ?" m7 Y" V7 O- ~! z
3. PACK: STM32F1xx_DFP——1.0.5(2014-03-14)  C. Y% N6 y& k0 f' e( j# d3 b: ]. T
9 s& d5 w# j$ k$ e, y
4. 其它:USB转串口,ST-Link下载器,
) s5 E: O0 D* Y* ], U, }0 h4 |' v  f( c% s) J  k7 E
USB-CAN Adapter用于直接监视CAN口发出的数据,上位机有两个,一个是EmbededConfig for USB2CAN 配置串口、串口波特率、CAN速率等,另一个是EmbededDebug V2.0监视CAN口数据;使用顺序是先配置后查看CAN数据。
+ p# T8 t- {8 U
# {( J# L, I* t! |6 S二. CAN总线的介绍简略:
, b, w4 Y; I6 Y* b4 I  k  A/ \/ o' N5 o" ^( b
bxCAN 是基本扩展 CAN (Basic Extended CAN) 的缩写,它支持 CAN 协议 2.0A 和 2.0B 。它的设计目标是,以最小的 CPU 负荷来高效处理大量收到的报文。它也支持报文发送的优先级要求(优先级特性可软件配置)。; U) Q- j5 f; _( J: `! ]
1 _8 n0 p; w. w. _
对于安全紧要的应用,bxCAN 提供所有支持时间触发通信模式所需的硬件功能。: ^# b# ^, g8 y9 ?/ j! E
' ~* V; ?4 H: L5 v0 \
主要特点
6 f4 b- v% `% b& m" U· 支持 CAN 协议 2.0A 和 2.0B 主动模式
0 v. b/ `, H! p: c) R) {9 c· 波特率最高可达 1 兆位 / 秒
0 X3 p' J, H1 j( g; C6 x3 q· 支持时间触发通信功能
/ ~' f. e- w: c' A* _4 {& T% I- I. V& B, V3 c4 p" J, k- @
发送- B1 N/ N4 `+ M( w, [" e9 J+ p3 s0 A
· 3 个发送邮箱
$ \" O, B& V2 w+ w! W' G· 发送报文的优先级特性可软件配置
+ C: G" G6 S8 p; X* l· 记录发送 SOF 时刻的时间戳
" c8 A/ a  y8 m  j# G: ?, J
' H: g/ l' c& r8 ~接收' @, \- z6 }9 }/ `
· 3 级深度的2个接收 FIFO4 _" e$ d& y4 X+ y$ H
· 14 个位宽可变的过滤器组 - 由整个 CAN 共享; e  x4 E" K2 [' m1 ~% a6 W' b
· 标识符列表
2 K1 y0 c) Y0 z6 w) p) V· FIFO 溢出处理方式可配置
2 `+ b  P( B% V9 B· 记录接收 SOF 时刻的时间戳
. ^4 n5 o9 |8 o6 q$ `
- I9 d' A9 `2 |, |5 X可支持时间触发通信模式
5 }1 E( F' `, Q' q· 禁止自动重传模式# }- ~( w0 `6 F  a# l! F
· 16 位自由运行定时器
! i' s% D: f1 H9 X0 [) t) g- W· 定时器分辨率可配置4 Y6 \* K4 m$ K% `# b5 i
· 可在最后 2 个数据字节发送时间戳
( z: B# S+ e+ R4 l' d+ c& _
: n7 l5 d! P4 }1 I管理, n. |: }% X- T* l0 ~9 o' ^& P
· 中断可屏蔽7 g5 j" I% }/ Z1 H8 t! g
· 邮箱占用单独 1 块地址空间,便于提高软件效率6 Z3 U1 ~& s$ t" X7 A* }
4 l& W; B) O! m& g; v  y1 ^
更多STM32 CAN总线介绍详见:STM32中文参考手册_V10.pdf 或 STM32F10XXX-RM0008 Reference Manual 英文版# }' }: c3 c; _( p

# N/ \, I" D) T- d三. 遇到的问题分析与解决:
% B. N; r. r% ^: [2 Q  y. d( M9 h: p
' e7 G$ ?' r# f2 l手上有两块STM32的板子,一个是网上买的MINI STM32工控板,另一个是自己公司设计的板子。二者有所不同,大致有两点,第一是串口,工控板用的是USART1 且用的是GPIO PA9(TX)和PA10(RX),自设板用的是USART2 且用的是GPIO PA2(TX)和PA3(RX);第二是CAN口管脚不同,工控板用的是复用功能映射到PB8(RX)和PB9(TX),而自设板用的是PA11(RX)和PA12(TX)。下图所示,两块板子部分原理图:4 X4 ?) h- E( s% a& I& L+ J; K
. c0 N+ Q) @+ Q9 l: @  E
工控板( \- {' A  a6 e

4 Q3 F0 e% |/ a' E
1.jpg

. Z2 b+ K5 w" }0 {8 o9 O! K自设板
: C3 |, V  S" X! Z! A6 @4 w. V7 L
! e5 H# Y3 F( j. n, I2 D1 I" P
2.jpg
* D' {4 b( R1 M( T, r. ]9 d
现在我是在工控板测试代码基础上,用到自设板上,实现PC端串口与STM32 CAN双向通信,要做的是将USART和CAN口的GPIO配置对应到自设板上。
. s5 q$ Z: g* Y7 v$ C+ b
' @- x, G$ H( r! K首先,串口GPIO配置:
- c- f3 ?& p6 n, ~9 v  Y
4 f8 o5 S7 c! Y# L+ m' d: @( w$ _工控板
/ y- L) R& [& t, `2 m# v" o
  1. [objc] view plain copy  T0 `8 c/ V( ?* y0 |, Y$ w# N
  2. void USART1_Config(void)  / d( u+ w- F0 K5 J, Q
  3. {  ( P* x  a7 I/ V. b1 X$ q9 O  w
  4.     GPIO_InitTypeDef GPIO_InitStructure;  
    + k) _6 i: q5 L# P& j7 s7 j( N1 t
  5.     USART_InitTypeDef USART_InitStructure;  
    8 [  a4 n9 Y( Q( i* _! y& |3 C
  6.   
    ) c( l/ V9 N1 a; b# n: z& e
  7.     /* config USART1 clock */  3 h! t) Y" H* ~
  8.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);  
    ) }# W5 r7 `0 B6 f- l
  9.       5 M- b% L5 W- y/ S
  10.     /* USART1 GPIO config */  
    ) j4 _" e) f& A- c
  11.    /* Configure USART1 Tx (PA.09) as alternate function push-pull */  
    6 P  V0 e# {* W4 Q
  12.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  
    % C& v9 x% B: {
  13.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
    % _* q' b9 K$ I' t& |: R0 }" A
  14.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    + V& w7 a' K# s  U& {8 l* \$ d
  15.   GPIO_Init(GPIOA, &GPIO_InitStructure);      
    % c* E( T" |3 p, s
  16.   /* Configure USART1 Rx (PA.10) as input floating */  
    7 R4 Z3 Q9 R0 H% v
  17.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  
    % l3 M% [( n* l
  18.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
    * a" ?8 w0 b% U* n9 W
  19.   GPIO_Init(GPIOA, &GPIO_InitStructure);  9 @) g" Z" `9 q) m/ u
  20.         6 Y: ?" a0 r' r7 @6 K* j0 f. m: {
  21.     /* USART1 mode config */  # b  W+ W6 {9 q6 g
  22.     USART_InitStructure.USART_BaudRate = 115200;  
    % c# a* ^3 ]# E' M1 X
  23.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  , T% c) D& L9 \/ J# p
  24.     USART_InitStructure.USART_StopBits = USART_StopBits_1;  8 M, X! M6 t! Y# z8 z/ d
  25.     USART_InitStructure.USART_Parity = USART_Parity_No ;    A- `5 Q- O# ^# \
  26.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  
    0 \9 z) ?/ @% L3 D( w
  27.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  
    ) {% z) t6 {, ], V& K. w: [- u
  28.     USART_Init(USART1, &USART_InitStructure);   
    9 |. [/ }% e# @
  29.   USART_Cmd(USART1, ENABLE);  3 o# R# E# {' c3 z' B6 j* f9 O& L* J
  30.       
    ! [5 G; o' S8 b. z4 T" N# d
  31.     /* Enable the EVAL_COM1 Transmit interrupt: this interrupt is generated when the  + m5 ]( {  v4 H" g
  32.      EVAL_COM1 transmit data register is empty */    6 n' M: c$ j) C9 |) G  e* L
  33.   //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);  2 a( A/ x& Y5 _0 \/ \( s3 c( b
  34.   4 _8 a! N1 G1 f- q7 _: K
  35.   /* Enable the EVAL_COM1 Receive interrupt: this interrupt is generated when the  
    5 e1 P1 f7 n$ R5 Z% V  ~
  36.      EVAL_COM1 receive data register is not empty */  / s5 x( q' I% Z+ ?& m; q: R  ]
  37.   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  
    9 @. V( l8 r1 Y& z
  38. }  ) P* r' b# ~) Z3 ~
  39.   
    3 U  E; u2 B+ e: W! w
  40. /***************USART1 ÅäÖÃÖжϷ½Ê½·¢ËͽÓÊÕÊý¾Ý******************************/  
    7 w# b+ n3 }* p9 I
  41. void USART1_NVIC_Configuration(void)  
    ; m2 p1 Y) Z# t' a8 Q
  42. {  
      g, R0 p9 g: G9 E5 N# B
  43.   NVIC_InitTypeDef NVIC_InitStructure;  
    . N$ _. W* H$ U8 q) ?9 j, {' r
  44.   ! c- x) F% q: [5 k+ l
  45.   /* Enable the USARTx Interrupt */  5 y; O& A9 c) k$ b
  46.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  7 y( S! u& N9 r, _
  47.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
    , L) l# e7 F' S8 i0 y5 e1 R
  48.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  3 Y: C* O' I  T
  49.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    1 E9 {; h. C  o0 s1 e0 T
  50.   NVIC_Init(&NVIC_InitStructure);  
    ) }+ X. D- [3 s9 {3 _4 S* a1 z4 |
  51. }  6 r3 g1 G3 N& n9 E, I* ~
  52.   
    ) i# K& N) y+ X+ h* t
  53. /****************USART1 ÖжϺ¯Êý***************************/  ) q2 G  z$ q" y2 q3 }
  54. void USART1_IRQHandler(void)  
    ) \( f8 x0 {) z
  55. {  
    1 Q9 R% R, _( {3 \$ ?/ x# P
  56.     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  4 o/ |+ F( k2 `
  57.     {  : ^: E1 Z7 T. ]$ d8 v: a
  58.         RxBuffer[RxCounter++] = (USART_ReceiveData(USART1));  7 R+ I9 f4 D% \0 n3 n2 Q) G, ^
  59.     }  
    6 o+ B9 w6 m5 Y" A: N
  60. }  
复制代码
USART1_Config()用于USART1的GPIO配置,配置到9 ~- ^8 J8 |# B3 Q, M2 c6 n& ]
*          | PA9  - USART1(Tx)      |6 P$ j% {8 F$ r
*          | PA10 - USART1(Rx)      |$ a) E8 O8 `1 h7 K7 p1 s
*           ------------------------! H. {, x5 y) \9 E6 B" r) _
USART1_NVIC_Configuration() 用于USART1设置中断方式接受发送数据
& D. x; G* M* R; J) I' R( K% R" U6 V$ T# \0 ?
USART1_IRQHandler()用于USART1中断接受函数
  |% a: B- i: y: O& Z
2 S+ O+ N+ o& [7 ~6 M: X6 H自设板6 e/ T4 G" A' l# R
  1. [objc] view plain copy
    / j5 O! t- E; c
  2. void USART2_Config(void)  
    7 v( s) @7 ?5 M/ e; D
  3. {  & o" C: ?: x8 Y8 r3 r
  4.     GPIO_InitTypeDef GPIO_InitStructure;  
    : y7 c/ x. R5 z- K+ N) P% W
  5.     USART_InitTypeDef USART_InitStructure;  & S6 T, m1 p2 a" L* |, a
  6.   
    ! v2 \& I6 z/ }  `: J3 C% Z
  7.     /* config USART2 clock */    s& O# e/ {+ w2 ^& J
  8.     //RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);  * T6 Y. ]0 Y8 G  a
  9.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 , ENABLE);  
    9 y/ r" Z' S  M% e
  10.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  
    5 u' i5 t- s- ~! w3 ^) S! `, {
  11.       5 f6 X! ?  M/ q# ]8 P
  12.     /* USART2 GPIO config */  
    " \  J- Q4 {* T5 F
  13.    /* Configure USART2 Tx (PA.02) as alternate function push-pull */  6 R* q) {% }) z9 r
  14.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;  ( e2 ~) |0 ]# u5 k
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
    ' Q/ V3 s6 d& k. `% p2 u: R7 G( q
  16.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  : D( l3 N! J2 G2 G9 ~
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);      ( E* S) f1 w  \5 b
  18.   /* Configure USART2 Rx (PA.03) as input floating */  
    ' j8 d& A' \# h& `+ i
  19.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;  ; K. O# h! W" V! r  K# M; |% t+ |
  20.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  ( t% x. T" T/ m2 Z
  21.   GPIO_Init(GPIOA, &GPIO_InitStructure);  ! c' h% j% k! ]* H9 z
  22.         6 s: ?% i- s, h- i6 K8 k8 Q. Y7 B
  23.     /* USART2 mode config */  
    : G1 \! |; V, K
  24.     USART_InitStructure.USART_BaudRate = 115200;  , o  l, h- x- `9 }7 v+ N4 h: \; L
  25.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  
    ( z$ C1 }2 m% b" I8 F
  26.     USART_InitStructure.USART_StopBits = USART_StopBits_1;  ' ^( u" F3 K6 ~. X2 D
  27.     USART_InitStructure.USART_Parity = USART_Parity_No ;  : k; ~: R% I: \$ v7 V
  28.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  , a& {0 j5 {5 Z5 I2 r" k/ |/ P
  29.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  . j" g3 o2 w9 e# A" e4 \* i
  30.     USART_Init(USART2, &USART_InitStructure);  
    3 y. D9 A8 Y9 [9 v. B. ?6 n
  31.     USART_Cmd(USART2, ENABLE);  * x& D3 f& g8 e  y, q6 }. l4 W
  32.       - R+ q1 |/ n, p3 Z# f- i
  33.     /* Enable the EVAL_COM1 Transmit interrupt: this interrupt is generated when the  - |0 |# f& U) x) F% y) B
  34.      EVAL_COM1 transmit data register is empty */    5 f# U2 |% b' U/ W" |0 Y) f
  35.   //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);  
    : E2 e. `$ B* @5 U
  36.   7 ]4 t) P* d3 X
  37.   /* Enable the EVAL_COM1 Receive interrupt: this interrupt is generated when the  
    . @. V) N* A; a- K5 z' N. h
  38.      EVAL_COM1 receive data register is not empty */  ( T* q) I! ]" g. r
  39.   //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  
    % Z$ Q' K) e# y+ j
  40.     USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);  
    # X/ F4 t. W# S$ V
  41. }  / \2 \* L' P) ~( G2 U1 D8 _
  42.   3 g$ V. t0 B) ]% x* R/ u
  43.   
    . C. [, A6 J: z3 z$ T
  44. /***************USART2 ÅäÖÃÖжϷ½Ê½·¢ËͽÓÊÕÊý¾Ý******************************/  
    & Y% m4 A0 i  D* {
  45. void USART2_NVIC_Configuration(void)  . g  h0 L, T3 Z2 Q2 M
  46. {  % Q9 ?8 Y' R! ^: K& ^
  47.   NVIC_InitTypeDef NVIC_InitStructure;  0 L0 Q# m8 F4 I, E! W
  48.   
    / {4 Z" U- p# C2 z* N# b
  49.   /* Enable the USARTx Interrupt */  , s0 J3 W# }4 N: i. |# ~) _+ s% T
  50.   NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;  
    ) i/ [5 W2 h. u1 v. n$ g  k1 M
  51.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
    1 h7 W* Y, A. p2 w- I
  52.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
    & h. w0 t) i9 v% Z( t
  53.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    * V7 Y6 `  K$ J+ q0 E7 s
  54.   NVIC_Init(&NVIC_InitStructure);  
      V+ t' `! Y2 c- a# b8 c
  55. }  
    ! {1 Y7 h+ ^& a
  56.   
    - A' e& N% W* |% A& h  E5 l2 t
  57. /****************USART2 ÖжϺ¯Êý***************************/  6 u/ A2 F( I: F& T- `6 {! _0 U! o
  58. void USART2_IRQHandler(void)  ' r2 X3 `3 T; J5 V
  59. {  
    7 h4 s: X9 ^, b' F! H" g5 U
  60.     if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  # n# ]- Z0 B3 N
  61.     {  6 |# P9 `3 e& a) A7 Z5 C3 W
  62.         RxBuffer[RxCounter++] = (USART_ReceiveData(USART2));  - g/ }$ N9 z0 G  N* p; I+ Y
  63.     }  
    0 E- t- L" g! z' @, O/ ^
  64. }  
复制代码
USART2_Config()用于USART2的GPIO配置,配置到; j0 e2 @+ ]! q& a; L8 g: P
*          | PA2  - USART2(Tx)      |
& l( J! K6 v1 g *          | PA3 - USART2(Rx)      |5 c# Y+ d7 z4 @& T* @
*           ------------------------
. |/ `2 a* d2 n: n+ q) n* K- i3 R
USART2_NVIC_Configuration() 用于USART2设置中断方式接受发送数据
+ A% e  Y2 {% G! d$ Y. C, b1 T* D) g$ A8 ]5 M* L" x% {
USART2_IRQHandler()用于USART2中断接受函数
& N9 E( s! P. u" j* s/ D  ?$ }5 @2 O) |) e4 o  K7 k$ v0 g) O
然后,配置CAN口GPIO4 v0 u- V! n' |/ h' b- l% n

( r9 q- F7 ?4 S, U9 x工控板
& g8 c9 j' _. r7 M+ X
  1. [objc] view plain copy1 H  @& V% @, d3 A+ m
  2. /*CAN GPIO ºÍʱÖÓÅäÖà */  : d; w+ N! F/ u  Z
  3. void CAN_GPIO_Config(void)  , R9 U5 M$ Q0 h# u' F
  4. {    @2 J  M8 t% \# D
  5.   GPIO_InitTypeDef GPIO_InitStructure;   4 J" \9 K6 E  }( ~( r1 V5 p( A
  6.   /* ¸´Óù¦ÄܺÍGPIOB¶Ë¿ÚʱÖÓʹÄÜ*/     
    & T% t; i6 ~8 P$ C  S5 e6 b! D
  7.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);                                                                          
    : J5 p9 w* C3 Y' u- f+ k! t
  8.   4 N% _( ~' H' q& F9 M: P
  9.   /* CAN1 Ä£¿éʱÖÓʹÄÜ */  
    ) ]& g! d( x, B; W
  10.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);   + ~. a+ Y: O; @6 q
  11.   2 \  U* ^: T! t7 s# L8 U! z
  12.   /* Configure CAN pin: RX */    // PB8  
    1 r$ P$ h( f! j! h" r0 L0 @- K" t
  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;  
    ( ?/ E( H; L4 a, U# M1 q6 _
  14.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    & ]5 h9 b; X# l6 S
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  // ÉÏÀ­ÊäÈë  
    9 i% a8 t4 J( ?- d
  16.   GPIO_Init(GPIOB, &GPIO_InitStructure);  * W: s& b2 U1 }9 g, Q. Y
  17.     ( Z. `) {1 N# |* G7 h
  18.   /* Configure CAN pin: TX */   // PB9  
    ' {) L& a  {7 ~8 o
  19.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  
    : ^: G2 f' R8 Z0 F$ N: i6 w1 H, Z
  20.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // ¸´ÓÃÍÆÍìÊä³ö  
      T9 d: y$ _6 P8 |" E5 \$ u) Q: |
  21.   GPIO_Init(GPIOB, &GPIO_InitStructure);  
    0 q; x8 A% @9 i, w
  22.    
    3 D* t, K( E% i  ?) p/ h/ R; ]
  23.     //#define GPIO_Remap_CAN    GPIO_Remap1_CAN1 ±¾ÊµÑéûÓÐÓõ½ÖØÓ³ÉäI/O  
    / @0 A; m: F, t2 J8 `
  24.   GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);  
    7 L1 o2 R; T. d
  25.   
    3 z7 ~$ T2 V. m) Z! b: g
  26.    
    8 F3 V8 Y0 M( O- A( m) |& \
  27. }  
复制代码
自设板
4 ^+ d# v( J9 ~' n& h0 d
  1. [objc] view plain copy
      P" E: e) m- C0 p! `- l3 P8 c
  2. void CAN_GPIOA_Config(void)   
    6 [. }+ F2 F' A, d: z# M
  3. {    6 H. z" H3 ~0 v! Q1 n2 B
  4. GPIO_InitTypeDef GPIO_InitStructure;       4 V' f2 b8 e" Y. A
  5. /* CAN Periph clock enable */   
    - E. h& M* F# B$ t
  6.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);    0 K- k/ o) l; o+ V
  7. // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);    8 y! z. A$ w0 v7 Q
  8.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);    5 Z# F2 _' c9 n' I! G' b2 a0 G
  9.    
    - T! l3 n& S( P% d
  10.   /* Configure CAN pin: TX */   
    9 ]4 k: D0 G* \  v2 U
  11.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;   
    & S, i+ z( k6 d) S. `1 N& m
  12.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    - r  A7 u' g! |) y( ~
  13.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    % H1 a6 {! c! a1 q- J% A  i. r8 F
  14.   GPIO_Init(GPIOA, &GPIO_InitStructure);      
    + _+ c; [6 v! p8 N9 G0 f
  15. /* Configure CAN pin: RX */    7 G- z: m3 ^' o$ k5 Y0 T) `; V& C
  16.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;  4 A: }+ I7 a* Q+ I
  17.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     / h; V- u& ^, g8 j! f& Y
  18.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;     * l" f: q5 F6 W
  19.   GPIO_Init(GPIOA, &GPIO_InitStructure);       ; q# Q8 z/ H) T/ ?/ l
  20.   //GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE);   
    ' J3 g! e9 P; B& B
  21. }   
复制代码
/******************************************************************************************/7 ]- i2 m: V" Y8 I) u! Q% f
就是这里!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
, o" @( I0 {7 e5 z出现几个小问题,但是却是致命的问题!!!!!!!!!!!!!!!!!!!
# w3 P, C  f( s
8 w" w2 F8 ]; F4 l/******************************************************************************************/- `6 B+ D. C& p! r1 n7 E
* X$ M' ?' t0 ~& G$ R" O5 b& h9 |
第一配置GPIO_Speed:3 ^9 x* l7 H. ^
' i& j! v) f. s$ w8 I7 s
[objc] view plain copy$ ~% \  }9 J0 Z% W$ S# p
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  //配置GPIO_Speed为50MHz  ( W/ a' _+ b, y+ k' D8 W
如果配置GPIO时,省略这一步,会导致CAN口发送不出数据,工控板的配置是放在LED 的GPIO配置中,一开始忽略了这一点,之后用排除法试出来的;/ _0 Z/ i- n5 i: b  J7 o! x
/ Y4 y; a; j: \$ p9 g/ d
第二配置复用功能和映射与否:
1 A% B: O# J! x; W, g
  1. [objc] view plain copy
    & P' G4 g" Q% N
  2. // RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //复用功能时钟使能  
复制代码
  1. [objc] view plain copy
    ' |+ Q9 q% h" R( o
  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
复制代码
上面两个被注释掉了,是由于:  
$ e2 l, C# Q- X* F1 C用PA11和PA12 用的是CAN的默认端口,而用PB8和PB9是用CAN的复用功能重映射端口。
0 E; `! N7 y7 H) D7 ?" X5 k! `+ r6 o/ S) [8 P
  1. [objc] view plain copy
    5 h! J; I3 J( L6 [& d8 n0 F
  2.   
复制代码

9 V' G+ f- e, x, y7 |
3.jpg

  w+ f9 a0 T* w! e8 s具体:
+ o% N( _# ~' @  i3 n6 Q-------------------------------------------------------------------------
$ h/ R" I. p; M8 ?; Z9 [' n! y2 t) ]# D
默认模式
# o6 ?$ y1 N- ^. t: l
: q! ?- P4 S% @% ]3 l   /* Configure CAN pin: RX */2 k# X6 m* K! R8 D

. i) v3 G& P! |2 l0 @2 Q& _GPIO
4 O2 E; z$ k/ u, f. l
) [  N2 U+ Z: Q, V3 \_InitStructure.GPIO_Pin = GPIO_Pin_11;6 _$ T+ i4 H9 p3 M( F0 c5 v& H6 U
: w' h/ q. p' F6 ~7 L7 x* g
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+ f! Q" ?2 f( K1 O" Q  }: X# q5 Z# Z" `+ M5 [# b8 [6 {) T
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;7 l+ z. `: Z* H2 F) R5 X

) X  T+ w6 M+ r. |" U( q   GPIO_Init(GPIOA, &GPIO_InitStructure);6 }* |# n6 n: m, O6 c

) V+ O* G# n2 Q! {   /* Configure CAN pin: TX */; L8 h. `, A; s& J4 a  U" B

) e8 O" r3 H" y# U   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;! u8 V' j& m; u! H- ^
; Q+ q* U% ?" ^- P+ `3 L1 q( Q
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
$ K0 h: ~8 W: O
3 _2 f( R" `' U$ L   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;) T) ], ^: u5 d9 ^$ H
8 W, B* b8 M- w6 `$ k; y
   GPIO_Init(GPIOA, &GPIO_InitStructure);, n& q9 i3 j- C+ y  e( g
------------------------------------------------------------------------
) ?3 M) u4 z' w7 p; x' Q  M( \& x& j/ v. G
重定义地址1模式+ ?/ @* O7 ~6 ^2 l- q  C1 I9 l

* @9 C- o9 |$ x) l1 |/* Configure CAN pin: RX */# ~9 a  b3 @1 m3 v
4 y, T" {" E( P" C* H
   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
% i- o9 Y/ v. Z/ C: [; M4 W5 O7 F+ b9 ^; |' N
   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;, R' I9 s$ T( I

" b; r2 J: B" n3 I2 T" j" y   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
$ }8 |1 t; ~, [! n+ d
- u7 g- S) I% C- h% o   //GPIO_Init(GPIOB, &GPIO_InitStructure);
& L1 o. X/ `  s0 p' x% B% H5 ~3 o+ Q" ]0 y
   /* Configure CAN pin: TX */  # S4 ?' u* O  ?' v
* z3 [" m, ^& `8 {' P: M4 t
   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;+ g- o" m! K9 A8 @6 G4 i  y! k$ X( [
+ g# }' V- s! ?  O) W, O1 f% g
   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
: d% W3 `  x1 N; T* y4 d* V1 Y" b# ]/ ]; N+ a
   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;3 I; K/ y2 U& g- b

6 T% Y3 @- w. l  o  k0 B   //GPIO_Init(GPIOB, &GPIO_InitStructure);# l) O# q+ x1 C5 n! k. ?' {( p

# k, p0 `: \8 T' H7 E# E   /* Configure CAN Remap   重影射 */# w0 s. B8 z! e5 _# m2 v
. ~- E1 P* b+ x  F/ u
   //GPIO_PinRemapConfig(GPIO_Remap1_CAN, ENABLE);  H& l/ n- v) k0 ^& A3 @
+ F0 b& ~- N5 L# M
-------------------------------------------------------------------------  1 o7 v; I+ z8 Q0 k# D- v/ y0 {

# C; S! w! o% C重定义地址2模式0 F7 w4 A) L" n( [; {  q9 p
$ D1 a, b+ a$ T$ ~; _7 p
   /* Configure CAN pin: RX */  l. `- ?$ J8 _7 j3 `

5 z1 A) C5 V: [2 w   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;8 X1 h+ e5 n, N6 R( M

6 H+ h( p/ L. O! O0 y   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
) U6 w- X# r& ?5 B( G/ z2 i$ I
* g1 z! b5 i  U   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
+ z; v3 s- @3 Z7 I  b4 t  t' Q& x: u' L$ r
   //GPIO_Init(GPIOD, &GPIO_InitStructure);/ n/ T. v. a' i7 `  C! |" U- }0 a( a
$ O& [" {8 o3 f/ e* R4 S
( g' x" x! x+ T  ?% \
   /* Configure CAN pin: TX */& ^8 N: l+ x- `' z9 k& p* H
+ U8 w* A5 |. j( f8 z! @6 J
   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
& a- R/ H: u& f# ?* m
1 N3 G: L0 K: Y  G   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;& R$ Y: [/ s% B- X

) x! l4 U' @( l( j8 Y  Q5 H   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;& }0 W$ m3 `2 g. Z& G  c
5 v9 l. ~: Z  L5 {3 u1 T2 [) u
   //GPIO_Init(GPIOD, &GPIO_InitStructure);7 i0 h; ]) b0 t9 l

' r) d0 T" J; M: ?, s) }# \
6 t. I6 |6 g, Z1 \" W: N   /* Configure CAN Remap   重影射 */
' J8 U# H9 G" f2 N
' {! I& w8 C2 @- _" i   //GPIO_PinRemapConfig(GPIO_Remap2_CAN, ENABLE);
2 Y, A* z# D' ?* b9 j. |  R# r! x/ t3 f: b! U5 ?
-------------------------------------------------------------------------6 w+ _- v& x' K; O( ^" N, A2 u

( e6 N- K( C  A9 a! D; u. d/ m设置完 CAN 的引脚之后还需要打开 CAN 的时钟:
9 |  o" D: s5 u& ~% c5 D
9 x, i! i0 f" W" K9 v0 m/* CAN Periph clock enable */1 o2 S/ \: X; d8 A" ^0 ?' R

# A0 R9 V9 ?$ k$ T   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);! m, C" v% h, M$ u0 S# n3 U0 ]

3 ~7 l& R# f( _: {第三CAN硬件部分:7 _$ y# y5 X8 ~
% _7 x# }* i( K8 s5 B
一开始对CAN硬件部分没有过多的了解,后面经过一系列的试验,发现:( L# s; v2 ]6 q# z: ]9 {0 ~

/ b/ k/ g. h, e  w- ?1. 如果STM32 CAN TX和RX没有和CAN收发器连接的情况下,STM32的CAN TX和RX是没用数据发出的;: m2 ^8 O( ^7 p  L6 c

3 U- w! u7 p8 k# M. E* ?1 S4 o$ @2 y2. STM32 CAN TX和RX必须要与CAN收发器的TX和RX对应,即TX接TX,RX接RX,否则CAN没有数据发出,说明:之所以说这个问题,不知道你们有没有注意到,我的自设板CAN收发器TX和RX是反接的;) R% ^% Y) y# x) e! ^
* j8 x6 r9 ]/ S0 ~/ b0 i  M( B
3. STM32F103C8T6-LQFP48 的CAN口和USB口复用,即用CAN口是需要将USB口断开,防止有所影响;
* F* h3 Q% i+ a6 L' P: q& ~1 a
) R# P0 G8 P4 o4 q/ N" ]3 z9 ~4. 是我本身设备问题,我的自设板用的12V电源是我自己焊接的,不太可靠,电源12V时有时无的,所以最好烧写程序的时候点亮一个LED灯,可以显示板子的工作状态;
' B. r4 s- B2 z* F8 Z8 ]) R% g
4 O/ Q$ \  `0 s; a( |5. 工控板上CAN收发器是用TJA1050 是5V供电的,自设板用SN65HVD234 3.3-V CAN Bus Transceivers,之前有所顾虑,怕CAN收发器不一样会导致其它后果,之后发现没有问题。0 I) C% H: v" @" J1 Y

# U3 O# J' H' x1 q/ i; m
$ u& W* C( |: B7 V. [& v9 S! o  u
  r) g9 C* ?! X) ^  T# E0 c& N以上为本人的一点心得,走了很多弯路。。。记录点滴,以此自励。7 N3 d) U" r6 B

5 A* P  r1 j2 d  H& G  X: F. L9 p' V# i
; ~- ?6 K" N; w- ~2 H) n
. U2 e1 v3 J7 z' o" T# y/ K" ]. g

& V7 ^( T5 M& O9 _1 W转载自sunnyhyh
6 o1 g5 ^, R3 i- ]2 `# g
8 i  D8 S$ E4 a6 y7 c- k- S, k  w( C: v

评分

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

查看全部评分

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

举报

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

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版