CAN总线学习笔记 | STM32CubeMX配置CAN环回测试

news2024/11/19 1:37:46

CAN基础知识介绍文中介绍了CAN协议的基础知识,以及STM32F4芯片的CAN控制器相关知识,下面将通过实例,利用STM32CubeMX图形化配置工具,来实现CAN通讯的环回测试

一、STM32CubeMX配置

  • CAN是挂载在APB1总线上,设置PCLK1时钟频率到最大45MHz

在这里插入图片描述

  • 激活CAN1,配置位时序参数,其他基本参数以及工作模式(此处设置为Loopback环回模式

在这里插入图片描述

CAN波特率的计算公式:只需要知道BS1和BS2的设置,以及APB1的时钟频率,就可以方便的计算出波特率。比如设置TS1=8、TS2=6和BRP=6,在APB1频率为45Mhz的条件下,即可得到CAN通信的波特率=45000/6/(8+6+1)=500Kbps
在这里插入图片描述

  • 激活USART1作为调试串口,配置相关LED对应的GPIO引脚作为指示灯

二、MDK-ARM编程

2.1 几个重要的结构体

  • CAN 初始化结构体:此结构体内容,可由STM32CubeMX工具进行配置
typedef struct
{
  uint32_t Prescaler;  					/* 配置 CAN 外设的时钟分频,可设置为 1-1024*/
  uint32_t Mode;       					/* 配置 CAN 的工作模式,回环或正常模式 */
  uint32_t SyncJumpWidth;  				/* 配置 SJW 极限值 */
  uint32_t TimeSeg1;   					/* 配置 BS1 段长度 */
  uint32_t TimeSeg2;   					/* 配置 BS2 段长度 */
  FunctionalState TimeTriggeredMode;   	/* 是否使能 TTCM 时间触发功能 */
  FunctionalState AutoBusOff;     		/* 是否使能 ABOM 自动离线管理功能 */
  FunctionalState AutoWakeUp;   		/* 是否使能 AWUM 自动唤醒功能 */
  FunctionalState AutoRetransmission;  	/* 是否使能 NART 自动重传功能 */
  FunctionalState ReceiveFifoLocked;   	/* 是否使能 RFLM 锁定 FIFO 功能 */
  FunctionalState TransmitFifoPriority;	/* 配置 TXFP 报文优先级的判定方法 */
} CAN_InitTypeDef;
  • 发送及接收头结构体:主要用于构造发送报文,以及接收报文。收发发文时,需要自定义头结构体变量
typedef struct
{
  uint32_t StdId;    			/* 存储报文的标准标识符 11 位,0-0x7FF. */
  uint32_t ExtId;    			/* 存储报文的扩展标识符 29 位,0-0x1FFFFFFF. */
  uint32_t IDE;     			/* 存储 IDE 扩展标志 */
  uint32_t RTR;    				/* 存储 RTR 远程帧标志 */
  uint32_t DLC;    				/* 存储报文数据段的长度,0-8 */
  FunctionalState TransmitGlobalTime; 
} CAN_TxHeaderTypeDef;

typedef struct
{
  uint32_t StdId;    			/* 存储报文的标准标识符 11 位,0-0x7FF. */
  uint32_t ExtId;    			/* 存储报文的扩展标识符 29 位,0-0x1FFFFFFF. */
  uint32_t IDE;     			/* 存储 IDE 扩展标志 */
  uint32_t RTR;      			/* 存储 RTR 远程帧标志 */
  uint32_t DLC;     			/* 存储报文数据段的长度,0-8 */
  uint32_t Timestamp; 
  uint32_t FilterMatchIndex; 
} CAN_RxHeaderTypeDef;
  • 过滤器结构体:STM32CubeMX不会初始化过滤器的相关内容,需要自己添加
typedef struct
{
  uint32_t FilterIdHigh;         	/*CAN_FxR1 寄存器的高 16 位 */
  uint32_t FilterIdLow;         	/*CAN_FxR1 寄存器的低 16 位 */
  uint32_t FilterMaskIdHigh;   		/*CAN_FxR2 寄存器的高 16 位 */
  uint32_t FilterMaskIdLow;    		/*CAN_FxR2 寄存器的低 16 位 */
  uint32_t FilterFIFOAssignment;  	/* 设置经过筛选后数据存储到哪个接收 FIFO */
  uint32_t FilterBank;            	/* 筛选器编号,范围 0-27,数据手册上说0-27是CAN1/CAN2共享,但是实测发现并不是这样,CAN1是0-13,CAN2是14-27 */
  uint32_t FilterMode;            	/* 筛选器模式 */
  uint32_t FilterScale;           	/* 设置筛选器的尺度 */
  uint32_t FilterActivation;      	/* 是否使能本筛选器 */
  uint32_t SlaveStartFilterBank;  	/* CAN2起始过滤器组 */
} CAN_FilterTypeDef;

4.2 程序编写

  • 生成工程后,打开can.c文件,可见STM32CubeMX已经对位时序参数、其他基本参数以及工作模式进行了初始化。但是并没有初始化过滤器的相关内容,因此需要我们自己添加,并在CAN初始化时调用
//下面的设置只使能了FIFO0,并不过滤任何消息
void CAN_Filter_Config(){
	CAN_FilterTypeDef sFilterConfig;
	
	sFilterConfig.FilterBank = 0;						//筛选器编号, CAN1是0-13, CAN2是14-27
	sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;	//采用掩码模式
	sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;	//设置筛选器的尺度, 采用32位
	sFilterConfig.FilterIdHigh = 0X0000;				//过滤器ID高16位,即CAN_FxR1寄存器的高16位
	sFilterConfig.FilterIdLow = 0X0000;					//过滤器ID低16位,即CAN_FxR1寄存器的低16位
	sFilterConfig.FilterMaskIdHigh = 0X0000;			//过滤器掩码高16位,即CAN_FxR2寄存器的高16位
	sFilterConfig.FilterMaskIdLow = 0X0000;				//过滤器掩码低16位,即CAN_FxR2寄存器的低16位
	sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;	//设置经过筛选后数据存储到哪个接收FIFO
	sFilterConfig.FilterActivation = ENABLE;			//是否使能本筛选器
	sFilterConfig.SlaveStartFilterBank = 14;			//指定为CAN1分配多少个滤波器组
	
	if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
	{
		Error_Handler();
	}
}
  • 编写发送和接收数据函数:此处将格式固定为标准数据帧,ID为12
uint8_t CAN1_Send_Msg(uint8_t *msg, uint8_t len){
	uint16_t i = 0;
	uint32_t txMailBox;
	uint8_t send_buf[8];
	
	txHeader.StdId = 12;
	txHeader.ExtId = 12;
	txHeader.IDE = CAN_ID_STD;
	txHeader.RTR = CAN_RTR_DATA;
	txHeader.DLC = len;
	
	for(i = 0; i < len; i++)
		send_buf[i] = msg[i];
	
	if(HAL_CAN_AddTxMessage(&hcan1, &txHeader, send_buf, &txMailBox) != HAL_OK)
		return 1;	
	return 0;
}

uint8_t CAN1_Recv_Msg(uint8_t *buf){
	uint16_t i = 0;	
	HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &rxHeader, buf);
	
	if(rxHeader.IDE == CAN_ID_STD)
		printf("StdId ID: %d\r\n", rxHeader.StdId);
	else
		printf("ExtId ID: %d\r\n", rxHeader.ExtId);
	
	printf("CAN IDE: %d\r\n", rxHeader.IDE);
	printf("CAN RTR: %d\r\n", rxHeader.RTR);
	printf("CAN DLC: %d\r\n", rxHeader.DLC);
	printf("Recv Data: ");
	
	for(i = 0; i < rxHeader.DLC; i++)
		printf("%c",buf[i]);
	
	printf("\n");
	return rxHeader.DLC;
}
  • 默认Cubemx生成的代码并没有can start,没有调用HAL_CAN_Start(&hcan1) 来使能CAN,因此需要在CAN初始化代码中添加
