【STM32CubeMX】F103 BxCAN

F103&BxCAN

bxCAN总体描述

  • 有一个增强的过滤机制来处理各种类型的报文此外,应用层任务需要更多CPU时间,因此报文接收所需的实时响应程度需要减轻。

  • 接收FIFO的方案允许,CPU花很长时间处理应用层任务而不会丢失报文。 构筑在底层CAN驱动程序上的高层协议软件,跟CAN控制器之间有高效的接口。

BxCAN与CAN的区别?

  1. 硬件结构:BxCAN是基本扩展CAN(Basic Extended CAN)的缩写,它支持CAN协议2.0A和2.0B。而CAN通常只有一个主控制器。
  2. 功能:BxCAN具有更多的功能,例如时间触发通信模式。在该模式下,CAN硬件的内部定时器被激活,并且被用于产生(发送与接收邮箱的)时间戳,分别存储在CAN_RDTxR/CAN_TDTxR寄存器中。内部定时器在每个CAN位时间累加。内部定时器在接收和发送的帧起始位的采样点位置被采样,并生成时间戳。

功能名词

标识符过滤:在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的。因此,发送者乙 广播的形式把报文发送给所有的接收者。节点在接收报文时-根据标识符的值-决定软件是否 需要该报文;如果需要,就拷贝到SRAM里;如果不需要,报文就被丢弃且无需软件的干预。

数据结构

  • CAN过滤器配置结构定义

    typedef struct
    {
      uint32_t FilterIdHigh;          // 指定过滤器标识号的高16位,范围0x0000~0xFFFF
      uint32_t FilterIdLow;           // 指定过滤器标识号的低16位,范围0x0000~0xFFFF
      uint32_t FilterMaskIdHigh;      // 用于设置过滤器掩码高16位,范围0x0000~0xFFFF
      uint32_t FilterMaskIdLow;       // 用于设置过滤器掩码低16位,范围0x0000~0xFFFF
      uint32_t FilterFIFOAssignment;  // 指定将分配给过滤器的FIFO(0或1U),该参数可以是@ref CAN_filter_FIFO的值
      uint32_t FilterBank;            // 指定要初始化的筛选器组,对于单个CAN实例(14个专用过滤器组),该参数必须是0~13之间。对于双CAN实例(28个过滤器组共享),该参数必须是0~27之间。
      uint32_t FilterMode;            // 指定要初始化的筛选器模式,列表模式和掩码模式,该参数可以是@ref CAN_filter_mode的值
      uint32_t FilterScale;           // 指定过滤器的规模,该参数可以是@ref CAN_filter_scale的值
      uint32_t FilterActivation;      // 启用或禁用过滤器,该参数可以是@ref CAN_filter_activation的值
      uint32_t SlaveStartFilterBank;  // 为从CAN实例选择启动过滤器组,对于单个CAN实例,此参数没有意义。对于双CAN实例,索引较低的滤波器组分配给主CAN实例,索引较大的滤波器组分配给从CAN实例。该参数必须为0~27之间。
    
    } CAN_FilterTypeDef;
    
  • CAN Tx消息头结构定义

    typedef struct
    {
      uint32_t StdId;    // 指定标准标识符,范围0~0x7FF
      uint32_t ExtId;    // 指定扩展标识符,范围0~0x1FFFFFFF
      uint32_t IDE;      // 指定要传输的消息的标识符类型。该参数可以是@ref CAN_identifier_type
      uint32_t RTR;      // 指定要传输的消息的帧类型。该参数可以是@ref CAN_remote_transmission_request
      uint32_t DLC;      // 指定要传输的帧的长度,范围0~8
      FunctionalState TransmitGlobalTime;	//指定时间戳计数器值是否在开始时捕获在帧传输中,以DATA6和DATA7代替pData[6]和pData[7]发送。@注:必须启用“时间触发通信模式”。@注意:DLC必须被编程为8字节,为了这2字节被发送。可设置为“ENABLE”或“DISABLE”。
    
    } CAN_TxHeaderTypeDef;
    
  • CAN Rx消息头结构定义

    typedef struct
    {
      uint32_t StdId;    	// 指定标准标识符,范围0~0x7FF
      uint32_t ExtId;    	// 指定扩展标识符,范围0~0x1FFFFFFF
      uint32_t IDE;      	// 指定要传输的消息的标识符类型。该参数可以是@ref CAN_identifier_type
      uint32_t RTR;      	// 指定要传输的消息的帧类型。该参数可以是@ref CAN_remote_transmission_request
      uint32_t DLC;      	// 指定要传输的帧的长度,范围0~8
      uint32_t Timestamp; 	//指定在帧接收开始时捕获的时间戳计数器值。@注:必须启用“时间触发通信模式”。该参数必须为0~0xFFFF。
      uint32_t FilterMatchIndex; // 指定匹配接受筛选元素的索引。该参数必须为0~0xFF
    
    } CAN_RxHeaderTypeDef;
    

