1、什么是CAN
CAN是Controller Area Network 的缩写(简称称CAN),是ISO国际标准化的串行通信协议。由德国电气商博世公司在1986 年率先提出。此后,CAN 通过ISO11898 及ISO11519 进行了标准化。现在在欧洲已是汽车网络的标准协议。ISO11898是针对通信速率为125Kbps~1Mbps的高速通信标准,而ISO11519-2是针对通信速率为125Kbps以下的低速通信标准。现场总线是当今自动化领域技术发展的热点之一,被誉为自动化领域的计算机局域网。
CAN 控制器根据两根线上的电位差来判断总线电平。总线电平分为显性电平和隐性电平,二者必居其一。发送方通过使总线电平发生变化,将消息发送给接收方。具有很高的可靠性,广泛应用于:汽车电子、工业自动化、船舶、医疗设备、工业设备等方面。
2、CAN协议的特点
①多主控制。
②系统柔软性。
③ 速度快,距离远。
④ 具有错误检测、错误通知和错误恢复功能。
⑤ 故障封闭功能。
⑥连接节点多。
3、ISO11898标准下的物理层特征
CAN 控制器根据CAN_L和CAN_H上的电位差来判断总线电平。总线电平分为显性电平和隐性电平,二者必居其一。发送方通过使总线电平发生变化,将消息发送给接收方。
显性电平对应逻辑:0,CAN_H和CAN_L之差为2.5V左右。
隐性电平对应逻辑:1,CAN_H和CAN_L之差为0V。
显性电平具有优先权,只要有一个单元输出显性电平,总线上即为显性电平。而隐形电平则具有包容的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平(显性电平比隐性电平更强)。另外,在CAN总线的起止端都有一个120Ω的终端电阻,来做阻抗匹配,以减少回波反射。
4、CAN 协议的5 种类型帧
其中,数据帧和遥控帧有标准格式和扩展格式两种格式。
标准格式有11 个位的标识符(ID),扩展格式有29 个位的ID 。
其中,最常用,也是最复杂的是数据帧,接着就看看数据帧:
数据帧一般由 7 个段构成
(1) 帧起始。表示数据帧开始的段。
(2) 仲裁段。表示该帧优先级的段。
(3) 控制段。表示数据的字节数及保留位的段。
(4) 数据段。数据的内容,一帧可发送 0~8 个字节的数据。
(5) CRC 段。检查帧的传输错误的段。
(6) ACK 段。表示确认正常接收的段。
(7) 帧结束。表示数据帧结束的段。
4.1、总线仲裁介绍
同时多个单元发送数据时,总线仲裁过程:
上图中,单元 1 和单元 2 同时开始向总线发送数据,开始部分他们的数据格式是一样的,故无法区分优先级,直到 T 时刻,单元 1 输出隐性电平,而单元 2 输出显性电平,此时单元 1仲裁失利,立刻转入接收状态工作,不再与单元 2 竞争,而单元 2 则顺利获得总线使用权,继续发送自己的数据。这就实现了仲裁,让连续发送显性电平多的单元获得总线使用权.
规律:
1,总线空闲时,最先发送的单元获得发送优先权,一但发送,其他单元无法抢占。
2,如果有多个单元同时发送,则连续输出显性电平多的单元,具有较高优先级。
4.2、位时序
位速率:由发送单元在非同步的情况下发送的每秒钟的位数称为位速率。一个位一般可以分为如下四段:
同步段(SS)
传播时间段(PTS)
相位缓冲段 1(PBS1)
相位缓冲段 2(PBS2)
这些段又由可称为 Time Quantum(以下称为 Tq)的最小时间单位构成,1 位分为 4 个段,每个段又由若干个 Tq 构成,这称为位时序。
位时间=1/波特率,因此,知道位时间,我们就可以知道波特率1 位由多少个 Tq 构成、每个段又由多少个 Tq 构成等,可以任意设定位时序。通过设定位时序,多个单元可同时采样,也可任意设定采样点。各段的作用和 Tq 数如表所示:
1 个位的构成如图所示:
上图的采样点,是指读取总线电平,并将读到的电平作为位值的点。位置在 PBS1 结束处。根据这个位时序,我们就可以计算 CAN 通信的波特率了。图中采样时间加大或减少量的最大值就是SJW。
5、STM32 CAN控制器简介
STM32F4 自带的是 bxCAN,即基本扩展 CAN。它支持 CAN 协议 2.0A 和 2.0B。它的设计目标是,以最小的 CPU 负荷来高效处理大量收到的报文。它也支持报文发送的优先级要求(优先级特性可软件配置)。对于安全紧要的应用, bxCAN 提供所有支持时间触发通信模式所需的硬件功能。
STM32F4 的 bxCAN 的主要特点有:
①支持 CAN 协议 2.0A 和 2.0B 主动模式
②波特率最高达 1Mbps
③支持时间触发通信
④具有 3 个发送邮箱
⑤具有 3 级深度的 2 个接收 FIFO
⑥可变的过滤器组(28 个, CAN1 和 CAN2 共享)
5.1、标识符筛选器
CAN的标识符不表示目的地址而是表示发送优先级。接收节点根据标识符的值,来决定是否接收对应消息。
STM32 CAN控制器,提供了28个可配置的筛选器组(F1仅互联型才有28个,其他的只有14个),可降低CPU处理CAN通信的开销。
STM32 CAN控制器每个筛选器组由2个32位寄存器组成(CAN_FxR1和CAN_FxR2,x=0~27)。根据位宽不同,每个筛选器组可提供:
● 1个32位筛选器,包括:STDID[10:0]、EXTID[17:0]、IDE和RTR位
● 2个16位筛选器,包括:STDID[10:0]、IDE、RTR和EXTID[17:15]位
4.筛选器可配置为:屏蔽位模式和标识符列表模式。
在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按照“必须匹配”或“不用关心”处理。
在标识符列表模式下,屏蔽寄存器也被当作标识符寄存器用。因此,不是采用一个标识符加一个屏蔽位的方式,而是使用2个标识符寄存器。接收报文标识符的每一位都必须跟筛选器标识符相同。
为了过滤出一组标识符,应该设置筛选器组工作在屏蔽位模式。
为了过滤出一个标识符,应该设置过滤器组工作在标识符列表模式。
应用程序不用的筛选器组,应该保持在禁用状态(通过CAN_FA1R设置)。
筛选器组中的每个筛选器,都被编号为(即:筛选器编号)从0开始,到某个最大数值-取决于筛选器组的模式和位宽的设置。
通过CAN_FFA1R的设置,可以将筛选器组关联到FIFO0/FIFO1
5.2、STM32 CAN模式
1)工作模式
①初始化模式(INRQ=1,SLEEP=0)
②正常模式(INRQ=0,SLEEP=0)
③睡眠模式(SLEEP=1)
2)测试模式
静默模式( LBKM=0,SILM=1 )
环回模式( LBKM=1,SILM=0 )
环回静默模式(LBKM=1,SILM=1)
3)调试模式
5.3、STM32 CAN发送流程
CAN发送流程为:
程序选择1个空置的邮箱(TME=1)--->设置标识符(ID),数据长度和发送数据--->设置CAN_TIxR的TXRQ位为1,请求发送--->邮箱挂号(等待成为最高优先级)--->预定发送(等待总线空闲)--->发送--->邮箱空置。
还包含了很多其他处理,终止发送(ABRQ=1)和发送失败处理等
5.4、STM32 CAN接收流程
CAN接收流程为:
FIFO空--->收到有效报文--->挂号_1(存入FIFO的一个邮箱,这个由硬件控制,从而节省了 CPU 的处理负荷,简化了软件并保证了数据的一致性)---->收到有效报文---->挂号_2---->收到有效报文---->挂号_3---->收到有效报文à溢出。
CAN收到的有效报文,存储在3级邮箱深度的FIFO中。FIFO接收到的报文数,我们可以通过查询CAN_RFxR的FMP寄存器来得到,只要FMP不为0,我们就可以从FIFO读出收到的报文。
报文FIFO具有锁定功能(由CAN_MCR,RFLM位控制),锁定后,新数据将丢弃,不锁定则新数据将替代老数据
5.5、STM32 CAN位时序
STM32F4 把传播时间段和相位缓冲段 1(STM32F4 称之为时间段1)合并了,所以 STM32F4 的 CAN 一个位只有 3 段:同步段(SYNC_SEG)、时间段 1(BS1)和时间段 2(BS2)。 STM32F4 的 BS1 段可以设置为 1~16 个时间单元,刚好等于CAN的传播时间段和相位缓冲段 1 之和。
图中还给出了 CAN 波特率的计算公式,我们只需要知道 BS1 和 BS2 的设置,以及 APB1的时钟频率(一般为 42Mhz),就可以方便的计算出波特率。
比如:
STM32F103,设TS1=8、TS2=7、BRP=3,波特率=36000/[(9+8+1)*4]=500Kbps。
STM32F407,设TS1=6、TS2=5、BRP=5,波特率=42000/[(7+6+1)*6]=500Kbps。
6、参考代码
#include "can.h"
#include "delay.h"
#include "usart.h"
u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1);
CAN_InitStructure.CAN_TTCM=DISABLE;
CAN_InitStructure.CAN_ABOM=DISABLE;
CAN_InitStructure.CAN_AWUM=DISABLE;
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;
CAN_InitStructure.CAN_BS1=tbs1;
CAN_InitStructure.CAN_BS2=tbs2;
CAN_InitStructure.CAN_Prescaler=brp;
CAN_Init(CAN1, &CAN_InitStructure);
CAN_FilterInitStructure.CAN_FilterNumber=0;
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
return 0;
}
void CAN1_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
int i=0;
CAN_Receive(CAN1, 0, &RxMessage);
for(i=0;i<8;i++)
printf("rxbuf[%d]:%drn",i,RxMessage.Data[i]);
}
u8 CAN1_Send_Msg(u8* msg,u8 len)
{
u8 mbox;
u16 i=0;
CanTxMsg TxMessage;
TxMessage.StdId=0x12;
TxMessage.ExtId=0x12;
TxMessage.IDE=0;
TxMessage.RTR=0;
TxMessage.DLC=len;
for(i=0;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; } 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 return RxMessage.DLC; } ———————————————— 版权声明:本文为CSDN博主「nandycooh」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_42108484/article/details/93325869
上一篇:STM32的I2C的原理与使用(24C02附代码)
下一篇:STM32的DMA基本原理及实现过程
推荐阅读最新更新时间:2024-11-08 11:26
推荐帖子
- 提问+MP3一般用的什么方案做最普遍和简单?
- 最近网上看了关于MP3的资料,VS10系列的方案比较普遍,利用存储卡把歌曲放进去。然后利用单片机将其读出来通过编码再播放,谁做过其他方案的MP3不。有没有其他方案好点的。成本更第一点的。VS10的芯片还不便宜。提问+MP3一般用的什么方案做最普遍和简单?商品的MP3都是专用MP3芯片,一片搞定,一般这种芯片不是面向大众玩的,没有资料,也买不到。普通玩家只能用VS10xx玩玩或者直接用单片机解码,单片机解码的话,对单片机的性能和软件编码都有要求。lcofjp发表于2014-2-28
- youluo 综合技术交流
- 想用16位定时器捕捉1~200kHz的脉冲周期,求大神指点迷津!
- 定时器配置:RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16,ENABLE);/*----------------------------TIM16Configuration----------------------------*//*Timebaseconfiguration*/TIM_DeInit(TIM16);TIM_TimeBaseSt
- 1152075117 stm32/stm8
- TCP与UDP数据包结构
- TCP(TransportControlProtocol)传输控制协议:1、TCP数据包的分组格式:A,源端口:标识源端应用进程。B,目的端口:标识目的端应用进程。C,序号:在SYN标志未置位时,该字段指示了用户数据区中第一个字节的序号;在SYN标志置位时,该字段指示的是初始发送的序列号。D,确认号:用来确认本端TCP实体已经接收到的数据,其值表示期待对端发送的下一个字节的序号,实际上告诉对方,在这个序号减1以前的字节已正确接收。E,数据偏移:表示以32位字为
- Aguilera DSP 与 ARM 处理器
- FPGA精华学习资源推荐(六)--Altera FPGA/CPLD设计 (基础篇)
- FPGA精华学习资源推荐(六)--AlteraFPGA/CPLD设计(基础篇)FPGA从诞生以来经历了从配角到主角的转变,FPGA主要用于取代复杂的逻辑电路,现在重点强调平台概念,当集成数字信号处理器、嵌入式处理器、高速串行和其它高端技术后,从而被应用到更多的领域,正因为其飞速的发展,让更多学FPGA的人看到了希望,其广阔的前景正是我们选择的原因之一。(1)广阔的发展前景2)更多的就业机会(3)更大的
- tiankai001 下载中心专版
- 一个汇编
- 我是汇编初学者,希望大家帮忙给解决个问题向内存0:200——0:23F依次传输数据0——63(3FH)谢谢大家了一个汇编你用的是什么单片机汇编也有许多种应用下的汇编,而且即便是同一种应用,不同的厂家也有所不同,所以把你的问题描述清楚好让大家帮忙引用2楼xjdreamer的回复:汇编也有许多种应用下的汇编,而且即便是同一种应用,不同的厂家也有所不同,所以把你的问题描述清楚好让大家帮忙 是啊.
- 海洋dz 嵌入式系统
- 【2024 DigiKey 创意大赛】+功能
- 项目概述和主要工作内容,以下是对项目的详细分析:针对您提出的项目,以下是对软件规划部分的详细阐述,包括LVGL用户交互界面的实现等关键内容:一、硬件连接示意图:二、软件架构概述软件部分将基于ESP32-S3和rp2040双核心进行开发,其中ESP32-S3作为主核心负责LVGL用户交互界面的运行和显示,而rp2040作为副核心则负责温湿度数据的采集、处理以及与主核心的通信。界面设计:利用LVGL(LightandVersatileGraph
- meiyao DigiKey得捷技术专区