CAN通信配置过滤器和使用三个邮箱发送

这篇具有很好参考价值的文章主要介绍了CAN通信配置过滤器和使用三个邮箱发送。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

RM比赛用的电机基本都使用CAN通信,但是一条CAN线上只用一个发送邮箱在挂在设备多的情况可能会导致发送不完,但其实完全可以把三个发送邮箱都用上。这里贴一下自己的CAN筛选器,接收以及发送的代码。

完整的工程可以看我开源的飞机云台程序~

项目代码开源地址: https://github.com/ittuann/RoboMaster_UAV-Gimbal_Ares2022

/**
  * @brief          CAN筛选器
  */
void Can_Filter_Init(void)
{
	/***	CAN1	***/
    CAN_FilterTypeDef sFilterConfig;
	sFilterConfig.FilterActivation = ENABLE;			// 激活过滤器
	sFilterConfig.FilterBank = 0;						// 配置主CAN筛选器组编号
	sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;	// 配置工作模式为列表模式
	sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;	// 配置筛选器的尺度为16位长
	sFilterConfig.FilterIdHigh = 0x0000;				// CAN_FxR1寄存器
	sFilterConfig.FilterIdLow = 0x0000;
	sFilterConfig.FilterMaskIdHigh = 0x0000;			// CAN_FxR2寄存器
	sFilterConfig.FilterMaskIdLow = 0x0000;
	sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;	// 筛选器接筛选报文关联到FIFO0
	
	if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) {						// 配置CAN1接收筛选过滤器
		Error_Handler();
	}
	if (HAL_CAN_Start(&hcan1) != HAL_OK) {												// 开启CAN1
		Error_Handler();
	}
	if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) {	// 开启CAN1的FIFO0接收中断
		Error_Handler();
	}
}
  • 过滤的方法分为以下两种模式:

    • 标识符列表模式(CAN_FILTERMODE_IDLIST):它把要接收报文的ID列成一个表, 要求报文ID与列表中的某一个标识符完全相同才可以接收,可以理解为白名单管理。
    • 掩码模式(CAN_FILTERMODE_IDMASK):它把可接收报文ID的某几位作为列表,这几位被称为掩码, 可以把它理解成关键字搜索,只要掩码(关键字)相同,就符合要求,报文就会被保存到接收FIFO。
  • CAN_FilterNumber 用于设置筛选器的编号,即本过滤器结构体配置的是哪一组筛选器,CAN一共有28个筛选器,所以它的可输入参数范围为0-27。如果是双CAN的情况,一般CAN1为0-13,CAN2为14-27。

  • CAN_FilterFIFOAssignment 用于设置当报文通过筛选器的匹配后,该报文会被存储到哪一个接收FIFO

  • 每组筛选器包含2个32位的寄存器,分别为CAN_FxR1CAN_FxR2,它们用来存储要筛选的ID或掩码

模式 CAN FilterldHigh CAN FilterldLow CAN FilterMaskIdHigh CAN FilterMaskIdLow
32位列表 ID1 的高16位 ID1 的低16位 ID2 的高16位 ID2 的低16位
16位列表 ID1 的完整数值 ID2 的完整数值 ID3 的完整数值 ID4 的完整数值
32位掩码 ID1 的高16位 ID1 的低16位 ID1 掩码的高16位 ID1 掩码的低16位
16位掩码模 ID1 的完整数值 ID2 的完整数值 ID1 掩码的完整数值 ID2 掩码完整数值

CAN通信的发送函数如下,以RM比赛用的M3508无刷电机使用的C620电调的通信协议为例

#include <stdbool.h>

/**
  * @brief          发送C620电调控制电流
  * @param[in]		motorID对应的电机控制电流, 范围 [-16384, 16384],对应电调输出的转矩电流范围 [-20A, 20A]
  * @param[in]      etcID: 控制报文标识符(电调ID)为1-4还是5-8
  */