相关资料

下面图片摘录于STM32F10xxx参考手册(中文)

  • 注意手册里也提醒了,要是想跑CAN总线的化,还需要CAN收发器,MCU只能提供CAN_Rx,CAN_Tx,不要搞混了。

    在这里插入图片描述

  • 这里是过滤器的寄存器的含义图,因为我没找到其它的关于解释过滤器关于CAN中标准的ID的位置到底在哪里,下面两张图就有,比如STID的含义就是CAN协议中的标准ID,而且它也是通过程序也知道它是对应着过滤器结构中FilterIdHigh,FilterIdLow之类的,方便理解下面的程序,为什么要移位。

    在这里插入图片描述

    在这里插入图片描述

  • 这个说实话,没看懂这样的定义是啥,32位的仲裁域?还是标准标识符,怪怪的。但是是手册中唯一,一张有介绍CAN帧的图,所以就顺便截出来了,万一大家有自己的理解。

    在这里插入图片描述

前置配置

  • STM32CubeMX中配置

    在STM32CubeMX中配置,RCC配置使用高速外部晶振,开启USART1,配置PC13为输出模式(点灯),CAN配置(下面附图)其它的省略配置过程。

    在这里插入图片描述

    在这里插入图片描述

  • 配置完后生成,Keil5打开。

相关程序

以下函数都可以写在main.c中,只不过分块写更容易理解。

初始化相关的

// 开启CAN
HAL_CAN_Start(&hcan);

发送相关的

/*
* @描述:CAN发送函数
* @参数:id(CAN发送的ID号)
* @参数:idMode(帧ID号类型选择)
         CAN_ID_STD:标准ID号
         CAN_ID_EXT:扩展ID号
* @参数:*pData(要发送的数据)
* @参数:len(发送的数据长度)
*				 范围 0 ~ 8
* @返回值: 返回0:正常  返回1:异常
*/
uint8_t CAN_SendData(uint32_t id,uint8_t idMode,uint8_t *pData,uint8_t len)
{
	CAN_TxHeaderTypeDef pHeader;
	uint32_t pTxmailbox;
	uint8_t result = 0;
	
	if(idMode == CAN_ID_STD)
	{
		pHeader.StdId = id;   		//标准ID号
		pHeader.IDE = CAN_ID_STD;	//标准ID
	}
	else
	{
		pHeader.ExtId = id;				//扩展ID号
		pHeader.IDE = CAN_ID_STD;	//扩展ID
	}
	
	pHeader.RTR = CAN_RTR_DATA;	//传输数据的帧类型为数据帧
	pHeader.DLC = len>8?8:len;	//发送数据的字节长度,最大为8个字节
	pHeader.TransmitGlobalTime = DISABLE;	//是否要发送时间戳
	
	// CAN发送函数
	if(HAL_CAN_AddTxMessage(&hcan, &pHeader, pData, &pTxmailbox) != HAL_OK)
	{
		return 1;
	}
	return 0;
}

接收相关的

