本帖最后由 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
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
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- [objc] view plain copy' n' R- v' N' H: [* @
- void USART1_Config(void)
0 Q) i! `+ ]+ }* n! p - { ' }+ t! H0 U* s2 i& Z2 r
- GPIO_InitTypeDef GPIO_InitStructure; 4 K! J4 [9 z- g; _: Z+ [
- USART_InitTypeDef USART_InitStructure;
) |2 w" ~& E0 `$ h - . \$ o3 g. s1 r# {1 j1 x
- /* config USART1 clock */ + L/ q9 t' H/ W" l* @" {* _
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
4 _, t; F. J' {* R. o! m -
* o @6 m9 A/ X/ W# t - /* USART1 GPIO config */ / ^6 w3 Z2 L& J7 d
- /* Configure USART1 Tx (PA.09) as alternate function push-pull */ : `2 |% |+ r% [. _9 N5 {) K
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; : g; G; P: ]6 e0 c* G0 R
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
+ l3 H+ ^! T; q) f. n- } - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; , N1 M) i2 h" v
- GPIO_Init(GPIOA, &GPIO_InitStructure); 7 e0 w4 H( D( Y) c7 G) ` w* X
- /* Configure USART1 Rx (PA.10) as input floating */
5 O# S! U$ N' ?8 \* { s% P - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 4 R& n9 E$ z1 |/ I
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
' X+ @/ \6 k4 P$ U+ ?# U9 b - GPIO_Init(GPIOA, &GPIO_InitStructure);
: x5 ~; a8 c- k. t; M - U: b. ^! e: j/ T% B1 p8 E
- /* USART1 mode config */ . C* k( G5 H5 c* o t! ?! j
- USART_InitStructure.USART_BaudRate = 115200;
$ g9 @# x9 z6 e; W3 B - USART_InitStructure.USART_WordLength = USART_WordLength_8b;
$ B, N) E$ D3 q5 W8 ? - USART_InitStructure.USART_StopBits = USART_StopBits_1;
8 Y1 R1 S0 h. ]+ m/ i2 z - USART_InitStructure.USART_Parity = USART_Parity_No ;
W, C, C9 }. n% @: X' P - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; ) G8 s$ c% `$ ?1 B' K
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
: |2 F) w3 V# |! w - USART_Init(USART1, &USART_InitStructure);
2 W( ]2 B: R2 H$ d* S5 z% _' R6 z - USART_Cmd(USART1, ENABLE); : N0 C# K9 y# }2 I0 L; i8 B
-
4 {* [" V& h! U! g - /* Enable the EVAL_COM1 Transmit interrupt: this interrupt is generated when the
) a, e% ]$ c4 K" g! t+ s6 W - EVAL_COM1 transmit data register is empty */
+ b) a! Z# N" ]0 y: j9 y - //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
2 W* H! _4 K8 x' }) v - % P5 K/ C7 p! H; H. I9 N
- /* Enable the EVAL_COM1 Receive interrupt: this interrupt is generated when the
9 l @: J9 A6 W8 W - EVAL_COM1 receive data register is not empty */ " m, N0 k# `" `. { E* e2 z c
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); " y* y, b; U" R" f% N/ i
- } % c7 j- G, y2 q
-
}1 U& D% @$ \. Z - /***************USART1 ÅäÖÃÖжϷ½Ê½·¢ËͽÓÊÕÊý¾Ý******************************/ - x" S- v# b2 S0 M. a8 v0 y0 H1 L
- void USART1_NVIC_Configuration(void) 1 `, p5 ]- c) J& W8 B! {# H
- {
+ F/ S& J( x/ W3 I* ] - NVIC_InitTypeDef NVIC_InitStructure;
( p# l7 {" ~. a, U( v - 4 u' G9 C5 I- ~6 y" N1 k* i5 e
- /* Enable the USARTx Interrupt */ 8 P. h0 ^' ?' e% Q3 Z$ r
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
# W, e9 A: O) ~+ W' Z* s. u - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
' `9 y5 f' [9 P: o Y - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 6 q) r% q- r5 g" h; }
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
! B+ g4 t* F7 H& L: W) m) S/ ?& _ - NVIC_Init(&NVIC_InitStructure);
, V! s* H8 D9 ]) G2 q - }
! ]) k% n j" k3 w2 U; ` -
$ `$ ?' H/ \3 ?$ z% M - /****************USART1 ÖжϺ¯Êý***************************/ ! A4 q1 E8 c) n
- void USART1_IRQHandler(void) I/ E; F0 ~$ i: J7 E
- { ! ?5 M4 l, Q B/ h7 X; q
- if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
, n+ r" ]# F3 r/ O' ]& }; ` - { # t5 P/ h' A! [5 ?9 x: T0 j
- RxBuffer[RxCounter++] = (USART_ReceiveData(USART1));
$ ^3 \2 Z' ]- K% F1 H) M; Z( ` - }
8 ] `; l# B e5 ~ - }
复制代码 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- [objc] view plain copy7 {6 T6 a! C8 X! a
- void USART2_Config(void) 9 U3 ~( @; o6 f u5 Q
- { ( v' t- [! E3 A+ G5 Q" @
- GPIO_InitTypeDef GPIO_InitStructure;
8 z9 I3 F& r) Y; M$ \5 w - USART_InitTypeDef USART_InitStructure;
, v3 d* H: X- S6 i -
! Y) `$ V. ~( ` P - /* config USART2 clock */ + {; j! y6 }* V9 p
- //RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); 9 @+ S+ o9 O3 ]9 ?: z# b. I
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 , ENABLE);
( A+ Y4 ?- d- w" j5 Q' ~8 O& s - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 3 T2 ] W" j- L: m3 d9 s9 e
-
/ t: ~) u3 \! ?0 g. a8 L$ Z - /* USART2 GPIO config */
) L% i5 w2 {9 P" {# c2 O9 i& k - /* Configure USART2 Tx (PA.02) as alternate function push-pull */
7 |+ C7 y r1 E8 }5 R& ] - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; : O% q: ~8 m; A( \6 @8 j$ h! l
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- z O; e. P% D3 q( @" ^* i - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
, N4 n: @: e5 O* B$ `7 z. Q - GPIO_Init(GPIOA, &GPIO_InitStructure);
- \8 o5 M# D; t C - /* Configure USART2 Rx (PA.03) as input floating */
, X5 V! e9 f' K- U1 d! v) O5 Q- u - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
: T5 q. j" l6 M6 f7 F d9 r - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; - Q* `; K6 E8 b8 ]) \6 c" ^
- GPIO_Init(GPIOA, &GPIO_InitStructure);
; v) o* K% W4 `7 s2 `/ z - : q! B8 K9 ?0 s" \4 r( B
- /* USART2 mode config */ # \4 u1 u, m3 ~8 y6 ^4 d1 l" a
- USART_InitStructure.USART_BaudRate = 115200;
9 j: i9 H S* G1 G - USART_InitStructure.USART_WordLength = USART_WordLength_8b;
+ _; B) r" V0 g - USART_InitStructure.USART_StopBits = USART_StopBits_1;
- J A5 V+ p4 V9 o/ H( {; \ - USART_InitStructure.USART_Parity = USART_Parity_No ; w8 V- i, d4 b% l; U2 @& G5 H( w# j
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 9 L) J0 q3 J9 T1 n) [: y
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 8 D3 y3 i6 e! K3 R7 a
- USART_Init(USART2, &USART_InitStructure);
. i: X x1 z4 R5 ^0 T - USART_Cmd(USART2, ENABLE);
" D4 ~4 G* K. a, n9 F- X5 O - ( G3 b' \6 H5 @, b8 l5 G7 D4 \, |' @' t
- /* Enable the EVAL_COM1 Transmit interrupt: this interrupt is generated when the ) X! ?+ c# i7 D8 @1 K! q
- EVAL_COM1 transmit data register is empty */
0 s6 e! C- C+ f- M2 o: W, M1 K m" |! a - //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
1 _7 [' T7 n3 ^ -
3 S0 a0 C: S4 `1 }$ l. X7 J - /* Enable the EVAL_COM1 Receive interrupt: this interrupt is generated when the
" J: j( h9 ?- k+ S0 u - EVAL_COM1 receive data register is not empty */ ! V! T& L4 M9 o
- //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
2 H3 D. A; Z" ?9 J: d+ r - USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
% U/ i4 r8 c+ D) g( c1 P( w, G - }
+ J. L8 b% }: D9 b9 m/ Z -
8 w' R$ Z0 M2 _5 y/ P/ L5 t -
6 {" p) \7 ~. t7 l2 U! j7 u; n& B5 A - /***************USART2 ÅäÖÃÖжϷ½Ê½·¢ËͽÓÊÕÊý¾Ý******************************/
+ b/ O; v. ~+ t' _; C5 ?6 y7 Z - void USART2_NVIC_Configuration(void)
( v6 Z$ `# }( \6 Z4 i7 r0 g$ O - { 0 m% B2 g- h' ^9 i4 h% a
- NVIC_InitTypeDef NVIC_InitStructure; , p' k5 j# e2 N" }4 G
-
% T$ D1 Z' K9 m& N4 T( ` - /* Enable the USARTx Interrupt */
1 N/ V8 ~; r0 i4 y/ U8 Z - NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
! |9 I. ]$ @; s - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
# p- r" T. t8 X* p, U3 j2 v6 G8 Z9 J - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; : @! q7 v2 ^5 N. Q
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
1 e5 [2 I+ Z, f' m7 U! d5 b - NVIC_Init(&NVIC_InitStructure);
* u) f( D; F! G* Q/ L' y - } ; _& W$ G# U* D' a! ~1 Q" _4 m( n7 l9 ^
- & f4 Q6 z8 O2 k9 u9 u. S2 `
- /****************USART2 ÖжϺ¯Êý***************************/
% s( W9 v% X1 b - void USART2_IRQHandler(void)
J+ x( _/ S. J - { . N4 j& e n2 F: @
- if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
: [$ C$ f& @1 [1 P1 {- Z" u - {
8 h' ]) s6 ~, N/ c9 S& B - RxBuffer[RxCounter++] = (USART_ReceiveData(USART2));
# Z) j- T1 m9 s9 _ - } ; d, S, H- J9 O, _
- }
复制代码 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" [
- [objc] view plain copy8 d0 a. z9 u) ?* z9 f z9 |, H
- /*CAN GPIO ºÍʱÖÓÅäÖà */
' G2 y( h: F' Z+ S, V5 w - void CAN_GPIO_Config(void) $ w' g- i* Y# |+ p5 o3 h( G2 c: R" G; Z
- { : b. @+ A% R# |9 v) ~
- GPIO_InitTypeDef GPIO_InitStructure; ' b3 X k2 Z' L* d; }: f
- /* ¸´Óù¦ÄܺÍGPIOB¶Ë¿ÚʱÖÓʹÄÜ*/ 7 t) e' j) {( _. s
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE); , k- Q1 D$ S4 I) T P( z7 a
- {: U3 D H3 G1 w7 [
- /* CAN1 Ä£¿éʱÖÓʹÄÜ */ $ k# R: t) J9 v* f. _8 @6 [
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
4 H! y7 d: |9 ?: P. q - , f. c1 a' q( | ~' I" U
- /* Configure CAN pin: RX */ // PB8
: c1 F0 ]* x. a) s - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
, D8 s& N9 ^* w2 |+ s; [ - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; " ] a) K# w! q E0 S0 R* u
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // ÉÏÀÊäÈë ; }. R2 e' V8 g) w; e. L
- GPIO_Init(GPIOB, &GPIO_InitStructure); ; m4 _$ J9 _9 l' ]. a: J4 ^5 y
- * T6 D9 Z& w1 F) T( D* G2 i' R
- /* Configure CAN pin: TX */ // PB9
5 Z: N' v/ X; | - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
9 b" }& f' M1 A0 R. U5 O. G& L3 r - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // ¸´ÓÃÍÆÍìÊä³ö
2 W3 I6 u8 m9 y' N - GPIO_Init(GPIOB, &GPIO_InitStructure); 2 D$ D1 M( b( w4 x* [
- 2 P, ]- _& E1 L. E0 F1 J. s
- //#define GPIO_Remap_CAN GPIO_Remap1_CAN1 ±¾ÊµÑéûÓÐÓõ½ÖØÓ³ÉäI/O
2 |- r5 e ?- h0 O6 z - GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);
2 S0 ?7 z d' `: o4 y* } -
8 L! P& c8 d7 n8 }$ |0 e - - n7 e7 ]2 u% c( q4 B6 X, N' _
- }
复制代码 自设板
3 W' d) V. T) `- [objc] view plain copy
' F) J) p0 g- O2 {+ I2 T1 v - void CAN_GPIOA_Config(void)
$ ` L. d3 |3 y6 ~: F: z# ? - {
/ e1 Y8 a2 w( r9 [7 G% H - GPIO_InitTypeDef GPIO_InitStructure; ( `- Q/ e9 S8 s9 S4 k6 x
- /* CAN Periph clock enable */
% t5 g+ u) ^6 t: f - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);
* f8 W: l* F5 A' Q1 \ - // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE); * M6 \ f+ c4 f9 Z0 n0 b* R
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
, r$ N% Z) M. y* M5 `, Z -
9 R/ F2 D; _, U0 v/ Y - /* Configure CAN pin: TX */
9 q9 [; W0 [2 Y! f - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
/ p" S6 z$ v$ ~. H - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; / }5 x. t& T& x
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; $ n e8 b! E U/ K& s$ T0 i7 G. R
- GPIO_Init(GPIOA, &GPIO_InitStructure); 9 o4 q8 I# S+ K+ [
- /* Configure CAN pin: RX */
6 [6 F0 D' M4 e0 o- ^# E - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
/ P# G, y- e) ^) X3 o0 U& I, e - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; $ x3 G3 i8 p* H: r6 L; k% `
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
0 Y7 W& |+ B4 R6 g8 o7 K! g - GPIO_Init(GPIOA, &GPIO_InitStructure);
1 c! ]! ^+ R8 B/ a& `6 f - //GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE);
0 \( i8 u2 o" f8 J5 ~( ~ - }
复制代码 /******************************************************************************************/
, [ 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- [objc] view plain copy6 _0 w3 e* Q* l; I) m, G
- // RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //复用功能时钟使能
复制代码- [objc] view plain copy
0 U4 G5 ` E9 n1 ?# f' \ - //GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE); //重映射I/O CAN使能
复制代码 上面两个被注释掉了,是由于: * 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* ~
- [objc] view plain copy6 P$ m! k& @* ?3 f
-
复制代码 1 U+ A2 `, K" G4 B; k8 X
& 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 |