void MX_CAN1_Init(void){
	......
	/* USER CODE BEGIN CAN1_Init 2 */
	CAN_Filter_Config();
	HAL_CAN_Start(&hcan1);	
  	/* USER CODE END CAN1_Init 2 */
}
  • 主函数main.c中,代码如下
int main(void){
  	HAL_Init();
  	SystemClock_Config();
 	MX_GPIO_Init();
  	MX_CAN1_Init();
  	MX_USART1_UART_Init();
  	/* USER CODE BEGIN 2 */
	uint8_t ret,i;
	printf("CAN Testing....!\r\n");
	uint8_t txdata[8] = {76, 79, 79, 80, 66, 65, 67, 75};
	uint8_t rxdata[8];
  	/* USER CODE END 2 */
  	/* Infinite loop */
  	/* USER CODE BEGIN WHILE */
  	while (1)
  	{
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);
		HAL_Delay(1000);
		printf("Start Send data...\r\n");
		
		ret = CAN1_Send_Msg(txdata, 8);
		if(ret == 0)
			printf("CAN Send success!\r\n");
		else 
			printf("CAN Send failed!\r\n");
		
		CAN1_Recv_Msg(rxdata);	
		printf("+++++++++++++++++++++++++++++++\r\n");
    	/* USER CODE END WHILE */
    	/* USER CODE BEGIN 3 */
  	}
  	/* USER CODE END 3 */
}