过滤模式:部分ID位数相同也能接收  列表模式:必须是指定ID才能接收

两种模式的程序都在下面,测试时,二选一验证就行了。

  • 列表模式
/*
* @描述:CAN过滤器配置,接收模式采用的是列表模式,
*			  该id不管是标准帧还有扩展帧都适用,因为两个
*				筛选id的寄存器分别写入了它的标准帧和扩展帧
* @参数:id(筛选的ID号)
*/
void CAN_Fliter_Config_IDLIST(uint32_t id)
{
	CAN_FilterTypeDef hcan_filterconfig;
	
	hcan_filterconfig.FilterActivation = CAN_FILTER_ENABLE;		//过滤器使能
	hcan_filterconfig.FilterBank = 0;  												//使用过滤器0
	hcan_filterconfig.FilterMode = CAN_FILTERMODE_IDLIST;			//采用列表模式
	hcan_filterconfig.FilterScale = CAN_FILTERSCALE_32BIT;		//采用32位掩码模式
	hcan_filterconfig.FilterFIFOAssignment = CAN_FilterFIFO0;	//使用FIFO0
	
	hcan_filterconfig.FilterIdHigh =     id << 5;																					//过滤器ID高16位
	hcan_filterconfig.FilterIdLow =      0 | CAN_ID_STD | CAN_RTR_DATA;    								//过滤器ID低16位,CAN_ID_STD(标准ID)、CAN_RTR_DATA(帧类型为数据帧)
	hcan_filterconfig.FilterMaskIdHigh = ((id<<3)>>16)&0xffff;														//过滤器掩码高16位
	hcan_filterconfig.FilterMaskIdLow =  ((id<<3) & 0xffff) | CAN_ID_EXT | CAN_RTR_DATA;	//过滤器掩码低16位,CAN_ID_EXT(扩展ID)、CAN_RTR_DATA(帧类型为数据帧)

	
	hcan_filterconfig.SlaveStartFilterBank = 14; 		//过滤器数量14
	HAL_CAN_ConfigFilter(&hcan,&hcan_filterconfig); //初始化过滤器
	HAL_CAN_Start(&hcan);	//开启CAN
	//开启CAN-FIFO0中断
	HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING);
}
  • 掩码模式
/*
* @描述:CAN过滤器配置,接收模式采用的是掩码模式。
*				掩码模式,对'1'位,不感兴趣,对'0'位必须匹配。
* @参数:id(筛选的ID号)
* @阐述:mask_if(掩码)
*/
void CAN_Fliter_Config_IDMASK(uint32_t id,uint32_t mask_id)
{
	CAN_FilterTypeDef hcan_filterconfig;
	
	hcan_filterconfig.FilterActivation = CAN_FILTER_ENABLE;	//过滤器使能
	hcan_filterconfig.FilterBank = 0;  											//使用过滤器0
	hcan_filterconfig.FilterMode = CAN_FILTERMODE_IDMASK;		//采用掩码模式
	hcan_filterconfig.FilterScale = CAN_FILTERSCALE_32BIT;	//采用32位掩码模式
	hcan_filterconfig.FilterFIFOAssignment = CAN_FilterFIFO0;	//使用FIFO0
	
//	hcan_filterconfig.FilterIdHigh =     (((((uint32_t)id)<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xffff0000)>>16;//过滤器ID高16位,CAN_ID_EXT(扩展ID)、CAN_RTR_DATA(帧类型为数据帧)
//	hcan_filterconfig.FilterIdLow =      (((((uint32_t)id)<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0x0000ffff);    //过滤器ID低16位,CAN_ID_EXT(扩展ID)、CAN_RTR_DATA(帧类型为数据帧)
//	hcan_filterconfig.FilterMaskIdHigh = (mask_id & 0xffff0000)>>16;	//过滤器掩码高16位
//	hcan_filterconfig.FilterMaskIdLow =  mask_id & 0x0000ffff;      	//过滤器掩码低16位
	
	hcan_filterconfig.FilterIdHigh =     id << 5;														//过滤器ID高16位,CAN_ID_EXT(扩展ID)、CAN_RTR_DATA(帧类型为数据帧)
	hcan_filterconfig.FilterIdLow =      0 | CAN_ID_STD | CAN_RTR_DATA;    	//过滤器ID低16位,CAN_ID_EXT(扩展ID)、CAN_RTR_DATA(帧类型为数据帧)
	hcan_filterconfig.FilterMaskIdHigh = 0x00;			//过滤器掩码高16位
	hcan_filterconfig.FilterMaskIdLow =  0x00;      				//过滤器掩码低16位
	
	hcan_filterconfig.SlaveStartFilterBank = 14; 		//过滤器数量14
	HAL_CAN_ConfigFilter(&hcan,&hcan_filterconfig); //初始化过滤器
	HAL_CAN_Start(&hcan);	//开启CAN
	HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING);//开启CAN-FIFO0中断
}

