基于stm32的can总线彻底研究
1、CAN总线的初始化
void can_init(void)
{
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/* CAN register init */
CAN_DeInit();
CAN_StructInit(&CAN_InitStructure);
/* CAN cell init */
CAN_InitStructure.CAN_TTCM=DISABLE;//禁止时间触发通信模式
CAN_InitStructure.CAN_ABOM=DISABLE;
CAN_InitStructure.CAN_AWUM=DISABLE;
CAN_InitStructure.CAN_NART=DISABLE;//CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失)
CAN_InitStructure.CAN_RFLM=DISABLE;
CAN_InitStructure.CAN_TXFP=DISABLE;
CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;
//CAN_Mode_LoopBack
//CAN_Mode_Normal
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;//1--16
CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;//1--8
CAN_InitStructure.CAN_Prescaler=2;
CAN_Init(&CAN_InitStructure);
#ifdef can_id_filter
/* CAN filter init */
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=slave_id<<5;//过滤器标识符
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;//
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xffff;//过滤器屏蔽标识符
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xfffc;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;//选择FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//使能过滤器
CAN_FilterInit(&CAN_FilterInitStructure);//进入初始化函数
#else
/* CAN filter init */
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;//过滤器标识符
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;//
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//过滤器屏蔽标识符
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_ITConfig(CAN_IT_FMP0, ENABLE);//使能指定的can中断
}
void CAN_DeInit(void)
{
/* Enable CAN reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN, ENABLE);
/* Release CAN from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN, DISABLE);
}
2、发送程序
unsigned char CAN_PushMessage(CAN_MSG *pTransmitBuf )
{
u8 TransmitMailbox=0;
CanTxMsg TxMessage;
if(pTransmitBuf -> LEN > 8)
{
return 1;
}
/* transmit */
TxMessage.StdId=pTransmitBuf ->StdId;//用来设定标准标识符(0-0x7ff,11位)
TxMessage.ExtId=pTransmitBuf ->ExtId;
TxMessage.RTR= pTransmitBuf ->RTR;//设置RTR位为数据帧
TxMessage.IDE= pTransmitBuf ->IDE;//标识符扩展位,为标准帧
TxMessage.DLC= pTransmitBuf ->LEN;//设置数据长度
//根据DLC字段的值,将有效数据拷贝到发送数据寄存器
memcpy(TxMessage.Data, pTransmitBuf ->BUF,pTransmitBuf ->LEN);
TransmitMailbox = CAN_Transmit(&TxMessage);
// TxMessage.Data[1]=(data & 0xff00)>>8;
return 1;
}
3、中断接收程序
void USB_LP_CAN_RX0_IRQHandler(void)
{
//清空can接收缓存
CanRxMsg RxMessage;
RxMessage.StdId=0x00;
RxMessage.ExtId=0x00;
RxMessage.IDE=0;
RxMessage.DLC=0;
RxMessage.FMI=0;//CAN过滤主控制寄存器
memset( &RxMessage.Data[0],0,8);
//can总线接收数据函数
CAN_Receive(CAN_FIFO0, &RxMessage);
//将接收到的数据写于modbus的寄存器1
//modbus_regester[1]=(RxMessage.Data[0]<<8)|(RxMessage.Data[1]);
// if((RxMessage.StdId==slave_id) && (RxMessage.ExtId==0x00) && (RxMessage.IDE==CAN_ID_STD))
{
//将can接收标志位置1,表示从卡应经接收到一个can报文
flag_can_recv=0;
memcpy(can_rx_data,&RxMessage.Data,RxMessage.DLC);
flag_can_recv=1;
}
}
4、can总线的id过滤
对扩展数据帧过滤:
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)CAN_ID<<3)&0xFFFF0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow= (((u32)CAN_ID<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;
对标准数据帧过滤:
CAN_FilterInitStructure.CAN_FilterIdHigh= (((u32)CAN_ID0<<21)&0xFFFF0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow=(((u32)CAN_ID0<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;
假如要对标准远程帧进行过滤,那么:
只需要将
CAN_FilterInitStructure.CAN_FilterIdLow=(((u32)CAN_ID0<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF; 改成:
CAN_FilterInitStructure.CAN_FilterIdLow=(((u32)CAN_ID0<<21)|CAN_ID_STD|CAN_RTR_REMOTE)&0xFFFF;
5、can总线的帧格式
数据帧格式:
远程帧格式:
6、can总线的逻辑电平
can总线的物理连接有两根线:CANH和CANL,以差分的形式输出。
(有的时候有地线,作为屏蔽线使用)
can总线的高电平 3.5v,表示逻辑0
can总线的低电平 1.5v,表示逻辑1
7、CAN总线的波特率计算
can时钟是RCC_APB1PeriphClock,要注意CAN时钟频率
CAN波特率 = RCC_APB1PeriphClock/CAN_SJW CAN_BS1 CAN_BS2/CAN_Prescaler;
如果CAN时钟为8M, CAN_SJW = 1,CAN_BS1 = 8,CAN_BS2 = 7,CAN_Prescaler = 2
那么波特率就是=8M/(1 8 7)/2=250K
8、can总线的仲裁机制
根据仲裁来判断优先级:
(1) 若在同一时刻,标准格式的报文与扩展格式的报文同时抢占总线,且它们的基础ID相同,则发标准格式的报文节点就会PK成功。这是因为扩展格式在基本ID后,紧接着是SRR位,与IDE位,且这两位都是隐性位。而在标准格式中,这两位分别对应的位为RTR与r1,其中RTR既可以为隐性位,也可以为显性位,,但是r1必须为显性位。由仲裁规则可以此时标准帧必定胜出。
(2) 同理,如果在同一时刻,具有相同格式,且具有相同ID的数据帧与远程帧争夺总线控制权,那么数据帧必定胜出。因为RTR显性表示数据帧,隐性表示远程帧。
stm32的can总线的配置如下:
CAN_InitStructure.CAN_TTCM=DISABLE;//禁止时间触发通信模式
CAN_InitStructure.CAN_ABOM=DISABLE;
CAN_InitStructure.CAN_AWUM=DISABLE;
CAN_InitStructure.CAN_NART=DISABLE;//CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失)
CAN_InitStructure.CAN_RFLM=DISABLE;
CAN_InitStructure.CAN_TXFP=DISABLE;
CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;
//CAN_Mode_LoopBack
//CAN_Mode_Normal
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;//1--16
CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;//1--8
CAN_InitStructure.CAN_Prescaler=2;
CAN_Init(&CAN_InitStructure);
/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber=0;//选择过滤器0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//指定过滤器被设置为标识符屏蔽模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//给出过滤器位宽为32位
下面根据设置的参数不同来决定can总线can总线的配置情况:
1、对扩展数据帧进行过滤:(只接收扩展数据帧)
CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<3)&0xFFFF0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;
(注:标准帧数据帧、标准远程帧和扩展远程帧均被过滤)
2、对扩展远程帧过滤:(只接收扩展远程帧)
CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<3)&0xFFFF0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_REMOTE)&0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;
3、对标准远程帧过滤:(只接收标准远程帧)
CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<21)&0xffff0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_REMOTE)&0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;
4、对标准数据帧过滤:(只接收标准数据帧)
CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<21)&0xffff0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;
5、对扩展帧进行过滤:(扩展帧不会被过滤掉)
CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<3)&0xFFFF0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<3)|CAN_ID_EXT)&0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFC;
6、对标准帧进行过滤:(标准帧不会被过滤掉)
CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<21)&0xffff0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<21)|CAN_ID_STD)&0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFC;
注:slave_id为要过滤的id号。
基于stm32的can总线彻底研究相关推荐
- 2个相同的 stm32 can通讯不成功_一文读懂,基于 STM32 和 CAN 总线的温度监控系统的设计方法...
1 系统总体方案概述 系统总体框图如图 1 所示,本系统采用主站+从站的结构,CAN 主站主要实现温度数据的存储以及 CAN 总线协议和串口协议之间的桥接,CAN 从站主要实现温度的采集.CAN 从站 ...
- 基于STM32的CAN总线通信学习笔记
转自:https://blog.csdn.net/ludaoyi88/article/details/53350077 基于STM32的CAN总线通信学习笔记 本文主要简单介绍CAN总线的相关概念,以 ...
- 基于STM32的SNTP授时服务器的研究与设计
摘要:针对工控领域对时间同步的要求,给出了以STM32和W5100为核心来搭建网络硬件平台,并在其上实现简单网络时间协议(SNTP),从而建立嵌入式授时服务器的设计与实现方法.该系统运行稳定,能够实现 ...
- 双足竞走机器人的意义_基于STM32双足竞步机器人的研究与设计
龙源期刊网 http://www.qikan.com.cn 基于 STM32 双足竞步机器人的研究与设计 作者:卢士林 李彩霞 张奎庆 段忠臣 来源:<智能计算机与应用> 2016 年第 ...
- 基于STM32开发板I²C总线通信协议浅析
基于STM32开发板I²C总线通信协议浅析 一.前言 I²C(Inter-Integrated Circuit),中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,是由飞利浦公司在1980 ...
- 基于STM32开发板CAN总线通信协议浅析
基于STM32开发板CAN总线通信协议浅析 一.前言 控制器局域网(Controller Area Network,CAN),是由德国BOSCH(博世)公司开发,是目前国际上应用最为广泛的现场总线之一 ...
- stm32 工业按键检测_基于STM32芯片的能谱仪设计
随着对天然辐射场中低能量γ谱学及其应用的深入研究,γ能谱仪不仅在固体矿产勘探.油气普查.水文和工程地质调查等工业生产及科学研究方面,甚至在民用的环境辐射场调查.建材与建筑装饰材料放射性检测方面,都得到 ...
- 基于STM32与PCA9685制作四足机器人(代码开源)
前言:本文为手把手教学基于STM32的四足机器人项目--JDY-31蓝牙控制,特别地,本次项目采用的是STM32作为MCU.四足机器人的支架为3D打印件,SG90舵机驱动机器人实现姿态 ...
- 基于STM32的温度控制系统
提示:记录毕设 文章目录 前言 一.任务书 1.1设计(研究)目标: 1.2设计(研究)内容: 二.代码思路 三.硬件 四.联系我们 五.设计 六.框图代码等资料 喜欢请点赞哦! 前言 基于STM32 ...
最新文章
- 2022-2028年中国海水养殖行业市场研究及前瞻分析报告
- 图像二值化之最大类间方差法(大津法,OTSU)
- 在 Python 中使用 OpenCV 高斯模糊我这张的丑脸
- 2020将至,谈谈中小企业创业的那些事儿
- xcode6新建pch文件过程
- Windows phone应用开发[15]-辅助工具
- eclipse安装OpenExplorer插件--快速打开文件目录
- 简单实现虚拟机备份上云
- 世界土壤数据库(HWSD)基本参数介绍
- vc html插件,VC++6.0插件系列(绝对经典)
- 中小学生计算机编程笔试,计算机编程笔试题
- MySQL语句-查看当前数据库有哪些表(SHOW TABLES)
- JS计算字符串在浏览器中显示的宽度
- lvgl 8 中文内置字库配置
- WinRAR的命令行模式与用法介绍
- C/C++,定时关机代码和取消定时关机(应用范畴)
- ios开发所需图片尺寸汇总
- 使用Kali上的Metasploit获取ssh登录到靶机权限
- 计算机科学与技术文献翻译,计算机科学与技术外文文献翻译.doc
- 详解一个Python库,用于构建精美数据可视化web app,练习做个垃圾分类app
热门文章
- windows 下更新 npm 和 node
- 为什么选择Netty作为基础通信组件?
- 总结:ps aux指令
- Android --- 命名规范
- 2020 蓝桥杯大学 B 组省赛模拟赛(一) C. 结果填空:七巧板
- js 浅拷贝直接赋值_js 深拷贝 vs 浅拷贝
- 关键帧动画html例子,Bounce.js 是一个漂亮的CSS3关键帧动画生成工具和类库_前端开发者...
- 讲mysql执行流程书籍_MySQL 基础架构 1. 一条SQL查询语句的执行过程(个人学习笔记)...
- 业界真的需要水下数据中心?微软的确认为如此
- linux i2c子系统入口,I2C子系统1 - ARM_Linuxx的个人空间 - OSCHINA - 中文开源技术交流社区...