三、下载测试

编译无误后下载到开发板,可以看到系统运行时D1指示灯不断闪烁,串口不断的打印CAN环回测试的数据

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/70000.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flink系列之Flink中四层Graph详解

title: Flink系列 四、Flink Runtime 四层 Graph 详解 首先回顾一下 Flink 的整体架构设计&#xff1a; {% asset_img processes.svg %} 关于上图中的一些概念的解释&#xff1a; 1、DataFlow Graph 是一个逻辑概念&#xff0c;表示这个应用程序的一个执行图&#xff0c;事…

开关电源环路笔记(11)-TL431电路的几个电阻的取值

上次文章发出来后&#xff0c;有兄弟留言布置了作业&#xff0c;让说说几个电阻的取值&#xff0c;就是下图的Rled&#xff0c;Rbias&#xff0c;R1&#xff0c;Rlower等。那么就写写吧&#xff0c;毕竟&#xff0c;这个电路确实用得非常多&#xff0c;实际工作中确实也需要知道…

登录信息记录模块实现(UserAgentUtils)

如果文章对你有帮助欢迎【关注❤️❤️❤️点赞&#x1f44d;&#x1f44d;&#x1f44d;收藏⭐⭐⭐】一键三连&#xff01;一起努力&#xff01; 一、UserAgentUtils简介 user-agent-utils 是一个用来解析 User-Agent 字符串的 Java 类库。 其能够识别的内容包括&#xff1a…

32_STM32内部温度传感器实验

目录 内部温度传感器简介 STM32ADC对应引脚 内部温度传感器使用注意使用事项 开启内部温度传感器步骤 实验源码 内部温度传感器简介 内部温度传感器框图 从图上可以看出温度传感器可通过TSVREFR控制位连接到ADC的固定通道16,温度的值最终肯定是被转换成电压值,电压值然后通…

学会python这十个语言技法,让你有上手风范

如何让你的代码更有python味&#xff1f; 大部分编程语言都有共性&#xff0c;也有个性。下手害怕个性&#xff0c;视为异端&#xff0c;抵触之&#xff1b;上手善用个性&#xff0c;欣欣然&#xff0c;妙用之。 1、三元表达式 别抱怨python没有三元表达式&#xff0c;请看&…

《大数据导论》之数据的概念、类型和组织形式

目录 说在前面 一、数据的概念 二、数据类型 ​三、数据组织形式 说在前面 大数据时代悄然来临&#xff0c;带来了整个信息技术发展的巨大变革&#xff0c;并深刻影响着社会生产和人们生活的方方面面。全球范围内&#xff0c;世界各国政府也非常重视整个大数据的研究和产业…

hadoop pig-0.17.0 安装配置

下载Apache Pig 首先&#xff0c;从以下网站下载最新版本的Apache Pig&#xff0c;下载Pig步骤取自W3C&#xff1a;Pig安装教程 步骤1 打开Apache Pig网站的主页。在News部分下&#xff0c;点击链接release page&#xff08;释放&#xff09;&#xff0c;如下面的快照所示。 步…