中断回调函数

/*CAN-FIFO0中断回调函数*/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)  
{  
    CAN_RxHeaderTypeDef RxHeader;  
    uint8_t RxData[8];				// 存储接收数据
    uint32_t RxDataLength;  	// 数据长度
	
    if(hcan->Instance == CAN1)  
    {  
        // 从FIFO中读取消息  
        if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)  
        {  
            // 处理读取错误 
        }  
        
				// 获取数据长度
        RxDataLength = RxHeader.DLC;  
          
        // 判断是标准帧还是扩展帧,并打印相应的ID和简单的验证下前四个字节的数据
        if(RxHeader.IDE == CAN_ID_STD)  
        {  
          printf("接收到标准ID为:0x%X\r\n", RxHeader.StdId); 
					printf("接收到的数据为:%d %d %d %d\r\n",RxData[0],RxData[1],RxData[2],RxData[3]);
        }  
        else if(RxHeader.IDE == CAN_ID_EXT)  
        {  
					printf("接收到扩展ID为:0x%X\r\n", RxHeader.ExtId);  
					printf("接收到的数据为:%d %d %d %d\r\n",RxData[0],RxData[1],RxData[2],RxData[3]);
        }  		
    }  
}

main.c中主函数片段,该片段中只包含用户需要测试编写的,不包括STM32CubeMX生成的其它初始化。

int main()
{
    uint8_t CAN_Send_Data[] = {8,8,8,8,8,8,8,8};
	int Count = 0;
    HAL_CAN_Start(&hcan);//开启CAN
	CAN_Fliter_Config_IDMASK(0x123,0x000);
    while(1)
    {
        // CAN发送函数
		if(CAN_SendData(0x0123,CAN_ID_STD,CAN_Send_Data,8))
		{
			printf("Send Lose!\r\n");
		}
		else
		{
			printf("SendOK:%d\r\n",Count++);
		}

		// 闪烁LED-运行状态灯
		HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
		HAL_Delay(500);
    }
}

串口配置(可选),方便观察到调试现象,不一定要用

// 引入该库为了可以使用 printf 函数
#include "stdio.h" 

//避免使用半主机模式
void _sys_exit(int x)
{
	x = x;
}
//标准库需要支持的函数
struct __FILE
{
	int handle;
};
FILE __stdout;

//重定向print
int fputc(int ch, FILE *f)//printf
{
	//HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET); 	//485发送使能端口 没有可去掉
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1,0xffff);  	//发送一个字节的数据到你希望的串口
	//HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET); 	//485发送使能端口 没有可去掉
	return (ch);
}

实验现象

材料:STM32C6T6两块,CAN收发器两块,若干杜邦线,串口模块,ST-LINK下载器,面包板若干块

程序:配置,闪烁LED观察程序运行状态,调用CAN发送程序并用变量计数程序是否发送成功,并用串口打印出来。

在这里插入图片描述

在这里插入图片描述

程序资料

文中演示的程序

