【通信协议】CAN总线通信协议的学习,(三)stm32f103系列单片机,can通信的代码实现

目录

1、CAN 的基本知识

2、CAN的cubemx配置

3、CAN的代码实现

3.0、初始化,认识函数及变量

3.1、CAN发送

3.1.1、代码1

3.1.2、代码2

3.1.3、代码3

3.2、CAN中断接收

3.2.1、代码1

3.2.2、代码2

3.2.3、代码3

3.3、过滤器

3.3.1、代码1 

3.3.2、代码2


1、CAN 的基本知识

参考:

【通信协议】CAN总线通信协议的学习(一)基础理论知识学习-CSDN博客

2、CAN的cubemx配置

参考:

[通信协议】CAN总线通信协议的学习,(二)stm32f103芯片cubemx配置,CAN总线配置,参数计算及配置-CSDN博客

3、CAN的代码实现

3.0、初始化,认识函数及变量

初始化,在main函数中进行,

1、CAN滤波器的配置、2、启动CAN控制器、3、使能CAN控制器接收中断:

 /* USER CODE BEGIN 2 *//* 1. CAN Filter Config */CANFilter_Config();/* 2. CAN Start */if (HAL_CAN_Start(&hcan1) != HAL_OK) {Error_Handler();}/* 3. Enable CAN RX Interrupt */if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) {Error_Handler();}/* USER CODE END 2 */

 定义CAN发送/接收消息的结构体,在main中或者can.c中都可以,定义全局变量

/* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV */
static CAN_TxHeaderTypeDef        TxMessage;    //CAN发送的消息的消息头
static CAN_RxHeaderTypeDef        RxMessage;    //CAN接收的消息的消息头
/* USER CODE END PV */

3.1、CAN发送

在can.c函数中,添加

3.1.1、代码1

/* CAN 发送数据测试函数 */
void CAN1_Send_Test()
{uint8_t data[4] = {0x01, 0x02, 0x03, 0x04};uint32_t TxMailbox; TxMessage.IDE = CAN_ID_STD;     //设置ID类型,标准TxMessage.StdId = 0x222;        //设置ID号TxMessage.RTR = CAN_RTR_DATA;   //设置传送数据帧TxMessage.DLC = 4;              //设置数据长度if (HAL_CAN_AddTxMessage(&hcan1, &TxMessage, data, (uint32_t*)CAN_TX_MAILBOX0) != HAL_OK) {Error_Handler();}
}

上述代码所使用的一个关键函数

HAL_CAN_AddTxMessage 函数的主要功能是将一个待发送的 CAN 消息添加到发送邮箱中,以便通过 CAN 总线进行传输。

HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox);
  1. hcan:指向 CAN_HandleTypeDef 结构体类型的指针,该结构体包含了 CAN 控制器的相关配置和状态信息,通过它可以访问特定的 CAN 控制器实例。
  2. pHeader:指向 CAN_TxHeaderTypeDef 结构体类型的指针,这个结构体定义了要发送的 CAN 消息的头部信息,包括:
    • StdId 或 ExtId:标准帧标识符或扩展帧标识符,用于确定消息的唯一性。
    • IDE:标识符类型,区分标准帧和扩展帧。
    • RTR:远程传输请求标志,用于请求远程节点发送数据。
    • DLC:数据长度代码,指示消息中数据的长度。
  3. aData:指向要发送的数据缓冲区的指针,数据以字节数组的形式存储。
  4. pTxMailbox:指向一个 uint32_t 类型的变量的指针,该变量用于接收发送邮箱的索引。如果发送成功,函数会将使用的发送邮箱的索引存储在这个变量中

3.1.2、代码2

 HAL_CAN_Start(&hcan);CAN_TxHeaderTypeDef TxHeader;uint8_t TxData[8] = {0x23, 0x81, 0x60, 0x00, 0x55, 0x55, 0x08, 0x00};uint32_t TxMailbox; uint32_t std_id = 0x601;  TxHeader.RTR = CAN_RTR_DATA;TxHeader.IDE = CAN_ID_STD;            TxHeader.StdId=std_id;TxHeader.TransmitGlobalTime = DISABLE;TxHeader.DLC = 8;if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, TxData, &TxMailbox) != HAL_OK){/* Transmission request Error */Error_Handler();}

3.1.3、代码3

这个是stm32 标准库代码,和上面两种hal库代码不同

不过,代码的思路可以借鉴

