STM32_CAN通信
目录
1:CAN简介
CAN是Controller Area Network,是一种串行的通信协议,有两标准:ISO11898、ISO11519-2,其中ISO11898是针对通信速率为125Kbps~1Mbps的高速通信标准,而ISO11519-2是针对通信速率为123Kbps以下的低速通信标准
CAN有很多优点,比如多主控制,速度快,距离远,具有错误检测,恢复,连接节点多等功能。所以CAN协议特别适合工业过程监控设备的互联
讲下ISO11898标准,物理层特征如下
CAN控制器根据CAN_L和CAN_H上的点位差来判断总线电平,总线电平分为显性电平和隐形电平,二者必居其一,发送方通过使总线电平发生变化,将消息发送给接收方。
- 显性电平对应逻辑:0 CAN_H和CAN_L之差为2V左右
- 隐形电平对应逻辑:1 CAN_H和CAN_L之差为0V
要注意的是,显性电平比隐形电平强,显性电平具有优先权,只要有一个单元输出显性电平,总线上即为显性电平,而隐形电平则具有包容的意味,只要所有单元都输出隐形电平,总线上才为隐形电平,
另外,在CAN总线的起止端都有一个120Ω的终端电阻,来做阻抗匹配,以减少回波反射
2:CAN通信帧种类介绍
CAN通信是以以下5钟类型的帧进行的
数据帧、遥控帧、错误帧、过载帧、间隔帧
其中数据帧和遥控帧有标准格式和扩张格式两种,标准格式有11个位标识符(ID),扩展格式有29个位ID
介绍哈数据帧
- 帧起始:表示数据帧开始的段
- 仲裁段:表示该帧优先级的段
- 控制端:表示数据的字节数及保留位的段
- 数据段:数据的内容,一帧可发送0~8·个字节的数据
- CRC段:检查帧的传输错误的段
- ACK段:表示确认正常接受的段
- 帧结束:表示数据帧结束的段
3:CAN位时序
位时序:在CAN 通信中,一个位分为4段,这每个段又由Time Quantum(简称Tq)的最小时间单位构成,这个就是位时序
有如下四个段:
- 同步段(SS)
- 传播时间段(PTS)
- 相位缓冲段1(PBS1)
- 相位缓冲段2(PBS2)
位时间=1/波特率,因此,知道位时间,我们就可以知道波特率
1 位由多少个Tq 构成、每个段又由多少个Tq 构成等,可以任意设定位时序。通过设定位时序,多个单元可同时采样,也可任意设定采样点。
位时序各段的作用和Tq数如下
一个位的构成:
4:STM32_CAN
eg:STM32F407ZGT6
前面只是对CAN通信做一个基本的描述,在STM32上,自带了基本扩展CAN外设,称bxCAN,
- CAN1:主bxCAN,用于管理bxCAN与512字节SRAM存储器之间的通信。
- CAN2:从bxCAN,无法直接访问SRAM存储器,但两个bxCAN单元共享512字节SRAM存储器
- 波特率最高达1Mbps
- 支持时间触发通信
- 具有3个发送邮箱
- 具有3级深度的2个接受FIFO
- 可变的筛选器组(也称过滤器组,最多28个)
bxCAN有三种主要的工作模式:初始化、正常、睡眠,还有测试模式和调试模式,具体看数据手册
5:bx_CAN控制器框图
筛选器组,可以设置你需要的数据,不需要的就不接受,就是为降低CPU处理CAN通信的开销
STM32 CAN控制器每个筛选器组由2个32位寄存器组成,根据位宽不同,每个筛选器组可提供1个32位的筛选器或2个16位的筛选器
筛选器可配置为:屏蔽位模式、标识符列表模式
通过CAN_FM1R(筛选器模式寄存器)和CAN_FS1R(筛选器尺度寄存器)可配置筛选器的位宽和模式
- 为了过滤出一组标识符,应该设置筛选器组工作在屏蔽位模式
- 为了过滤出一个标识符,应该设置过滤器工作在标识符列表模式
- 应用程序不用的筛选器组,应该保持在禁用状态(通过CAN_FA1R设置)。
- 通过CAN_FFA1R的设置,可以将筛选器组关联到FIFO0/FIFO1
- 筛选器组中的每个筛选器,都被编号为(即:筛选器编号)从0开始,到某个最大数值-取决于筛选器组的模式和位宽的设置。
6:STM32_CAN发送,接受流程
报文FIFO具有锁定功能(由CAN_MCR,RFLM位控制),锁定后,新数据将丢失,不锁定则新数据将替代老数据
7:STM32CAN通信位时序
8:STM32CAN代码实现
1:初始化
//CAN单元设置 CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 CAN_InitStructure.CAN_ABOM=DISABLE; //软件自动离线管理 CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位) CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的 CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定 CAN_InitStructure.CAN_Mode= mode; //模式设置 CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq CAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq CAN_InitStructure.CAN_BS2=tbs2; //Tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tq CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1 //配置过滤器 CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0 CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; //32位ID CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; //32位MASK CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0 CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //**过滤器0 CAN_FilterInit(&CAN_FilterInitStructure); //滤波器初始化
相应引脚配置位复用推挽输出加上拉模式
- CAN_TTCM:操作CAN_MCR主控制寄存器的位7
- CAN_ABOM:操作CAN_MCR主控制寄存器的位6
- CAN_AWU:M操作CAN_MCR主控制寄存器的位5
- CAN_NART:操作CAN_MCR主控制寄存器的位4
- CAN_RFLM:操作CAN_MCR主控制寄存器的位3
- CAN_TXFP:操作CAN_MCR主控制寄存器的位2
- CAN_Mode:操作CAN_BTR位时序寄存器的位31,30
- CAN_SJW:操作CAN_BTR位时序寄存器的位25,24
- CAN_BS1:操作CAN_BTR位时序寄存器的位19~16
- CAN_BS2:操作CAN_BTR位时序寄存器的位22~20
- CAN_Prescaler:操作CAN_BTR位时序寄存器的位9~0
配置过滤器
- CAN_FilterNumber:操作CAN_FA1R筛选器**寄存器的位27:0
- CAN_FilterMode:操作CAN_FM1R筛选器模式寄存器的位27:0
- CAN_FilterScale:操作CAN_FS1R筛选器尺度寄存器的位27:0和CAN_FiRx筛选器组i寄存器
- CAN_FilterIdHigh、CAN_FilterIdLow、CAN_FilterMaskIdHigh、CAN_FilterMaskIdLow都是配合操作CAN_FiRx筛选器组i寄存器
- CAN_FilterFIFOAssignment:操作CAN_FFA1R筛选器FIFO分配寄存器的位27:0
- CAN_FilterActivation:操作CAN_FA1R筛选器**寄存器的位27:0
2:发送数据
u8 CAN1_Send_Msg(u8* msg,u8 len) { u8 mbox; u16 i=0; CanTxMsg TxMessage; TxMessage.StdId=0x12; // 标准标识符为0 TxMessage.ExtId=0x12; // 设置扩展标示符(29位) TxMessage.IDE=0; // 使用扩展标识符 TxMessage.RTR=0; // 消息类型为数据帧,一帧8位 TxMessage.DLC=len; // 发送两帧信息 for(i=0;i<len;i++) TxMessage.Data[i]=msg[i]; // 第一帧信息 mbox= CAN_Transmit(CAN1, &TxMessage); i=0; while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++; //等待发送结束 if(i>=0XFFF)return 1; return 0; }
- StdId、IDE、RTR :在IDE的基础上,决定在CAN_TIxR发送邮箱标识符寄存器上标识符类型和帧类型
- ExtId、IDE、RTR:在IDE的基础上,决定在CAN_TIxR发送邮箱标识符寄存器上标识符类型和帧类型
- len:操作CAN_TDTxR邮箱数据长度控制和时间戳寄存器的位3:0
- Data:操作CAN_TDL\HxR邮箱数据低\高寄存器
- 最后查询CAN_TSR发送状态寄存器,等待发送结束
3:接受数据
u8 CAN1_Receive_Msg(u8 *buf) { u32 i; CanRxMsg RxMessage; if( CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0; //没有接收到数据,直接退出 CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//读取数据 for(i=0;i<RxMessage.DLC;i++) buf[i]=RxMessage.Data[i]; return RxMessage.DLC; }
- 先查询CAN_RF0R接受FIFI 0寄存器的位1:0
- 然后去读取CAN_RDL\HxR接受FIFO邮箱数据低\高位寄存器的数据存放在RxMessage.Data中
上一篇: JVM故障诊断调优