链接:https://pan.baidu.com/s/18lqiq-thWXHbma8eLD9ODw  提取码:7qkw

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件设计中如何画各类图之七了解组件图:系统架构的关键视角

目录 1 前言2 组件图基本介绍3 画组件图的步骤4 组件图的用途5 场景及实际场景举例6 结语 1 前言 组件图是一种UML的图形化表示工具&#xff0c;为系统架构提供了重要视角。它描述了系统中各个组件以及它们之间的依赖关系和连接。用于展示系统中的组件、软件模块、以及它们之间…

简单实现Spring容器(五) 实现bean后置处理器BeanPostProcessor机制

阶段5: // 1.编写自己的Spring容器,实现扫描包,得到bean的class对象. // 2.扫描将 bean 信息封装到 BeanDefinition对象,并放入到Map. // 3.初始化单例池并完成getBean() createBean()方法 // 4.完成依赖注入(如果创建某个Bean对象,存在依赖注入,需要进行bean组装操作) 5.bean…

比较好的python书籍,python有什么书推荐

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;比较好的python书籍&#xff0c;python有什么书推荐&#xff0c;现在让我们一起来看看吧&#xff01; 我是在半年前接触到Python的&#xff0c;我之前没有一点编程基础&#xff0c;但在我自学的这半年里&#xff0c;我发…

绿盟 SAS堡垒机 local_user.php 权限绕过漏洞复现

绿盟 SAS堡垒机 local_user.php 权限绕过漏洞复现 一、 产品简介二、漏洞概述三、 复现环境四、漏洞复现五、小龙检测 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&…

jdom利用纯java技术对xml文档进行解析、生成、序列化等各种操作

Jdom对xml文档进行解析、生成、序列化等各种操作。 使用jdom之前&#xff0c;首先要导入jar包&#xff1a;jdom.jar 获得根元素&#xff1a; 首先确定xml文件位置 String xmlPath "./src/ceshi/Test.xml"; //使用的解析器&#xff0c;这里表示默认的解析…

资本热捧下的预制菜,如何挤出泡沫、回归务实?

在这个被快餐和即食文化主宰的时代&#xff0c;预制菜概念持续被资本热炒。 据悉&#xff0c;近30个交易日里&#xff0c;预制菜概念板块已累计上涨超15%&#xff0c;其中&#xff0c;惠发食品、得利斯、春雪食品等个股更是快速拉涨。但究竟谁才能笑到最后&#xff0c;还充满未…

数据结构和算法 - 数组

1、数组 1.1 简介 什么是数组&#xff1f; 他优缺点是什么&#xff1f;具体应用有哪些&#xff1f; 「数组 array」是一种基于顺序存储的线性数据结构&#xff0c;其将相同类型的元素存储在连续的内存空间中。我们将元素在数组中的位置称为该元素的「索引 index」。 如图&…

IDEA卡顿,进行性能优化设置(亲测有效)——情况一

需求场景 IDEA重新激活后&#xff0c;运行IDEA卡的非常卡顿&#xff0c;没有运行项目&#xff0c;CPU占比也非常高: 原因分析 可能的原因是&#xff0c;在IDEA的配置中&#xff0c;给他分配的空间比较小 解决方式 步骤一 选择顶部导航栏中的Help&#xff0c;然后点击Edi…

Java数据类型相关

数据类型 Java有哪些数据类型 定义&#xff1a;Java语言是强类型语言&#xff0c;对于每一种数据都定义了明确的具体的数据类 型&#xff0c;在内存中分配了不同大小的内存空间。 分类&#xff1a; 基本数据类型 数值型 整数类型(byte,short,int,long) 浮点类型(float,dou…

文本处理工具doctran(集成LLM和NLP库)

今天给大家推荐一款文本处理工具&#xff0c;可以Extract、Redact、Summarize、Refine、Translate、Interrogate&#xff0c;这个工具就是文档转换框架doctran。 欢迎关注公众号 doctran基于OpenAI的GPT模型和开源的NLP库来剖析文本数据。该工具也可以在LangChain框架document…