void MyCAN_Transmit(uint32_t ID, uint8_t Length, uint8_t *Data)
{CanTxMsg TxMessage;      //构建一个发送消息的结构体TxMessage.StdId = ID;TxMessage.ExtId = ID;TxMessage.IDE = CAN_Id_Standard;		//CAN_ID_STDTxMessage.RTR = CAN_RTR_Data;TxMessage.DLC = Length;for (uint8_t i = 0; i < Length; i ++){TxMessage.Data[i] = Data[i];}uint8_t TransmitMailbox = CAN_Transmit(CAN1, &TxMessage);uint32_t Timeout = 0;while (CAN_TransmitStatus(CAN1, TransmitMailbox) != CAN_TxStatus_Ok){Timeout ++;if (Timeout > 100000){break;}}
}以下是注释,解释
/** * @brief  CAN Tx message structure definition  */typedef struct
{uint32_t StdId;  /*!< Specifies the standard identifier.This parameter can be a value between 0 to 0x7FF. */uint32_t ExtId;  /*!< Specifies the extended identifier.This parameter can be a value between 0 to 0x1FFFFFFF. */uint8_t IDE;     /*!< Specifies the type of identifier for the message that will be transmitted. This parameter can be a value of @ref CAN_identifier_type */uint8_t RTR;     /*!< Specifies the type of frame for the message that will be transmitted. This parameter can be a value of @ref CAN_remote_transmission_request */uint8_t DLC;     /*!< Specifies the length of the frame that will be transmitted. This parameter can be a value between 0 to 8 */uint8_t Data[8]; /*!< Contains the data to be transmitted. It ranges from 0 to 0xFF. */
} CanTxMsg;

3.2、CAN中断接收

在main.c文件的最后编写CAN接收中断处理函数:

3.2.1、代码1

/* USER CODE BEGIN 4 */
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{uint8_t  data[8];HAL_StatusTypeDef	status;if (hcan == &hcan1) {	status = HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxMessage, data);if (HAL_OK == status){                              			printf("--->Data Receieve!\r\n");printf("RxMessage.StdId is %#x\r\n",  RxMessage.StdId);printf("data[0] is 0x%02x\r\n", data[0]);printf("data[1] is 0x%02x\r\n", data[1]);printf("data[2] is 0x%02x\r\n", data[2]);printf("data[3] is 0x%02x\r\n", data[3]);printf("<---\r\n");}}
}
/* USER CODE END 4 */

上述代码所使用的一个关键函数

HAL_CAN_GetRxMessage函数用于从指定的 CAN 控制器接收邮箱中获取接收到的 CAN 消息。

HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);
  1. hcan:指向CAN_HandleTypeDef结构体类型的指针,该结构体包含了 CAN 控制器的相关配置和状态信息,通过它可以访问特定的 CAN 控制器实例。
  2. RxFifo:指定接收 FIFO(FIFO0 或 FIFO1)的编号。在 CAN 控制器中,通常有两个接收 FIFO,用于缓存接收到的消息。
  3. pHeader:指向CAN_RxHeaderTypeDef结构体类型的指针,这个结构体用于存储接收到的 CAN 消息的头部信息,包括:
    • StdIdExtId:标准帧标识符或扩展帧标识符,取决于接收到的消息类型。
    • IDE:标识符类型,区分标准帧和扩展帧。
    • RTR:远程传输请求标志,用于判断接收到的消息是否为远程请求。
    • DLC:数据长度代码,指示接收到的消息中数据的长度。
    • FilterMatchIndex:过滤器匹配索引,用于确定接收到的消息是通过哪个过滤器接收的。
  4. aData:指向用于存储接收到的数据的缓冲区的指针。数据以字节数组的形式存储在这个缓冲区中。

3.2.2、代码2

 标准库,中断接收

