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

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

[复制链接]
aimejia 发布时间:2018-6-1 13:47
本帖最后由 aimejia 于 2018-6-1 13:49 编辑 ) e; t* \9 P- O- @6 o, ^% |7 l
* b% Q# ?& Y; R! {2 C: _: W
一. 开发平台与工具:  g  ]2 z- d% j9 p
6 A8 T. e2 S& X/ X
1. 平台: STM32F103C8T6  48PIN工控板和自己设计的STM32开发板
- ]0 _# n3 g# b6 M) }- ~3 g! K6 N
0 ?* P  K! y+ J! M! J7 e2. 软件: MDK5 UVision V5.14.0.0
1 }: g0 P5 r: I( V# P% \  x# |! U3 `5 Y3 i
3. PACK: STM32F1xx_DFP——1.0.5(2014-03-14)9 c9 g% \% U! N" q8 L

9 z/ x& ~( M( g& R8 [4. 其它:USB转串口,ST-Link下载器,
. b$ X2 H% x  c1 s& f& n8 `  c4 m1 N5 ~- z: d$ W/ e$ Z9 g. v
USB-CAN Adapter用于直接监视CAN口发出的数据,上位机有两个,一个是EmbededConfig for USB2CAN 配置串口、串口波特率、CAN速率等,另一个是EmbededDebug V2.0监视CAN口数据;使用顺序是先配置后查看CAN数据。& F5 Y* l, i0 x
" X- c; Z$ [; i/ D, \6 [/ N
二. CAN总线的介绍简略:
( ^4 r$ n7 s- J  X+ v/ F5 I& M) g
, }. l7 p& R9 Z8 W3 y6 ubxCAN 是基本扩展 CAN (Basic Extended CAN) 的缩写,它支持 CAN 协议 2.0A 和 2.0B 。它的设计目标是,以最小的 CPU 负荷来高效处理大量收到的报文。它也支持报文发送的优先级要求(优先级特性可软件配置)。
& K' D! Q; s. f3 j; K
; W0 v4 P* F+ n; K1 s5 b对于安全紧要的应用,bxCAN 提供所有支持时间触发通信模式所需的硬件功能。
) x) |4 ?9 d+ q4 b; x$ L# p$ T9 F+ P% _; H* C  r( I4 n' L# a( A
主要特点
8 t/ @4 v/ D# G* Z" u7 Z· 支持 CAN 协议 2.0A 和 2.0B 主动模式
! W9 g. v  W; h" B' j· 波特率最高可达 1 兆位 / 秒- S7 |, \# ~' F: v$ |+ y
· 支持时间触发通信功能) J/ G- W5 T, ~: y/ J
/ p4 {, s1 U- E4 e- g' l
发送* D( s* F) i! t" e
· 3 个发送邮箱% f) q  q  ]. O" Z% R; c! V
· 发送报文的优先级特性可软件配置
; t* g1 [+ m' U4 R· 记录发送 SOF 时刻的时间戳
( Z" _  h$ Y' m
3 c2 m9 E( h/ x% F2 A接收" X5 l4 n4 C& A7 F4 @" `, c' b
· 3 级深度的2个接收 FIFO! @$ ~4 K. O- n+ |7 E2 e$ [
· 14 个位宽可变的过滤器组 - 由整个 CAN 共享0 e/ j) [) m7 {% z% {( }
· 标识符列表
0 W6 `* G6 i6 _' [1 F% E· FIFO 溢出处理方式可配置
) U  ?8 x2 P" R0 _· 记录接收 SOF 时刻的时间戳
5 m  q2 |# {7 w4 B+ R. g0 V3 V: t
可支持时间触发通信模式
- p$ S1 p- ?' }: S2 w· 禁止自动重传模式! s% q4 F1 L+ c& C' }8 o
· 16 位自由运行定时器
' r+ m( t5 O3 k* q· 定时器分辨率可配置7 s8 T5 M" L# }) h# }
· 可在最后 2 个数据字节发送时间戳! m+ G5 y( f' e

- D$ _9 F5 [  i8 c/ x管理
. c- c$ i4 v5 R" ^1 W· 中断可屏蔽2 v7 R% @7 W  \9 h
· 邮箱占用单独 1 块地址空间,便于提高软件效率! k. E4 s  y5 ?# M- q0 w* ?
  i' k3 i+ L& K  o2 j
更多STM32 CAN总线介绍详见:STM32中文参考手册_V10.pdf 或 STM32F10XXX-RM0008 Reference Manual 英文版, v9 d* u9 I/ i& |3 K

! R, W8 [0 ~  I$ S2 b, x三. 遇到的问题分析与解决:$ F! ^/ o) I( I7 ]; N2 }) w3 \

8 a& f+ w" r0 \) Z, Q  x0 ~手上有两块STM32的板子,一个是网上买的MINI STM32工控板,另一个是自己公司设计的板子。二者有所不同,大致有两点,第一是串口,工控板用的是USART1 且用的是GPIO PA9(TX)和PA10(RX),自设板用的是USART2 且用的是GPIO PA2(TX)和PA3(RX);第二是CAN口管脚不同,工控板用的是复用功能映射到PB8(RX)和PB9(TX),而自设板用的是PA11(RX)和PA12(TX)。下图所示,两块板子部分原理图:
  e: G% J, L2 j  r
! [1 a4 u" k. P* m& I& H( M工控板
" m; O/ t  F( x4 S0 l% A; b9 N; l+ g! z: y  |$ R
1.jpg

3 X4 ]0 ~+ i, f2 b0 o0 J2 z, H自设板9 V  O  k8 L5 Z# W
: s1 @% E- U7 v. B) m8 d  U- C
2.jpg

8 r# s# s6 }  n7 M0 |. a' y' h4 v现在我是在工控板测试代码基础上,用到自设板上,实现PC端串口与STM32 CAN双向通信,要做的是将USART和CAN口的GPIO配置对应到自设板上。
9 B1 H7 @! d- m4 V$ N4 K' V
0 Z) G1 g# i* P; ]' K- e2 m4 V首先,串口GPIO配置:
6 w1 ~4 g0 n& S: T. h# @
7 I. n% w9 I6 |. Z) i: f% e工控板
5 u/ t" C; O$ u# r
  1. [objc] view plain copy' n' R- v' N' H: [* @
  2. void USART1_Config(void)  
    0 Q) i! `+ ]+ }* n! p
  3. {  ' }+ t! H0 U* s2 i& Z2 r
  4.     GPIO_InitTypeDef GPIO_InitStructure;  4 K! J4 [9 z- g; _: Z+ [
  5.     USART_InitTypeDef USART_InitStructure;  
    ) |2 w" ~& E0 `$ h
  6.   . \$ o3 g. s1 r# {1 j1 x
  7.     /* config USART1 clock */  + L/ q9 t' H/ W" l* @" {* _
  8.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);  
    4 _, t; F. J' {* R. o! m
  9.       
    * o  @6 m9 A/ X/ W# t
  10.     /* USART1 GPIO config */  / ^6 w3 Z2 L& J7 d
  11.    /* Configure USART1 Tx (PA.09) as alternate function push-pull */  : `2 |% |+ r% [. _9 N5 {) K
  12.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  : g; G; P: ]6 e0 c* G0 R
  13.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
    + l3 H+ ^! T; q) f. n- }
  14.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  , N1 M) i2 h" v
  15.   GPIO_Init(GPIOA, &GPIO_InitStructure);      7 e0 w4 H( D( Y) c7 G) `  w* X
  16.   /* Configure USART1 Rx (PA.10) as input floating */  
    5 O# S! U$ N' ?8 \* {  s% P
  17.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  4 R& n9 E$ z1 |/ I
  18.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
    ' X+ @/ \6 k4 P$ U+ ?# U9 b
  19.   GPIO_Init(GPIOA, &GPIO_InitStructure);  
    : x5 ~; a8 c- k. t; M
  20.           U: b. ^! e: j/ T% B1 p8 E
  21.     /* USART1 mode config */  . C* k( G5 H5 c* o  t! ?! j
  22.     USART_InitStructure.USART_BaudRate = 115200;  
    $ g9 @# x9 z6 e; W3 B
  23.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  
    $ B, N) E$ D3 q5 W8 ?
  24.     USART_InitStructure.USART_StopBits = USART_StopBits_1;  
    8 Y1 R1 S0 h. ]+ m/ i2 z
  25.     USART_InitStructure.USART_Parity = USART_Parity_No ;  
      W, C, C9 }. n% @: X' P
  26.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  ) G8 s$ c% `$ ?1 B' K
  27.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  
    : |2 F) w3 V# |! w
  28.     USART_Init(USART1, &USART_InitStructure);   
    2 W( ]2 B: R2 H$ d* S5 z% _' R6 z
  29.   USART_Cmd(USART1, ENABLE);  : N0 C# K9 y# }2 I0 L; i8 B
  30.       
    4 {* [" V& h! U! g
  31.     /* Enable the EVAL_COM1 Transmit interrupt: this interrupt is generated when the  
    ) a, e% ]$ c4 K" g! t+ s6 W
  32.      EVAL_COM1 transmit data register is empty */   
    + b) a! Z# N" ]0 y: j9 y
  33.   //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);  
    2 W* H! _4 K8 x' }) v
  34.   % P5 K/ C7 p! H; H. I9 N
  35.   /* Enable the EVAL_COM1 Receive interrupt: this interrupt is generated when the  
    9 l  @: J9 A6 W8 W
  36.      EVAL_COM1 receive data register is not empty */  " m, N0 k# `" `. {  E* e2 z  c
  37.   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  " y* y, b; U" R" f% N/ i
  38. }  % c7 j- G, y2 q
  39.   
      }1 U& D% @$ \. Z
  40. /***************USART1 ÅäÖÃÖжϷ½Ê½·¢ËͽÓÊÕÊý¾Ý******************************/  - x" S- v# b2 S0 M. a8 v0 y0 H1 L
  41. void USART1_NVIC_Configuration(void)  1 `, p5 ]- c) J& W8 B! {# H
  42. {  
    + F/ S& J( x/ W3 I* ]
  43.   NVIC_InitTypeDef NVIC_InitStructure;  
    ( p# l7 {" ~. a, U( v
  44.   4 u' G9 C5 I- ~6 y" N1 k* i5 e
  45.   /* Enable the USARTx Interrupt */  8 P. h0 ^' ?' e% Q3 Z$ r
  46.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  
    # W, e9 A: O) ~+ W' Z* s. u
  47.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
    ' `9 y5 f' [9 P: o  Y
  48.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  6 q) r% q- r5 g" h; }
  49.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    ! B+ g4 t* F7 H& L: W) m) S/ ?& _
  50.   NVIC_Init(&NVIC_InitStructure);  
    , V! s* H8 D9 ]) G2 q
  51. }  
    ! ]) k% n  j" k3 w2 U; `
  52.   
    $ `$ ?' H/ \3 ?$ z% M
  53. /****************USART1 ÖжϺ¯Êý***************************/  ! A4 q1 E8 c) n
  54. void USART1_IRQHandler(void)    I/ E; F0 ~$ i: J7 E
  55. {  ! ?5 M4 l, Q  B/ h7 X; q
  56.     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  
    , n+ r" ]# F3 r/ O' ]& }; `
  57.     {  # t5 P/ h' A! [5 ?9 x: T0 j
  58.         RxBuffer[RxCounter++] = (USART_ReceiveData(USART1));  
    $ ^3 \2 Z' ]- K% F1 H) M; Z( `
  59.     }  
    8 ]  `; l# B  e5 ~
  60. }  
复制代码
USART1_Config()用于USART1的GPIO配置,配置到9 Q: [0 h2 p  B( s. y
*          | PA9  - USART1(Tx)      |  h- S, n7 f* A
*          | PA10 - USART1(Rx)      |) A: W! ~  M2 D* V7 ]9 i. F  H
*           ------------------------
+ _9 v: C6 v5 `3 kUSART1_NVIC_Configuration() 用于USART1设置中断方式接受发送数据
! ?0 D' n0 g5 a9 k1 Y+ b2 k9 ~' W6 Y* k
USART1_IRQHandler()用于USART1中断接受函数
5 p8 V. [0 {/ n' d9 k* o4 S
5 \2 l6 b! P6 N$ {自设板
* h% T( c. M' s9 x
  1. [objc] view plain copy7 {6 T6 a! C8 X! a
  2. void USART2_Config(void)  9 U3 ~( @; o6 f  u5 Q
  3. {  ( v' t- [! E3 A+ G5 Q" @
  4.     GPIO_InitTypeDef GPIO_InitStructure;  
    8 z9 I3 F& r) Y; M$ \5 w
  5.     USART_InitTypeDef USART_InitStructure;  
    , v3 d* H: X- S6 i
  6.   
    ! Y) `$ V. ~( `  P
  7.     /* config USART2 clock */  + {; j! y6 }* V9 p
  8.     //RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);  9 @+ S+ o9 O3 ]9 ?: z# b. I
  9.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 , ENABLE);  
    ( A+ Y4 ?- d- w" j5 Q' ~8 O& s
  10.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  3 T2 ]  W" j- L: m3 d9 s9 e
  11.       
    / t: ~) u3 \! ?0 g. a8 L$ Z
  12.     /* USART2 GPIO config */  
    ) L% i5 w2 {9 P" {# c2 O9 i& k
  13.    /* Configure USART2 Tx (PA.02) as alternate function push-pull */  
    7 |+ C7 y  r1 E8 }5 R& ]
  14.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;  : O% q: ~8 m; A( \6 @8 j$ h! l
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
    - z  O; e. P% D3 q( @" ^* i
  16.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    , N4 n: @: e5 O* B$ `7 z. Q
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);      
    - \8 o5 M# D; t  C
  18.   /* Configure USART2 Rx (PA.03) as input floating */  
    , X5 V! e9 f' K- U1 d! v) O5 Q- u
  19.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;  
    : T5 q. j" l6 M6 f7 F  d9 r
  20.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  - Q* `; K6 E8 b8 ]) \6 c" ^
  21.   GPIO_Init(GPIOA, &GPIO_InitStructure);  
    ; v) o* K% W4 `7 s2 `/ z
  22.         : q! B8 K9 ?0 s" \4 r( B
  23.     /* USART2 mode config */  # \4 u1 u, m3 ~8 y6 ^4 d1 l" a
  24.     USART_InitStructure.USART_BaudRate = 115200;  
    9 j: i9 H  S* G1 G
  25.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  
    + _; B) r" V0 g
  26.     USART_InitStructure.USART_StopBits = USART_StopBits_1;  
    - J  A5 V+ p4 V9 o/ H( {; \
  27.     USART_InitStructure.USART_Parity = USART_Parity_No ;    w8 V- i, d4 b% l; U2 @& G5 H( w# j
  28.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  9 L) J0 q3 J9 T1 n) [: y
  29.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  8 D3 y3 i6 e! K3 R7 a
  30.     USART_Init(USART2, &USART_InitStructure);  
    . i: X  x1 z4 R5 ^0 T
  31.     USART_Cmd(USART2, ENABLE);  
    " D4 ~4 G* K. a, n9 F- X5 O
  32.       ( G3 b' \6 H5 @, b8 l5 G7 D4 \, |' @' t
  33.     /* Enable the EVAL_COM1 Transmit interrupt: this interrupt is generated when the  ) X! ?+ c# i7 D8 @1 K! q
  34.      EVAL_COM1 transmit data register is empty */   
    0 s6 e! C- C+ f- M2 o: W, M1 K  m" |! a
  35.   //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);  
    1 _7 [' T7 n3 ^
  36.   
    3 S0 a0 C: S4 `1 }$ l. X7 J
  37.   /* Enable the EVAL_COM1 Receive interrupt: this interrupt is generated when the  
    " J: j( h9 ?- k+ S0 u
  38.      EVAL_COM1 receive data register is not empty */  ! V! T& L4 M9 o
  39.   //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  
    2 H3 D. A; Z" ?9 J: d+ r
  40.     USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);  
    % U/ i4 r8 c+ D) g( c1 P( w, G
  41. }  
    + J. L8 b% }: D9 b9 m/ Z
  42.   
    8 w' R$ Z0 M2 _5 y/ P/ L5 t
  43.   
    6 {" p) \7 ~. t7 l2 U! j7 u; n& B5 A
  44. /***************USART2 ÅäÖÃÖжϷ½Ê½·¢ËͽÓÊÕÊý¾Ý******************************/  
    + b/ O; v. ~+ t' _; C5 ?6 y7 Z
  45. void USART2_NVIC_Configuration(void)  
    ( v6 Z$ `# }( \6 Z4 i7 r0 g$ O
  46. {  0 m% B2 g- h' ^9 i4 h% a
  47.   NVIC_InitTypeDef NVIC_InitStructure;  , p' k5 j# e2 N" }4 G
  48.   
    % T$ D1 Z' K9 m& N4 T( `
  49.   /* Enable the USARTx Interrupt */  
    1 N/ V8 ~; r0 i4 y/ U8 Z
  50.   NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;  
    ! |9 I. ]$ @; s
  51.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
    # p- r" T. t8 X* p, U3 j2 v6 G8 Z9 J
  52.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  : @! q7 v2 ^5 N. Q
  53.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    1 e5 [2 I+ Z, f' m7 U! d5 b
  54.   NVIC_Init(&NVIC_InitStructure);  
    * u) f( D; F! G* Q/ L' y
  55. }  ; _& W$ G# U* D' a! ~1 Q" _4 m( n7 l9 ^
  56.   & f4 Q6 z8 O2 k9 u9 u. S2 `
  57. /****************USART2 ÖжϺ¯Êý***************************/  
    % s( W9 v% X1 b
  58. void USART2_IRQHandler(void)  
      J+ x( _/ S. J
  59. {  . N4 j& e  n2 F: @
  60.     if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  
    : [$ C$ f& @1 [1 P1 {- Z" u
  61.     {  
    8 h' ]) s6 ~, N/ c9 S& B
  62.         RxBuffer[RxCounter++] = (USART_ReceiveData(USART2));  
    # Z) j- T1 m9 s9 _
  63.     }  ; d, S, H- J9 O, _
  64. }  
复制代码
USART2_Config()用于USART2的GPIO配置,配置到
. D9 k6 w  [( t) _ *          | PA2  - USART2(Tx)      |3 Y3 y5 T) x1 S: z8 X
*          | PA3 - USART2(Rx)      |/ f* J1 \# @6 ]% I* [5 {- E
*           ------------------------
+ \# W  r8 G3 X2 Y7 [
& _" G7 O* l$ A, d; FUSART2_NVIC_Configuration() 用于USART2设置中断方式接受发送数据3 ?" q4 A  I' ?5 I" c7 W
& e9 }7 a# r5 B" M1 r
USART2_IRQHandler()用于USART2中断接受函数. o* X7 @, p' q$ y, g

# n5 s' L+ b, f; f! E: u% g然后,配置CAN口GPIO
& ^  K3 d- Z$ \1 g% f9 Y
4 x0 ~& D6 A: _; D  U工控板) @8 Z/ O! [, U" [
  1. [objc] view plain copy8 d0 a. z9 u) ?* z9 f  z9 |, H
  2. /*CAN GPIO ºÍʱÖÓÅäÖà */  
    ' G2 y( h: F' Z+ S, V5 w
  3. void CAN_GPIO_Config(void)  $ w' g- i* Y# |+ p5 o3 h( G2 c: R" G; Z
  4. {  : b. @+ A% R# |9 v) ~
  5.   GPIO_InitTypeDef GPIO_InitStructure;   ' b3 X  k2 Z' L* d; }: f
  6.   /* ¸´Óù¦ÄܺÍGPIOB¶Ë¿ÚʱÖÓʹÄÜ*/     7 t) e' j) {( _. s
  7.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);                                                                          , k- Q1 D$ S4 I) T  P( z7 a
  8.     {: U3 D  H3 G1 w7 [
  9.   /* CAN1 Ä£¿éʱÖÓʹÄÜ */  $ k# R: t) J9 v* f. _8 @6 [
  10.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);   
    4 H! y7 d: |9 ?: P. q
  11.   , f. c1 a' q( |  ~' I" U
  12.   /* Configure CAN pin: RX */    // PB8  
    : c1 F0 ]* x. a) s
  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;  
    , D8 s& N9 ^* w2 |+ s; [
  14.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  " ]  a) K# w! q  E0 S0 R* u
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  // ÉÏÀ­ÊäÈë  ; }. R2 e' V8 g) w; e. L
  16.   GPIO_Init(GPIOB, &GPIO_InitStructure);  ; m4 _$ J9 _9 l' ]. a: J4 ^5 y
  17.     * T6 D9 Z& w1 F) T( D* G2 i' R
  18.   /* Configure CAN pin: TX */   // PB9  
    5 Z: N' v/ X; |
  19.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  
    9 b" }& f' M1 A0 R. U5 O. G& L3 r
  20.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // ¸´ÓÃÍÆÍìÊä³ö  
    2 W3 I6 u8 m9 y' N
  21.   GPIO_Init(GPIOB, &GPIO_InitStructure);  2 D$ D1 M( b( w4 x* [
  22.     2 P, ]- _& E1 L. E0 F1 J. s
  23.     //#define GPIO_Remap_CAN    GPIO_Remap1_CAN1 ±¾ÊµÑéûÓÐÓõ½ÖØÓ³ÉäI/O  
    2 |- r5 e  ?- h0 O6 z
  24.   GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);  
    2 S0 ?7 z  d' `: o4 y* }
  25.   
    8 L! P& c8 d7 n8 }$ |0 e
  26.     - n7 e7 ]2 u% c( q4 B6 X, N' _
  27. }  
复制代码
自设板
3 W' d) V. T) `
  1. [objc] view plain copy
    ' F) J) p0 g- O2 {+ I2 T1 v
  2. void CAN_GPIOA_Config(void)   
    $ `  L. d3 |3 y6 ~: F: z# ?
  3. {   
    / e1 Y8 a2 w( r9 [7 G% H
  4. GPIO_InitTypeDef GPIO_InitStructure;       ( `- Q/ e9 S8 s9 S4 k6 x
  5. /* CAN Periph clock enable */   
    % t5 g+ u) ^6 t: f
  6.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);   
    * f8 W: l* F5 A' Q1 \
  7. // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);    * M6 \  f+ c4 f9 Z0 n0 b* R
  8.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);   
    , r$ N% Z) M. y* M5 `, Z
  9.    
    9 R/ F2 D; _, U0 v/ Y
  10.   /* Configure CAN pin: TX */   
    9 q9 [; W0 [2 Y! f
  11.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;   
    / p" S6 z$ v$ ~. H
  12.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    / }5 x. t& T& x
  13.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    $ n  e8 b! E  U/ K& s$ T0 i7 G. R
  14.   GPIO_Init(GPIOA, &GPIO_InitStructure);       9 o4 q8 I# S+ K+ [
  15. /* Configure CAN pin: RX */   
    6 [6 F0 D' M4 e0 o- ^# E
  16.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;  
    / P# G, y- e) ^) X3 o0 U& I, e
  17.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     $ x3 G3 i8 p* H: r6 L; k% `
  18.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;     
    0 Y7 W& |+ B4 R6 g8 o7 K! g
  19.   GPIO_Init(GPIOA, &GPIO_InitStructure);      
    1 c! ]! ^+ R8 B/ a& `6 f
  20.   //GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE);   
    0 \( i8 u2 o" f8 J5 ~( ~
  21. }   
复制代码
/******************************************************************************************/
, [  P' `; c1 s1 N  }就是这里!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!7 J3 O+ ]) j- X3 w! \+ q9 Q
出现几个小问题,但是却是致命的问题!!!!!!!!!!!!!!!!!!!
+ I# J2 z5 ~, u* J9 v+ l. s( U$ t' u  z- I$ w# s3 _
/******************************************************************************************/! t6 |, R6 g8 y1 m5 F
  P7 {; D% h, l$ M5 m
第一配置GPIO_Speed:* d$ o2 g% v( ^- C# p& z0 T* \5 \

8 o* u- w' Z9 Y' B[objc] view plain copy
5 ]% P+ n0 F3 K' r' E0 i6 vGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  //配置GPIO_Speed为50MHz  - Y* ^2 {2 i" D, q
如果配置GPIO时,省略这一步,会导致CAN口发送不出数据,工控板的配置是放在LED 的GPIO配置中,一开始忽略了这一点,之后用排除法试出来的;+ h3 G2 O3 m6 B, t% N6 E( A( a
  q$ s% v! o1 n8 g2 N6 q% f: G9 G
第二配置复用功能和映射与否:
0 R3 O( p& \& K% L4 Z3 e
  1. [objc] view plain copy6 _0 w3 e* Q* l; I) m, G
  2. // RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //复用功能时钟使能  
复制代码
  1. [objc] view plain copy
    0 U4 G5 `  E9 n1 ?# f' \
  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
复制代码
上面两个被注释掉了,是由于:  * M  R: S' ?2 K$ d3 S2 P8 d( b
用PA11和PA12 用的是CAN的默认端口,而用PB8和PB9是用CAN的复用功能重映射端口。7 P/ v4 b, C6 U. [6 L
$ Z/ E# p* o* ~
  1. [objc] view plain copy6 P$ m! k& @* ?3 f
  2.   
复制代码
1 U+ A2 `, K" G4 B; k8 X
3.jpg
& V  ]$ ~( F( Z3 B3 s
具体:
( y6 Q8 ?4 i. l-------------------------------------------------------------------------
( F3 d' O4 [0 z( T
2 U  a/ ?5 k# l" A; K+ ]默认模式  I+ E) o  P1 e" S9 z; j3 }
* B' i) M, `" v1 l+ g' G
   /* Configure CAN pin: RX */0 v/ V3 t  F, O! v
: X9 T- V2 {1 \9 r
GPIO% d' l' Y3 e2 `# Q
+ ]" x1 `: i% V' B3 C( e
_InitStructure.GPIO_Pin = GPIO_Pin_11;$ X9 M/ s; A$ D: I4 r4 n( B
4 W3 m2 y$ J" f+ m% A( L* @$ o: E: `
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;8 H! U/ p% S8 d$ `; |7 U. b

6 }8 @, T+ f4 o! ?( T   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;1 d- {' S3 _( M" Z! y
1 ?, f; Z3 |5 l* c$ O! X$ f
   GPIO_Init(GPIOA, &GPIO_InitStructure);
1 u+ a7 ?7 |# X9 V0 \- y. n/ P8 s1 c. G& C
   /* Configure CAN pin: TX */# `8 P$ k2 ]+ n+ z

5 g  @5 L* r- P+ b3 w   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;3 d" V9 j' Z+ }# P6 p3 S

- p  [9 h7 k3 s% b. A   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;9 L/ V8 d! g4 ^0 _

5 K; b; a5 I' T7 \7 W   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
( Z2 ?) P5 U3 w% w9 X2 i* i
" K% k! {" w) f- w3 B" g" s/ e8 q   GPIO_Init(GPIOA, &GPIO_InitStructure);/ |' L' _% q  ?8 @7 u
------------------------------------------------------------------------' y) V# n1 c& f
5 h3 x9 O( V5 Y8 y6 M4 ^
重定义地址1模式
  j/ N) A* n  s/ Z. h; T8 d
* k" c3 ~% z; K; O1 `( h, k4 \7 \/* Configure CAN pin: RX */* e+ H6 c6 k% ]6 v1 E( P6 G

0 q! O7 i( u$ A: U% t" U   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;) x/ W; U$ L% f

; q! u+ p2 J2 r& h& U* O   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;' n. Q- X* @1 D5 W* X
% S$ |7 u- B4 r6 W0 ?
   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;( [3 c3 x8 b' U& O) {
- \" o1 G+ H% o0 r
   //GPIO_Init(GPIOB, &GPIO_InitStructure);
( r8 m7 ^  b: R. V+ M* c/ {" f; H' A# e
1 \; `) V: k: z3 Q5 d8 V6 I6 x8 }   /* Configure CAN pin: TX */  
/ k& b9 b  ?, R$ m: H, i
( V8 d+ Y# r2 Z! Y( W0 C% N. C$ Z   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
7 H6 t* u) Q0 X$ K9 Z8 L: N( y6 V4 g5 W' x! c5 {
   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- F+ E6 a" Q) p7 i2 G7 Z. I  |
# u4 G) P' k3 j   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  {  l" w9 [* T( A  \
: m  @7 Y, L) j1 T) R  ^3 ?* f   //GPIO_Init(GPIOB, &GPIO_InitStructure);4 h. R8 k" ^  ^0 _

& B3 D; P: l  e3 w   /* Configure CAN Remap   重影射 */
) p$ i! q  d5 O2 v& P
& l$ ~2 I& e. \; ~. Y7 B) ~$ |   //GPIO_PinRemapConfig(GPIO_Remap1_CAN, ENABLE);5 H$ g/ n" [6 P- c2 U& F6 S& l
* c/ b' u' E- T+ D2 p& [
-------------------------------------------------------------------------  
2 G* @) s# C. f( M7 c8 i% G. \2 p
4 K! r! s2 f* y. z重定义地址2模式
/ h  n1 h  O, m, T
3 O$ U8 }8 k5 E   /* Configure CAN pin: RX */! X  }  v6 P8 E( e* D% v

* Q6 z) A6 {6 i! E) [   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;9 q5 y5 W2 v( v
, ^" e- ?3 i) e% ^* ^" t- }
   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
7 ~# Y1 U5 [8 j& M4 B3 ~
9 B' Q' z3 Y+ I. k# k   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
. y3 f- n4 W) i( ^6 S
$ |: D. K  S7 }% ^; r. I0 v   //GPIO_Init(GPIOD, &GPIO_InitStructure);* ~) d6 R2 y: P. X7 U0 g: b# D

' E+ R0 {/ H. G) u8 G* J1 m5 u% {! H2 @, Y* H* E! e6 A0 Q
   /* Configure CAN pin: TX */( \# N! h# V9 J! U! |+ R: q
. w% C' w0 V, {1 x: q
   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;# b/ F3 G5 `* p  T! v+ f) T8 [( R
2 q8 t. D( b1 T/ o6 ^
   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  y5 Y: k1 ~7 d" s! s0 M# Y9 I8 b# c" ~4 W6 O
   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
! {) B  Z) D1 f2 l  N3 G
/ T. l7 L1 H3 u7 @4 A, g   //GPIO_Init(GPIOD, &GPIO_InitStructure);- C; n0 U) n2 \% W; ^

4 q+ V3 g' D( u
( J$ o7 w+ s. W   /* Configure CAN Remap   重影射 */
5 W" s) r. J) I8 I
9 M* w$ B2 n: f) h6 R" U: d& N   //GPIO_PinRemapConfig(GPIO_Remap2_CAN, ENABLE);
2 Q1 W" w$ Y( I  D& ?1 ^, m8 z- C  ~' p3 s: V) x( o, q
-------------------------------------------------------------------------
% F0 C7 L( q. E
- X: g; z4 g- T7 |: Q+ O  h; x设置完 CAN 的引脚之后还需要打开 CAN 的时钟:$ \( t! u8 h/ j- p& K( p4 n: X% O+ w

1 k& o, B6 c! |' }6 R4 C$ U' i3 ~/* CAN Periph clock enable */. x% }% [3 V/ y+ Y

4 R3 N/ ~/ G# c1 k. Q: H   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);! t, p7 R6 P  |. m
1 @' a& G  ?+ \) \! O7 r( d" k7 e
第三CAN硬件部分:
/ w2 J3 Z, [( `8 [' Y3 g' u$ o/ s0 R6 E2 P$ @5 Y( {
一开始对CAN硬件部分没有过多的了解,后面经过一系列的试验,发现:
' n- O: c: `# `/ v3 c- v9 [2 z; }+ v" S" s
1. 如果STM32 CAN TX和RX没有和CAN收发器连接的情况下,STM32的CAN TX和RX是没用数据发出的;
/ T' ]- L( }: x# ?7 m: O  @' k! M1 `+ R6 _' F5 F
2. STM32 CAN TX和RX必须要与CAN收发器的TX和RX对应,即TX接TX,RX接RX,否则CAN没有数据发出,说明:之所以说这个问题,不知道你们有没有注意到,我的自设板CAN收发器TX和RX是反接的;
# ~& m/ x& R3 P: i: f/ ]! I' B& V8 S+ V
3. STM32F103C8T6-LQFP48 的CAN口和USB口复用,即用CAN口是需要将USB口断开,防止有所影响;% b4 a7 n4 r3 T' r& x; m- F

  K" b% d$ U2 {0 u4. 是我本身设备问题,我的自设板用的12V电源是我自己焊接的,不太可靠,电源12V时有时无的,所以最好烧写程序的时候点亮一个LED灯,可以显示板子的工作状态;# O4 ~, D- i  P. `& b) C

+ C1 d; e. ]. q5. 工控板上CAN收发器是用TJA1050 是5V供电的,自设板用SN65HVD234 3.3-V CAN Bus Transceivers,之前有所顾虑,怕CAN收发器不一样会导致其它后果,之后发现没有问题。
) v$ ?! Z; ~) k% U* Q3 P$ w) I5 s
9 `2 @$ V% {5 ?, s0 C) |# d
: T( {' y& v! `" Q! `  v$ C& _6 c1 v/ z9 I0 D: R! r
以上为本人的一点心得,走了很多弯路。。。记录点滴,以此自励。' [9 P" r% S+ \4 c, i

% m' d' B! E6 h  }
9 z7 S$ j. D) F( [& q
5 N% m9 g0 n* K+ W; V( t; Q
% i9 _2 F/ f# d3 n! J# \% w4 t( e6 E2 Z, @3 a
转载自sunnyhyh
. W8 n# p8 l5 \$ a& t' h* m7 m: `5 _5 E# V  |/ v2 X. p

" u8 i3 A  p& b/ T3 u2 k! w

评分

参与人数 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 手机版