纬图虚拟仪器论坛

 找回密码
 立即注册
搜索
查看: 5262|回复: 0

STM32的CAN现场总线应用总结

[复制链接]
发表于 2012-9-21 16:09:26 | 显示全部楼层 |阅读模式
STM32CAN现场总线应用总结
CAN现场总线的应用最重要的就是其接口端口映射、初始化及数据的发送、接收。
1.接口映射
STM32中的CAN物理引脚可以设置成三种:默认模式、重定义地址1模式、重定义地址2模式。
CAN信号可以被映射到端口A、端口B或端口D上,如下表所示,对于端口D,364864脚的封装上没有重映射功能。

1CAN复用功能重映射
复用功能
CAN_REMAP[1:0]="00"
CAN_REMAP[1:0]="10"
CAN_REMAP[1:0]="11"
CAN_RX
PA11
PB8
PD0
CAN_TX
PA12
PB9
PD1
重映射不适用于36脚的封装
PD0PD1没有被重映射到OSC_INOSC_OUT时,重映射功能只适用于100脚和144脚的封装上
----------------------------------------------------------------------------------------------------------------------
默认模式
/* Configure CAN pin: RX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);
  
  /* Configure CAN pin: TX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
----------------------------------------------------------------------------------------------------------------------
重定义地址1模式
  /* Configure CAN pin: RX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);
  
  /* Configure CAN pin: TX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);
  
  /*Configure CAN Remap 重映射 */
  GPIO_PinRemapConfig(GPIO_Remap1_CAN,ENABLE);
----------------------------------------------------------------------------------------------------------------------
/* Configure CAN pin: RX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);
  
/* Configure CAN pin: TX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);
  
  /*Configure CAN Remap 重映射 */
  GPIO_PinRemapConfig(GPIO_Remap2_CAN,ENABLE);