void CAN_Cmd_C620(CAN_HandleTypeDef *hcan, int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4, bool_t etcID)
{
	CAN_TxHeaderTypeDef TxHeader;						// CAN通信协议头
	uint8_t TxData[8] = {0};							// 发送电机指令缓存
	uint32_t TxMailboxX = CAN_TX_MAILBOX0;				// CAN发送邮箱

	if (etcID == false) {
		TxHeader.StdId = CAN_3508_ALL_ID;				// 标准格式标识符ID
	} else {
		TxHeader.StdId = CAN_3508_ETC_ID;
	}
	TxHeader.ExtId = 0;
	TxHeader.IDE = CAN_ID_STD;							// 标准帧
	TxHeader.RTR = CAN_RTR_DATA;						// 传送帧类型为数据帧
	TxHeader.DLC = 0x08;								// 数据长度码
	TxData[0] = (uint8_t)(motor1 >> 8);
	TxData[1] = (uint8_t)motor1;
	TxData[2] = (uint8_t)(motor2 >> 8);
	TxData[3] = (uint8_t)motor2;
	TxData[4] = (uint8_t)(motor3 >> 8);
	TxData[5] = (uint8_t)motor3;
	TxData[6] = (uint8_t)(motor4 >> 8);
	TxData[7] = (uint8_t)motor4;

	//找到空的发送邮箱 把数据发送出去
	while (HAL_CAN_GetTxMailboxesFreeLevel(hcan) == 0);	// 如果三个发送邮箱都阻塞了就等待直到其中某个邮箱空闲
	if ((hcan->Instance->TSR & CAN_TSR_TME0) != RESET) {
		// 检查发送邮箱0状态 如果邮箱0空闲就将待发送数据放入FIFO0
		TxMailboxX = CAN_TX_MAILBOX0;
	} else if ((hcan->Instance->TSR & CAN_TSR_TME1) != RESET) {
		TxMailboxX = CAN_TX_MAILBOX1;
	} else if ((hcan->Instance->TSR & CAN_TSR_TME2) != RESET) {
		TxMailboxX = CAN_TX_MAILBOX2;
	}
	// 将数据通过CAN总线发送
	#if DEBUGMODE
		if (HAL_CAN_AddTxMessage(hcan, &TxHeader, TxData, (uint32_t *)TxMailboxX) != HAL_OK) {
			Error_Handler();
		}
	#else
		HAL_CAN_AddTxMessage(hcan, &TxHeader, TxData, (uint32_t *)TxMailboxX);
	#endif
}
  • IDE存储的是扩展标志。当它的值为宏CAN_ID_STD时表示本报文是标准帧,使用StdId成员存储报文ID; 当它的值为宏CAN_ID_EXT时表示本报文是扩展帧,使用ExtId成员存储报文ID。ExtIdStdId这两个成员根据IDE位配置,只有一个是有效的。

  • RTR是报文类型标志。当它的值为宏CAN_RTR_Data时表示本报文是数据帧;当它的值为宏CAN_RTR_Remote时表示本报文是遥控帧。 由于遥控帧没有数据段,所以当报文是遥控帧时,下面的Data[8]是无效的。

  • 可以加上判断状态是否为HAL_OK,如果CAN信息发送失败则进入Error_Handler()死循环。测试时可以打断点判断问题所在,但正式版本时不想给运行着的程序增加可能卡死循环的风险所以会关掉判断。while循环等待空邮箱也可以关掉。文章来源地址https://www.toymoban.com/news/detail-461747.html

/**
  * @brief			HAL库CAN FIFO0接受邮箱中断(Rx0)回调函数
  * @param			hcan : CAN句柄指针
  */
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    static BaseType_t xHigherPriorityTaskWoken = pdFALSE;	// 不请求上下文切换
	CAN_RxHeaderTypeDef RxHeader;							// CAN通信协议头
	uint8_t rx_data[8] = {0};								// 暂存CAN接收数据
	motor_measure_t motorDataTmp;							// 电机数据
	uint8_t i = 0;
	
	if (hcan == &hcan1)
	{
		if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, rx_data) == HAL_OK)	// 接收CAN总线上发送来的数据
		{
			// 对应电机向总线上发送的反馈的标识符和程序电机序号
            switch (RxHeader.StdId) {
                case CAN_PITCH_MOTOR_ID : i = MotorID_GimbalPitch; break;
                case CAN_YAW_MOTOR_ID : i = MotorID_GimbalYaw; break;
				#if DEBUGMODE
                	default : i = RxHeader.StdId - CAN_3508_M1_ID; break;
				#endif
            }
            // 电机返回数据协议解析
            get_motor_measure(&motorDataTmp, rx_data);
            // 向消息队列中填充数据
            if (messageQueueCreateFlag) {
                xQueueOverwriteFromISR(messageQueue[i], (void *)&motorDataTmp, &xHigherPriorityTaskWoken);
                portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
            }
		}
	}
}

