【经验分享】STM32F103:CAN总线通信——初始化/波特率 - STM32团队 ST意法半导体中文论坛 一、CAN总线通信初始化配置 1. CAN总线通信初始化配置流程5 E: E) o( `8 o7 a# x# g0 l CAN总线GPIO和时钟配置 CAN总线接收中断优先级配置 CAN总线初始化配置* @% z' r7 n5 u, F 2. CAN总线GPIO和时钟配置; M( R9 K# i8 Z CAN引脚配置- D( Y) P* B! @9 d% n' u: z 6 d' R$ x( K! Y G5 } . _' \: H7 b' E% ~
CAN时钟配置:7 W6 _- e, V8 I& w 2 P A# b+ i7 K, y$ p" f 5 T& ~+ m3 N P+ ?6 [4 e ( R X% ^7 n, p& k* A$ z 4 {3 O% q8 ?( j- V! \5 Q" l" \6 _ PA11和PA12引脚,CAN GPIO初始化,具体代码如下:6 ^/ N4 `6 t" X2 X7 F# [4 o2 G# o
- /*CAN GPIO 和时钟配置 */' u+ H. n7 p5 F& x
- void CAN_GPIO_Config(void)
- {# x" @4 F5 h5 }
- GPIO_InitTypeDef GPIO_InitStructure;
- /*GPIOA端口时钟使能*/ 6 t3 [9 D3 R* H; h- g
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); ) Z* t' l3 o: B1 ~4 @; [6 l
- /* CAN1 模块时钟使能 */
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); ! L! w6 N9 w Y
- /* Configure CAN pin: RX */ // PA11
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;3 z: `$ p6 k, [
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- - W: Y( [4 w# B) _# \7 J1 f; P* }. @
- /* Configure CAN pin: TX */ // PA12: _5 T2 b: W( \, d9 z
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出# \1 d+ j& z+ P/ N
- GPIO_Init(GPIOA, &GPIO_InitStructure);8 e/ O4 L G, U) t) x, ~5 U$ C
- }
复制代码
! n6 r5 W: p9 a& h# ~ PB8和PB9引脚,CAN GPIO初始化,具体代码如下: 0 z- S5 {- X9 f# \0 D9 s4 c
- /*CAN GPIO 和时钟配置 */
- void CAN_GPIO_Config(void) ?- o+ f' m3 I6 T" R
- {5 a8 X8 y0 o2 i- m9 r# V; h
- GPIO_InitTypeDef GPIO_InitStructure; 1 g+ ^3 e, ~. X; l2 g- V4 Z2 k6 s
- /* 复用功能和GPIOB端口时钟使能*/ 7 k2 T1 |% b0 M) m( P; r
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE); , [" j7 V+ u7 ~# q. ^1 ~/ _
- ' F x, q) \: ^4 u) B; U
- /* CAN1 模块时钟使能 */( q- T( W' J8 w. c! l" l
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); + |1 Y |! j( h! v' W$ q# L" ]
- % k7 w9 a+ }2 E2 K4 y+ K4 u. v2 C
- /* Configure CAN pin: RX */ // PB8" s1 g3 a% L6 p- c
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
- GPIO_Init(GPIOB, &GPIO_InitStructure);7 u, u$ A. l- J7 S5 C* q' D
- 0 z# n& [5 T3 x- ]8 Z7 z$ k
- /* Configure CAN pin: TX */ // PB95 [7 A( }* U* B9 f# K0 q6 {9 H
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出; }/ P3 t, V1 v! {
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- //#define GPIO_Remap_CAN GPIO_Remap1_CAN1 - H$ y6 R, X* G# x1 X
- GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);
- }
复制代码
: {8 W/ s! b- ]. w/ N 3. CAN总线接收中断优先级配置 具体代码如下: ; H' d) E( j. p9 `
- /*CAN RX0 中断优先级配置 */
- void CAN_NVIC_Configuration(void) 9 m- {( Z! y* u4 Z" e( O% ~
- {0 _, m/ l! `5 i( t+ X; m/ u8 n
- NVIC_InitTypeDef NVIC_InitStructure; Z7 f! w. b0 M1 ]
- /* Configure the NVIC Preemption Priority Bits */
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);/ Q/ L% f- }' g5 P
- $ @% R: {- e8 r
- /* enabling interrupt */5 O& q' K' [: ^" u9 s$ \% i N
- NVIC_InitStructure.NVIC_IRQChannel=USB_LP_CAN1_RX0_IRQn;;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;) V" t! j: h1 K3 E7 O' a7 \
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);" _; N0 ?& ~( ]5 L, X( l. j$ X7 h
- }
复制代码
4. CAN总线初始化配置 具体代码如下:
- void CAN_INIT(void) , C+ l6 h8 k# ?! l6 U ]- l
- {& |. B k4 b9 t0 T3 f- k
- CAN_InitTypeDef CAN_InitStructure;8 Z5 U* f( |. h+ E( M" P
- CAN_FilterInitTypeDef CAN_FilterInitStructure;
- ! C7 a! s6 _8 g/ R0 v9 j
- /* CAN register init */- b4 v4 a1 N/ L- o* [4 f5 L- q
- CAN_DeInit(CAN1); //将外设CAN的全部寄存器重设为缺省值
- CAN_StructInit(&CAN_InitStructure);//把CAN_InitStruct中的每一个参数按缺省值填入
- ; n! y! D' P( e/ t( f: j; F
- /* CAN cell init */
- CAN_InitStructure.CAN_TTCM=DISABLE;//没有使能时间触发模式
- CAN_InitStructure.CAN_ABOM=DISABLE;//没有使能自动离线管理
- CAN_InitStructure.CAN_AWUM=DISABLE;//没有使能自动唤醒模式0 y) Z, ]5 M% S) l. h2 H3 E
- CAN_InitStructure.CAN_NART=DISABLE;//没有使能非自动重传模式; P# c4 g& y+ O! n9 }: p
- CAN_InitStructure.CAN_RFLM=DISABLE;//没有使能接收FIFO锁定模式6 N5 d8 \) _6 B+ O0 l# }
- CAN_InitStructure.CAN_TXFP=DISABLE;//没有使能发送FIFO优先级
- CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; //CAN设置为正常模式
- CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //重新同步跳跃宽度1个时间单位, y/ ?0 R. e# _" ]: ]. U
- CAN_InitStructure.CAN_BS1=CAN_BS1_3tq; //时间段1为3个时间单位( w, ^/ X" \. O% `, o; n
- CAN_InitStructure.CAN_BS2=CAN_BS2_2tq; //时间段2为2个时间单位
- CAN_InitStructure.CAN_Prescaler=24; //时间单位长度为24 250k7 d: H& y+ _: k0 n0 d
- CAN_Init(CAN1,&CAN_InitStructure);
- //波特率为:36M/24(1+3+2)=0.25 即250K4 I' R$ V0 C3 Q$ S
- /* CAN filter init */
- CAN_FilterInitStructure.CAN_FilterNumber=1;//指定过滤器为10 T Q, W6 z& b; j% D: q
- CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//指定过滤器为标识符屏蔽位模式
- CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//过滤器位宽为32位
- CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;// 过滤器标识符的高16位值$ a' b, g# H0 M& {2 ~3 n
- CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;// 过滤器标识符的低16位值
- CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//过滤器屏蔽标识符的高16位值) G! e; i s( R1 V# _
- CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;// 过滤器屏蔽标识符的低16位值: l; b- `$ U4 y; c# C1 W, r
- CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;// 设定了指向过滤器的FIFO为0
- CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;// 使能过滤器
- CAN_FilterInit(&CAN_FilterInitStructure);// 按上面的参数初始化过滤器! d' s* e2 D" |- K9 ?9 h7 g% P h7 o
- /* CAN FIFO0 message pending interrupt enable */
- CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE); //使能FIFO0消息挂号中断
- }
复制代码
0 Y" Z9 y( K- w) g* J; g' Z6 P- Y 二、CAN总线通信——波特率计算' U9 [0 N9 G: l+ t9 R 1. CAN总线时间特性 同步段(SYNC_SEG):通常期望位的变化发生在该时间段内。其值固定为1个时间单元(1 x tCAN)。 时间段1(BS1):定义采样点的位置。它包含CAN标准里的PROP_SEG和PHASE_SEG1。其值可以编程为1到16个时间单元,但也可以被自动延长,以补偿因为网络中不同节点的频率差异所造成的相位的正向漂移。 时间段2(BS2):定义发送点的位置。它代表CAN标准里的PHASE_SEG2。其值可以编程为1到8个时间单元,但也可以被自动缩短以补偿相位的负向漂移。) P) ~ ~- I, N2 c' S" B4 G 6 J8 T( x( A# e1 }! T7 h
2. 波特率计算公式) S# j+ l8 G8 M3 T `0 K CAN波特率=APB1时钟频率/BRP分频器/(1+tBS1+tBS2)
一般APB1时钟频率为36Mhz。如下图常见CAN总线的波特率设置。 C% c: I8 U% ]$ z, T) E , W4 [7 U5 ]! n* a6 i7 t ; d7 F9 h/ C- x " N) W4 c7 Z9 l 3. CAN波特率有关的寄存器$ g4 U' i/ T8 Z+ c$ V+ E |
所有评论(0)