----------------------------------------------------------------------------------------------------------------------
设置完CAN的引脚之后还需要打开CAN的时钟:
  /* CAN Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN,ENABLE);
2. 初始化
2.1.1 CAN单元初始化
CAN单元初始化最重要的就是波特率的设置,原理如下:

file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-26977.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-10342.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-25543.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-17481.png 位时间
同步段
时间段1BS1
时间段2BS2
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-14082.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-32136.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-31640.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-17268.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-16615.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-14308.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-31135.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-8781.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-30928.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-29966.png      1×tq             tBS1=TS1[3:0]+1×tq tBS2= (TS2[2:0]+1)×tq
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-27823.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-15790.png



波特率=1/位时间
位时间 = 1 + tBS1 + tBS2)× tq
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-27711.pngtq = BRP[9:0] + 1× tPCLK



tPCLK = APB1
例如现有一STM32系统时钟为72MHz,关于CAN波特率有以下设置:
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; //重新同步跳跃宽度1个时间单位
CAN_InitStructure.CAN_BS1 = CAN_BS1_8tq; //时间段18个时间单位
CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq; //时间段27个时间单位
CAN_InitStructure.CAN_Prescaler = 45; //设定了一个时间单位的长度为45
则其CAN的波特率为1÷[(1+8+7)×45÷(36×106)]=50KHz
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-24656.png
    CAN单元的初始化,除了波特率的设置
以外还包括以下设置:
CAN_InitTypeDef        CAN_InitStructure; //定义一个CAN单元
CAN_InitStructure.CAN_TTCM = DISABLE; //设置时间触发通信模式(失能)
  CAN_InitStructure.CAN_ABOM = DISABLE;// 使/失能自动离线管理(失能)
  CAN_InitStructure.CAN_AWUM = DISABLE;// 使/失能自动唤醒模式(失能)
  CAN_InitStructure.CAN_NART = DISABLE; //使/失能非自动重传输模式(失能)
  CAN_InitStructure.CAN_RFLM = DISABLE;// 使/失能接收FIFO锁定模式(失能)
  CAN_InitStructure.CAN_TXFP = DISABLE; //使/失能发送FIFO优先级(失能)
  CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;//设置CAN工作模式(正常模式)
2.1.2 CAN报文过滤器初始化
STM32共有14组过滤器,每组过滤器包括了2个可配置的32位寄存器:CAN_FxR0CAN_FxR1
可以将过滤器组配置成屏蔽位模式,这样CAN_FxR0中保存的就是标识符匹配值,CAN_FxR1中保存的是屏蔽码,即CAN_FxR1中如果某一位为1,则CAN_FxR0中相应的位必须与收到的帧的标志符中的相应位吻合才能通过过滤器;CAN_FxR1中为0的位表示CAN_FxR0中的相应位可不必与收到的帧进行匹配。
还可以过滤器组配置成标识符列表模式,此时CAN_FxR0CAN_FxR1中的都是要匹配的标识符,收到的帧的标识符必须与其中的一个吻合才能通过过滤。
CAN报文过滤器的初始化实际上就是对接收FIFO邮箱标识符寄存器(CAN_RixR(x=0,1)的设置。这些寄存器如下图所示:
31
30
29
28
27
26
25
24
23
22
21
20
19
18
17
16
STID[10:0]
EXID[17:13]
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
















15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
EXID[12:0]
IDE
RTR
Res.
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r

CAN_RIxR寄存器各位域定义:

定义
31:21
  STID[10:0]:标准标识符 标识符的标准部分
20:3
  EXID[17:0]: 扩展标识符 标识符的扩展部分(如果使用了扩展标识符)
2
  IDE:标识符选择  0:标准标识符;1:扩展标识符
1
  RTR:远程发送请求 0:数据帧;1:远程帧
0
  保留位

注意:CAN_FilterIdHigh是指高16CAN_FilterIdLow是低16应该将需要得到的帧和过滤器的设置值坐对齐起。
采用stm32f10x标准外设库时过滤器的完整设置如下:
CAN_FilterInitTypeDef  CAN_FilterInitStructure; //定义一个过滤器
CAN_FilterInitStructure.CAN_FilterNumber=0; //选定第一组过滤器
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask//屏蔽位模式
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32
  CAN_FilterInitStructure.CAN_FilterIdHigh=(0x0010 << 5); //接收ID10的消息,11位标准帧因此左移5
  CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xFFFF;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xFFFF;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0; //第一组过滤器指向FIFO0
  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
  CAN_FilterInit(&CAN_FilterInitStructure);

3.数据发送
CAN_Transmit()函数的操作包括:
1. [选择一个空的发送邮箱]
2. [设置Id]*
3. [设置DLC待传输消息的帧长度]
4. [请求发送]
请求发送语句:
CAN->sTxMailBox[TransmitMailbox].TIR |= TMIDxR_TXRQ;//对CAN_TIxR寄存器的TXRQ位置1,来请求发送
采用stm32f10x标准外设库时CAN发送的完整方法如下:
CanTxMsg TxMessage; //定义发送信息
TxMessage.StdId = 0x0110; //设定标识符(采用标准标识符时,硬件会自动把数据左移5位)
TxMessage.ExtId=0x0000; //设定扩展标识符(非必须,采用标准标识符时可不设定)
TxMessage.RTR = CAN_RTR_DATA; //设定待传输消息的帧类型
TxMessage.IDE = CAN_ID_STD; //设定消息标识符的类型
TxMessage.DLC = X; //设定待传输消息的帧的长度
TxMessage.Data[0] = 0xXX; //写入要传送的数据,最多可写8个字节
.
.
TxMessage.Data[7] = 0xXX;

CAN_Transmit(CAN1, &TxMessage); //开始一个消息的传输

4.数据接收
CAN数据的接收可以放在一个中断中,以下为一完整中断接收程序:
void USB_LP_CAN1_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;

  RxMessage.StdId=0x0004;
  RxMessage.IDE=0;
  RxMessage.DLC=2;
  RxMessage.FMI=0;
  RxMessage.Data[0]=0x00;
  RxMessage.Data[1]=0x00;

CAN_Receive(CAN1, CAN_FIFO0, &RxMessage)

CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|纬图虚拟仪器

GMT+8, 2024-12-25 13:05 , Processed in 0.294237 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表