到了这里,关于CAN通信配置过滤器和使用三个邮箱发送的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Javaweb | 过滤器、配置、过滤器链、优先级

    💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! 概念 过滤器(Filter)是处于客户端与服务器目标资源之间的一道过滤技术 用户的请求和响应都需要经过过滤器 过滤器作用 执行地位在Servlet之前,客户端发送请求是,会先经过Filter,再到达目标Servlet中;响应时,会根

    2023年04月17日
    浏览(53)
  • SpringBoot在使用SpringSecurity时,配置跨域过滤器CorsFilter不生效分析解决

    此文中代码只粘贴部分代码,完整版请自行查看 请求一般为重启debug服务再次请求 一般配置方法(适用于没有SpringSecurity配置时) SpringSecurity配置时配置方法 首先说明Spring中过滤器加载使用的是FilterRegistrationBean配置过滤器,FilterRegistrationBean实现了Ordered接口,order排序值默认值为

    2024年01月20日
    浏览(49)
  • 异常过滤器—MVC中异常过滤器使用

    异常过滤器( Exception Filters )是 ASP.NET Core 中用于处理全局异常的机制。它们允许你在发生异常时捕获、处理和记录异常,并提供自定义的异常处理逻辑。异常过滤器在整个应用程序范围内生效,可以用于处理各种异常情况。用于实现常见的错误处理策略,没有之前和之后事

    2024年02月13日
    浏览(59)
  • 结果过滤器—MVC项目中结果过滤器(Result Filter)使用

    结果过滤器( ResultFilter ),是对执行的Action结果进行处理的一种AOP思想,适用于任何需要直接环绕 View 或格式化处理的逻辑。结果过滤器可以 替换或更改 Action 结果 。在 IActionResult 执行的前后执行,使用它能够控制Action的执行结果,比如:格式化结果等。需要注意的是,它只

    2024年02月12日
    浏览(55)
  • 操作过滤器—MVC中使用操作过滤器实现JWT权限认证

    上一篇文章分享了授权过滤器实现JWT进行鉴权,文章链接:授权过滤器—MVC中使用授权过滤器实现JWT权限认证,接下来将用操作过滤器实现昨天的JWT鉴权。 ​ 与授权过滤器大部分一样,只是执行的时机和继承的接口有所不同。操作过滤器是在Action执行的前和后进行调用执行

    2024年02月13日
    浏览(51)
  • 高手速成 | 过滤器、监听器的创建与配置

       本节讲解过滤器、监听器的创建以及监听事件配置示例。 【例1】创建过滤器及配置过滤规则。 (1) 在Eclipse中新建一个Web项目,取名为Chapt_09。在src目录下,新建一个名为com.test.filter的包。选中该包并按Ctrl+N组合键,在弹出的菜单中选择Web→Filter。选择创建过滤器,如图

    2024年02月06日
    浏览(53)
  • springboot使用过滤器

    过滤器是处于客户端与服务器资源文件之间的一道过滤网,帮助我们过滤一些不符合要求的请求。通常用作 Session校验,判断用户权限。 使用过滤器很简单,只需要实现Filter类,然后重写它的3个方法即可。 init方法:程序启动调用Filter的init()方法(永远只调用一次);在容器中

    2024年02月15日
    浏览(55)
  • 自定义过滤器配置 Shiro 认证失败返回 json 数据

    by emanjusaka from ​ https://www.emanjusaka.top/2023/10/filter-shiro-authentication-error-json 彼岸花开可奈何 本文欢迎分享与聚合,全文转载请留下原文地址。 Shiro 权限框架认证失败默认是重定向页面的,这对于前后端分离的项目及其不友好,可能会造成请求404的问题。现在我们自定义过滤器

    2024年02月08日
    浏览(43)
  • Vue过滤器基本使用

    在Vue 2中,你可以使用 filters 选项来定义过滤器。以下在组件中定义和使用过滤器的简单例子: 1、app.vue 使用methods实现: 2、使用filters配合computed计算属性实现: 3、引入其他组件FilterFix.vue实现: app.vue FilterFix.vue main.js

    2024年02月09日
    浏览(56)
  • 资源过滤器—MVC中使用资源过滤器实现不执行Action方法体读取缓存信息返回

    上两篇文章分享了过滤器实现JWT进行鉴权,分别是通过授权过滤器和操作过滤器实现,这两个过滤器也是最常用的。文章链接:授权过滤器—MVC中使用授权过滤器实现JWT权限认证,操作过滤器—MVC中使用操作过滤器实现JWT权限认证,接下来将简单的谈谈资源过滤器在MVC中如何

    2024年02月13日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包