解决git中出现的“bash syntax error near unexpected token ’(‘”错误

今天来分享一篇关于我在git使用过程中出现的一个错误。 错误信息&#xff1a; bash: syntax error near unexpected token (’ 翻译过来就是提示我在’(这里有错误&#xff0c;而这个错误是我在使用git commit提交时候产生的&#xff0c;我当时是这么写的&#xff1a; git c…

java中Optional的应用,以及map和flatMap的区别

关于Option的介绍可以看深入理解java8中的Optional 类就可以了&#xff0c;但是复杂一点的使用在网上却没有搜到&#xff0c;这里结合我开发时遇到的真实案例来讲一下Option的使用。 1.案例一 在真实业务操作过程中&#xff0c;都是对象里面套对象&#xff0c;这边先简单定义操…

flink window 框架详细解读

1. dataStream window group window time window 基于时间驱动 滚动时间窗口 tumble time window 滑动时间窗口 sliding time window 会话时间窗口 session time window count window 基于数据驱动 滚动计数窗口 tumble count window 滑动计数窗口 sliding count window 2. s…

皕杰报表之雷达图

雷达图&#xff08;又可称为戴布拉图、螂蛛网图&#xff09;是数据分析报表的一种。即将各项数据分析所得的数字或比率&#xff0c;就其比较重要的项目集中划在一个图表上&#xff0c;来表现一组数据的各项数据比率的情况&#xff0c;使用者能一目了然的了解这个数据的指标的变…

LeetCode中等题之通过最少操作次数使数组的和相等

题目 给你两个长度可能不等的整数数组 nums1 和 nums2 。两个数组中的所有值都在 1 到 6 之间&#xff08;包含 1 和 6&#xff09;。 每次操作中&#xff0c;你可以选择 任意 数组中的任意一个整数&#xff0c;将它变成 1 到 6 之间 任意 的值&#xff08;包含 1 和 6&#…

计算机组成大题分析(三)

假定计算机 M 字长为 16 位&#xff0c;按字节编址&#xff0c;连接 CPU 和主存的系统总线中地址线为 20 位、数据线为 8位&#xff0c;采用 16 位定长指今字&#xff0c;指令格式及其说明如下: 其中&#xff0c;op1-op3 为操作码&#xff0c;rs&#xff0c;t 和 rd 为通用寄存…

【计算机视觉+CNN】keras+ResNet残差网络实现图像识别分类实战(附源码和数据集 超详细)

需要源码和数据集请点赞关注收藏后评论区留言私信~~~ 一、深度卷积神经网络模型结构 1&#xff1a;LeNet-5 LeNet-5卷积神经网络首先将输入图像进行了两次卷积与池化操作&#xff0c;然后是两次全连接层操作&#xff0c;最后使用Softmax分类器作为多分类输出&#xff0c;它对…

MySQL插入汉字报错的解决方案

MySQL插入汉字报错的原因是字符集的问题&#xff0c;MySQL默认使用的是Latin&#xff08;拉丁文&#xff09;字符集&#xff0c;可以在创建数据库时指定其字符集&#xff1a;CREATE DATABASE test DEFAULT CHARACTER SET utf8 或者修改MySQL的配置文件&#xff0c;可以参考以下…

Qt事件循环嵌套,BlockingQueuedConnection与QWaitCondition比较

前言&#xff1a; 之前写过有关事件循环和条件变量的博客&#xff1a; Qt使用事件循环&#xff0c;信号&#xff0c;stop变量&#xff0c;sleep阻塞&#xff0c;QWaitConditionQMutex条件变量&#xff0c;退出子线程工作_大橘的博客-CSDN博客_qt stop函数 Qt事件循环&#x…

Unity3D导出Android工程中使用并交互

, 目录 1&#xff0c;版本信息 2&#xff0c;前期准备 Unity方面&#xff1a; Android方面&#xff1a; 3&#xff0c;Android与Unity3D交互 1&#xff0c;版本信息 unity2020 android studio 2021 *不要用android studio 2020系列&#xff0c;存在不能导入Library的b…

Spring学习 | Bean作用域生命周期

文章目录一、作用域1.1 xml文件中配置1.2 注解配置二、生命周期2.1 四个阶段2.2 添加后置处理器2.3 实现aware类型接口2.4 Bean 初始化的方式2.5 Bean 销毁的方式2.6 测试程序学习视频&#x1f3a5;&#xff1a;https://www.bilibili.com/video/BV1Vf4y127N5 一、作用域 ❓ 引入…

Linux系统中裸机按键中断的驱动方法

大家好&#xff0c;今天主要和大家聊一聊&#xff0c;如何实现按键中断的驱动​方法。 目录 ​第一&#xff1a;外部中断头文件实现 ​第二&#xff1a;外部中断源文件的具体实现 ​第三&#xff1a;编写对应的main.c函数 ​第一&#xff1a;外部中断头文件实现 #ifndef _…

基于keras平台CNN神经网络模型的服装识别分析

在许多介绍图像识别任务的介绍中&#xff0c;通常使用着名的MNIST数据集。 最近我们被客户要求撰写关于图像识别的研究报告&#xff0c;包括一些图形和统计输出。但是&#xff0c;这些数据存在一些问题&#xff1a; 1.太简单了。例如&#xff0c;一个简单的MLP模型可以达到99…