void USB_LP_CAN1_RX0_IRQHandler(void)
{if (CAN_GetITStatus(CAN1, CAN_IT_FMP0) == SET){CAN_Receive(CAN1, CAN_FIFO0, &MyCAN_RxMsg);MyCAN_RxFlag = 1;  //主函数中,通过判断状态标志,进一步处理数据}
}

3.2.3、代码3

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{CAN_RxHeaderTypeDef CAN_RX;uint8_t aData[8]; if(hcan->Instance ==CAN1){HAL_CAN_GetRxMessage(hcan,CAN_FilterFIFO0,&CAN_RX,aData);//从上位机获取数据HAL_UART_Transmit(&huart1,aData,CAN_RX.DLC,HAL_MAX_DELAY);//把获取的数据通过串口打印出来}}

3.3、过滤器

 关于过滤器的讲解视频,可以参考:视频的18.13进度,有个示例讲解。

[2-2] STM32 CAN外设(下)_哔哩哔哩_bilibili

一、IDE(Identifier Extension)

  • 当 IDE = 0 时,表示标准帧。标准帧的标识符长度为 11 位。
  • 当 IDE = 1 时,表示扩展帧。扩展帧的标识符长度为 29 位。

二、RTR(Remote Transmission Request)

  • 当 RTR = 0 时,表示数据帧。数据帧是由发送节点主动发送数据的帧类型。
  • 当 RTR = 1 时,表示远程帧。远程帧是用于请求远程节点发送相应的数据帧。发送远程帧的节点希望总线上某个具有特定标识符的节点能够响应并发送包含相应数据的数据帧。

 过滤器掩码中,0表示不对ID做任何反应,1表示必须与ID的位号相同。

3.3.1、代码1 

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* CAN过滤器配置函数 这个过滤器没有进行任何过滤   */
static void CANFilter_Config(void)
{CAN_FilterTypeDef  sFilterConfig;sFilterConfig.FilterBank = 0;                       //CAN过滤器编号,范围0-27sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;   //CAN过滤器模式,掩码模式或列表模式sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;  //CAN过滤器尺度,16位或32位sFilterConfig.FilterIdHigh = 0x000 << 5;			//32位下,存储要过滤ID的高16位sFilterConfig.FilterIdLow = 0x0000;					//32位下,存储要过滤ID的低16位sFilterConfig.FilterMaskIdHigh = 0x0000;			//掩码模式下,存储的是掩码sFilterConfig.FilterMaskIdLow = 0x0000;sFilterConfig.FilterFIFOAssignment = 0;				//报文通过过滤器的匹配后,存储到哪个FIFOsFilterConfig.FilterActivation = ENABLE;    		//激活过滤器sFilterConfig.SlaveStartFilterBank = 0;if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) {Error_Handler();}
}
/* USER CODE END 0 */

3.3.2、代码2

 标准库,过滤器初始化的代码

	CAN_FilterInitTypeDef CAN_FilterInitStructure;CAN_FilterInitStructure.CAN_FilterNumber = 0;CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;CAN_FilterInit(&CAN_FilterInitStructure);

参考:

STM32CubeMX STM32F103C8-CAN_stm32103 配置can速率500k-CSDN博客

STM32F103c8t6 hal库 CubeMX CAN 双机通信_stm32f103 hal can-CSDN博客

STM32CubeMX工程配置——以STM32F103C8T6为例_stm32f103c8t6 cubemx-CSDN博客

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

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

相关文章

「Mac畅玩鸿蒙与硬件33」UI互动应用篇10 - 数字猜谜游戏

本篇将带你实现一个简单的数字猜谜游戏。用户输入一个数字&#xff0c;应用会判断是否接近目标数字&#xff0c;并提供提示“高一点”或“低一点”&#xff0c;直到用户猜中目标数字。这个小游戏结合状态管理和用户交互&#xff0c;是一个入门级的互动应用示例。 关键词 UI互…

不同类型转换

如果赋值运算两侧是数值型或字符型&#xff0c;但类型不一致时&#xff0c;赋值时自动进行类型的转换。 赋值转换规则&#xff1a;使赋值号右边表达式值自动转换成其左边变量的类型 350为int型&#xff0c;占4个字节&#xff0c;char占一个字节 350二进制&#xff1a; 000000…

计算机毕业设计Python+LSTM天气预测系统 AI大模型问答 vue.js 可视化大屏 机器学习 深度学习 Hadoop Spark

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

操作系统 | 学习笔记 | 王道 | 2.4死锁

2.4 死锁 文章目录 2.4 死锁2.4.1 死锁的概念2.4.2 死锁预防2.4.3 死锁避免2.4.4 死锁检测和解除 2.4.1 死锁的概念 死锁的定义 在并发环境下&#xff0c;各进程因竞争资源而造成的一种互相等待对方手里的资源&#xff0c;导致各进程都阻塞&#xff0c;都无法向前推进的现象&am…

路径规划之启发式算法之二:遗传算法(Genetic Algorithm)

遗传算法&#xff08;Genetic Algorithm, GA&#xff09;是一种基于自然选择和遗传学原理的优化搜索算法&#xff0c;它通过模拟自然界的进化过程来寻找最优解。 一、基本原理 遗传算法的基本原理是模拟自然选择、遗传和突变等生物进化过程。它通过将问题的求解过程转换成类似…

软件质量保证——单元测试之白盒技术

笔记内容及图片整理自XJTUSE “软件质量保证” 课程ppt&#xff0c;仅供学习交流使用&#xff0c;谢谢。 程序图 程序图定义 程序图P&#xff08;V,E&#xff09;&#xff0c;V是节点的集合&#xff08;节点是程序中的语句或语句片段&#xff09;&#xff0c;E是有向边的集合…

分析 系统滴答时钟(tickClock),设置72MHz系统周期,如何实现1毫秒的系统时间?

一、CubeMX相关配置 1.1 相关引脚配置 1.2 相关时钟数配置 1.3 打开程序源码 二、相关函数分析

基于Java Springboot奶茶点餐微信小程序

一、作品包含 源码数据库万字文档全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA,微信开发者工具 数据…

centos8:Could not resolve host: mirrorlist.centos.org

【1】错误消息&#xff1a; [rootcentos211 redis-7.0.15]# yum update CentOS Stream 8 - AppStream …

宏海科技募资额有所缩减,最大销售和采购都重度依赖美的集团

《港湾商业观察》施子夫 11月29日&#xff0c;北交所上市审核委员会将召开2024年第24次上市委审议会议&#xff0c;届时将审议武汉宏海科技股份有限公司&#xff08;以下简称&#xff0c;宏海科技&#xff09;的首发上会事项。 在上会之前&#xff0c;宏海科技共收到北交所下…

SE16N 外键校验报错问题

问题&#xff1a; SE16N维护时&#xff0c;偶尔有一些莫名奇妙的校验报错&#xff0c;条目XX在表XX中不存在&#xff0c;但是实际数据时存在的。 分析&#xff1a; DEBUG过程中&#xff0c;定位到数据校验部分&#xff0c;发现当外键定义的关联字段中存在某些不在对应维护表中…

前端学习笔记之FileReader

概念 FileReader接口允许网页应用程序异步读取用户计算机上存储的文件&#xff08;或原始数据缓冲区&#xff09;的内容&#xff0c;使用File或Blob对象来制定要读取的文件或数据。 File对象可以通过用户使用<input>元素选择文件后返回的FileList对象获得&#xff0c;或…

第三方Express 路由和路由中间件

文章目录 1、Express 应用使用回调函数的参数&#xff1a; request 和 response 对象来处理请求和响应的数据。2、Express路由1.路由方法2.路由路径3.路由处理程序 3. 模块化路由4. Express中间件1.中间件简介2.中间件分类3.自定义中间件 1、Express 应用使用回调函数的参数&am…

给UE5优化一丢丢编辑器性能

背后的原理 先看FActorIterator的定义 /*** Actor iterator* Note that when Playing In Editor, this will find actors only in CurrentWorld*/ class FActorIterator : public TActorIteratorBase<FActorIterator> {//..... }找到基类TActorIteratorBase /*** Temp…

小程序跳转到本页面并传参

const pages getCurrentPages(); const currentPage pages[pages.length - 1]; // 当前页面路由 const route currentPage.route; // 当前页面参数 const options currentPage.options;// 构建新的 URL 参数 const newOptions {...options,// newParam: newValue }; // 你…

【机器学习】支持向量机SVR、SVC分析简明教程

关于使用SVM进行回归分析的介绍很少&#xff0c;在这里&#xff0c;我们讨论一下SVR的理论知识&#xff0c;并对该方法有一个简明的理解。 1. SVC简单介绍 SVR全称是support vector regression&#xff0c;是SVM&#xff08;支持向量机support vector machine&#xff09;对回…

pytest+allure生成报告显示loading和404

pytestallure执行测试脚本后&#xff0c;通常会在电脑的磁盘上建立一个临时文件夹&#xff0c;里面存放allure测试报告&#xff0c;但是这个测试报告index.html文件单独去打开&#xff0c;却显示loading和404, 这个时候就要用一些办法来解决这个报告显示的问题了。 用命令产生…

分布式事务调研

目录 需求背景&#xff1a; 本地事务 分布式基本理论 1、CAP 定理 2、BASE理论 分布式事务方案 #2PC #1. 运行过程 #1.1 准备阶段 #1.2 提交阶段 #2. 存在的问题 #2.1 同步阻塞 #2.2 单点问题 #2.3 数据不一致 #2.4 太过保守 3PC #本地消息表 TCC TCC原理 …

鱼眼相机模型-MEI

参考文献&#xff1a; Single View Point Omnidirectional Camera Calibration from Planar Grids 1. 相机模型如下&#xff1a; // 相机坐标系下的点投影到畸变图像// 输入&#xff1a;相机坐标系点坐标cam 输出&#xff1a; 畸变图像素点坐标disPtvoid FisheyeCamAdapter::…

[GKCTF 2021]签到

[GKCTF 2021]签到 wireshark跟踪http流&#xff0c;基本编解码&#xff0c;倒叙&#xff0c;栅栏密码 找到cat /f14g 把包里返回的字符串先hex解码&#xff0c;再base64解码&#xff0c;看到一个时间是倒叙&#xff0c;不含flag 继续往下面翻&#xff0c;可以看到cat%2Ff14g%7…