汇编指令命令

ARM汇编指令学习 工程搭建 汇编编程环境搭建 HN0AE-522LW-NNRAF-63PUS-7IGFH-YF58D 配置编译工具链 为工程配置链接脚本&#xff08;map.lds&#xff09; 将map.lds 复制到工程文件夹(在桌面创建的ARM-ASM文件) 创建汇编文件 接下来我们需要建立一个start.s汇编文件添加到我们的…

基于Microchip 光伏逆变器方案

小编杂谈新能源已经完成了至少5期的博文了&#xff0c;Boss告诉小编&#xff0c;如果还不介绍我们的产品和方案&#xff0c;黄花菜都凉了&#xff0c;所以小编这期博文就重点介绍一下Microchip在储能上的产品介绍&#xff0c;重点聊聊Microchip储能中使用的光伏逆变器的解决方案…

沉浸文旅体验!实时云渲染助力2023广东旅博会智慧文旅元宇宙体验馆上线

2023广东国际旅游产业博览会&#xff08;以下简称旅博会&#xff09;于9月15-17日在广州中国进出口商品交易会展馆A区举办&#xff0c;共设有国际展区、国内展区、智慧文旅展区、文化创意展区、旅游商品展区等五大展区&#xff0c;汇聚了来自全球近40个国家和地区的近千家参展商…

综述 2022-Genome Biology:“AI+癌症multi-omics”融合方法benchmark

Leng, Dongjin, et al. "A benchmark study of deep learning-based multi-omics data fusion methods for cancer." Genome biology 23.1 (2022): 1-32. 被引次数&#xff1a;34作者单位 红色高亮表示写论文中可以借鉴的地方 一、方法和数据集 1. 3个数据集&…

【✅如何针对大Excel做文件读取?】

✅如何针对大Excel做文件读取&#xff1f; &#x1f7e9;如何针对大Excel做文件读取&#x1f7e9;XSSFWorkbook文件读取&#x1f7e9;EasyExcel文件读取 ✅扩展知识&#x1f7e9; EasyExcel简介&#x1f7e9;EasyExcel 为什么内存占用小&#xff1f; &#x1f7e9;如何针对大Ex…

MySQL使用Not in查询效率慢的优化

引言 问题复盘&#xff0c;在查询某个数据不在另一个表中&#xff0c;查询时间非常慢&#xff0c;10几秒。究其原因not in不走索引。那么怎么解决优化呢&#xff0c;下面是简单记录。 原SQL select * from test where a not in ( select a from test2 where status in (1, 2…

由@EnableWebMvc注解引发的Jackson解析异常

同事合了代码到开发分支&#xff0c;并没有涉及到改动的类却报错。错误信息如下&#xff1a; Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.conv…

重新认识Word——给图、表、公式等自动编号

重新认识Word——给图、表、公式等自动编号 给图增加题注题注失败的情况给图添加“如图xx-xx所示” 给公式插入题注第一步——先加题注第二步——设置两个制表符 解决题注“图一-1”的问题 前面我们已经学习了如何引用多级列表自动编号了&#xff0c;现在我们有第二个问题&…

数字病理图像分析的开源软件qupath学习 ①

介绍&#xff1a;QuPath是一种新的生物图像分析软件&#xff0c;旨在满足对用户友好、可扩展、开源解决方案日益增长的需求&#xff0c;用于数字病理学和全玻片图像分析。除了提供全面的肿瘤识别和高通量生物标志物评估工具外&#xff0c;QuPath 还为研究人员提供了强大的批处理…

怎么抠图换背景?这三个方法让你轻松抠图

怎么抠图换背景&#xff1f;抠图是每个独立站商家每天必不可少的工作&#xff0c;简单一张图用PS进行抠图还好&#xff0c;但如何多张图&#xff0c;用PS就效率非常低&#xff0c;且需要专业的PS技能才能上手实现精准抠图的目的&#xff0c;那么怎么快速抠图换背景呢&#xff0…