打印
[STM32F1]

STM32的CAN现场总线应用总结

[复制链接]
1440|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Tennasi|  楼主 | 2016-1-29 14:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
CAN现场总线的应用最重要的就是其接口端口映射、初始化及数据的发送、接收。
1.接口映射
STM32中的CAN物理引脚可以设置成三种:默认模式、重定义地址1模式、重定义地址2模式。
CAN信号可以被映射到端口A、端口B或端口D上,如下表所示,对于端口D,在36、48和64脚的封装上没有重映射功能。

表1:CAN复用功能重映射
  
复用功能
  
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脚的封装
当PD0和PD1没有被重映射到OSC_IN和OSC_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);


沙发
Tennasi|  楼主 | 2016-1-29 14:38 | 只看该作者
设置完CAN的引脚之后还需要打开CAN的时钟:
/* CAN Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN,ENABLE);
2. 初始化
2.1.2 CAN报文过滤器初始化
STM32共有14组过滤器,每组过滤器包括了2个可配置的32位寄存器:CAN_FxR0和CAN_FxR1。
可以将过滤器组配置成屏蔽位模式,这样CAN_FxR0中保存的就是标识符匹配值,CAN_FxR1中保存的是屏蔽码,即CAN_FxR1中如果某一位为1,则CAN_FxR0中相应的位必须与收到的帧的标志符中的相应位吻合才能通过过滤器;CAN_FxR1中为0的位表示CAN_FxR0中的相应位可不必与收到的帧进行匹配。
还可以将过滤器组配置成标识符列表模式,此时CAN_FxR0和CAN_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是指高16位,CAN_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);        //接收ID为10的消息,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);


使用特权

评论回复
板凳
Tennasi|  楼主 | 2016-1-29 14:39 | 只看该作者
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);        
}


使用特权

评论回复
地板
dentsgot| | 2016-1-30 20:25 | 只看该作者
stm32的can总线能够传输多远呢,外部电路设计简单吗

使用特权

评论回复
5
玛尼玛尼哄| | 2016-1-31 10:47 | 只看该作者
CAN数据的接收可以放在一个中断中?

使用特权

评论回复
6
515192147| | 2017-8-23 07:28 | 只看该作者
本帖最后由 515192147 于 2017-10-8 09:38 编辑

这个 是 基于 STM32F105 CAN高层协议开发源码,供大家参考
用户可在此冗余双CANWeb开发板(含4个DI/4个DO/1个AI/1个AO)的PCB文件及Keil源程序基础上,
轻松、快捷开发自己的CANWeb总线产品,如多通道DI、DO、AI、AO模块、温度、压力现场智
能仪表、电动调节阀、电磁阀、电量表、RS485网关(可与RS485的设备通信) 等设备。
https://bbs.21ic.com/icview-1945634-1-1.html

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

22

主题

169

帖子

1

粉丝