当前位置: 首页 > news >正文

STM32Cube STM32MP157 M4端CAN通讯实战

1、环境

开发系列:STM32MP157
开发软件:STM32CubeIDE 1.4.0
例程目的:在M4端实现CAN通讯

2、目的

近日,有客户需要在STM32MP157中的M4端实现CAN通讯,我也是初次在M4端编写CAN通讯代码,上网研究了其他人写的STM32系列单片机案例才把这个例程Demo写好。

3、程序配置

1、CAN引脚选用:
FDCAN1_RX ---->PI9
FDCAN1_TX ----->PH13

在这里插入图片描述
2、配置FDCAN1的相关参数
Mode模式选择Classic
如果刚刚第一步配置好的话,GPIO Setting上会出现两个引脚列表。

在这里插入图片描述
如果需要配置CAN中断接收的话把这个钩上√
在这里插入图片描述
这里非常关键一步就是Parameter Setting
重点!!!!!!!:Norminal xxxx这四个参数的设置直接决定了CAN波特率是多少!!!
CAN波特率的计算方式 :CAN波特率 = 系统时钟/Norminal prescaler/ (Nominal Sync Jump Width+Nominal Time Seg1+Nominal Time Seg1)
数据段也跟仲裁段一样的配置就好了。

Tx Fifo Queue Elmts Nbr为10,该参数设置用于Tx FIFO/Queue的Tx Buffers个数。范围0-32
在这里插入图片描述
上一步说到波特率的计算,其中系统时钟是在clock configuration配置,这里值得注意的是我使用的是HSE(外部高速时钟)为24MHZ。
所以波特率为24MHZ/8/(1+3+2) = 500KHZ

在这里插入图片描述
我这配置FDCAN模块的时候遇到了HSE被disable了,也就是说无法使用,这样我们需要使用一下设置,如下图,把disable改成Crustal/Ceramic Resonator
在这里插入图片描述
完成以上步骤后,可以保存一下.ioc文件,会自动生成初始化代码

4、代码编写

fdcan初始化代码,这些都不需要我们自行编写,只需在ioc文件上选择上保存即可。

fdcan.c
/* FDCAN1 init function */
void MX_FDCAN1_Init(void)
{hfdcan1.Instance = FDCAN1;hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;hfdcan1.Init.AutoRetransmission = DISABLE;hfdcan1.Init.TransmitPause = DISABLE;hfdcan1.Init.ProtocolException = DISABLE;hfdcan1.Init.NominalPrescaler = 8;hfdcan1.Init.NominalSyncJumpWidth = 1;hfdcan1.Init.NominalTimeSeg1 = 3;hfdcan1.Init.NominalTimeSeg2 = 2;hfdcan1.Init.DataPrescaler = 8;hfdcan1.Init.DataSyncJumpWidth = 1;hfdcan1.Init.DataTimeSeg1 = 3;hfdcan1.Init.DataTimeSeg2 = 2;hfdcan1.Init.MessageRAMOffset = 0;hfdcan1.Init.StdFiltersNbr = 0;hfdcan1.Init.ExtFiltersNbr = 0;hfdcan1.Init.RxFifo0ElmtsNbr = 10;hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;hfdcan1.Init.RxFifo1ElmtsNbr = 10;hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;hfdcan1.Init.RxBuffersNbr = 10;hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;hfdcan1.Init.TxEventsNbr = 10;hfdcan1.Init.TxBuffersNbr = 10;hfdcan1.Init.TxFifoQueueElmtsNbr = 10;hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK){Error_Handler();}}void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* fdcanHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};if(fdcanHandle->Instance==FDCAN1){/* USER CODE BEGIN FDCAN1_MspInit 0 *//* USER CODE END FDCAN1_MspInit 0 */if(IS_ENGINEERING_BOOT_MODE()){/** Initializes the peripherals clock*/PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_HSE;if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK){Error_Handler();}}/* FDCAN1 clock enable */__HAL_RCC_FDCAN_CLK_ENABLE();__HAL_RCC_GPIOH_CLK_ENABLE();__HAL_RCC_GPIOI_CLK_ENABLE();/**FDCAN1 GPIO ConfigurationPH13     ------> FDCAN1_TXPI9     ------> FDCAN1_RX*/GPIO_InitStruct.Pin = GPIO_PIN_13;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1;HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_9;GPIO_InitStruct.Mode = GPIO_MODE_AF;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1;HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);/* FDCAN1 interrupt Init */HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 0, 0);HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);/* USER CODE BEGIN FDCAN1_MspInit 1 *//* USER CODE END FDCAN1_MspInit 1 */}
}

接下来就是要我们手动编写的函数接口
can接受过滤器配置
更多的配置可以查看一下该stm32mp1xx_hal_fdcan.h文件

void CANconfigure()
{FDCAN_FilterTypeDef sFilterConfig;sFilterConfig.IdType = FDCAN_STANDARD_ID;//标准帧 FDCAN_EXTENDED_IDsFilterConfig.FilterIndex = 0;sFilterConfig.FilterType = FDCAN_FILTER_DUAL;//双过滤。FDCAN_FILTER_RANGEsFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;//过滤存储在rx fifo0sFilterConfig.FilterID1 = 0;//范围idsFilterConfig.FilterID2 = 0;//范围id//表示只能接收FilterID1 << id << FilterID2 //如果设置为0的话,表示不做任何的过滤if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)//滤波器初始化{Error_Handler();}sFilterConfig.IdType = FDCAN_STANDARD_ID;sFilterConfig.FilterIndex = 0;sFilterConfig.FilterType = FDCAN_FILTER_DUAL;sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;sFilterConfig.FilterID1 = 0;sFilterConfig.FilterID2 = 0;if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)//滤波器初始化{Error_Handler(); }if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)//开启FDCAN {Error_Handler();}if(HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, FDCAN_IT_TX_COMPLETE) != HAL_OK){Error_Handler();}
}

can发送函数:

FDCAN_HandleTypeDef hfdcan1;//全局变量
FDCAN_TxHeaderTypeDef TxHeader;//全局变量CAN_Transmit(uint16_t ID, uint8_t *pdata, uint8_t length)
{TxHeader.Identifier 	= ID;//帧IDTxHeader.IdType 		= FDCAN_STANDARD_ID;//标准IDTxHeader.TxFrameType 	= FDCAN_DATA_FRAME;//数据帧TxHeader.DataLength 	= FDCAN_DLC_BYTES_8;//数据长度TxHeader.ErrorStateIndicator 	= FDCAN_ESI_PASSIVE;//错误指示TxHeader.BitRateSwitch 			= FDCAN_BRS_OFF;//关闭可变波特率TxHeader.FDFormat 			= FDCAN_CLASSIC_CAN;//传统classsic canTxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;//发送时间FIFO控制,不存储TxHeader.MessageMarker = 0; //识别消息状态,范围0到0xFFif (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, pdata) != HAL_OK){Error_Handler();}
}

接收中断回调函数

void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{printf("fdcan recvice.....\r\n");/* Get RX message */if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader, (uint8_t*)&can_rx_data.RX_Data[0]) != HAL_OK){Error_Handler();}can_rx_data.ID = RxHeader.Identifier;can_rx_data.length = RxHeader.DataLength>>16;for  (int i=0;i<can_rx_data.length;i++){printf("fdcan recvice%d:%d.....\r\n",i,can_rx_data.RX_Data[i]);}
}

编写好这几个函数接口之后,编译看是否有错误再稍微作修改。

5、问题及方法

1、判断你的函数接口和配置是否正确,我发现可以是用外部回环模式进行测试,这样可以摆脱外部因素导致了通讯失败。
将FDCAN_FRAME_CLASSIC改成FDCAN_MODE_EXTERNAL_LOOPBACK

void MX_FDCAN1_Init(void)
{hfdcan1.Instance = FDCAN1;hfdcan1.Init.FrameFormat = FDCAN_MODE_EXTERNAL_LOOPBACK;hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;//省略部分代码}

2、这个是最最最最奇葩的,搞了我几天时间,就是如果在M4上使用CAN接口有可能需要修改tf-a文件和dtb设备树。
从源码上找到属于自己板子的fdts/stm32mp157xxxx.dtsi文件,修改如下:

在这里插入图片描述
因为我使用的是HSE时钟,而原来的是PLL4R时钟,导致时钟不工作,CAN功能异常。
内核设备树DTB修改:
把m_can1屏蔽disabled,分配给m4_m_can1

在这里插入图片描述

总结

希望大家遇到像我这类似的问题,能少走点弯路。好好总结。

相关文章:

STM32Cube STM32MP157 M4端CAN通讯实战

1、环境 开发系列&#xff1a;STM32MP157 开发软件&#xff1a;STM32CubeIDE 1.4.0 例程目的&#xff1a;在M4端实现CAN通讯 2、目的 近日&#xff0c;有客户需要在STM32MP157中的M4端实现CAN通讯&#xff0c;我也是初次在M4端编写CAN通讯代码&#xff0c;上网研究了其他人写…...

npm install报错unable to resolve dependency tree

一、问题背景npm install安装项目依赖时报错PS D:\test> npm install npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: vue-admin-template4.2.1 npm ERR! Found: webpack5.74.0 npm ERR! node_modules/we…...

力扣sql简单篇练习(二十六)

力扣sql简单篇练习(二十六) 1 每家商店的产品价格 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 # 多行变成多列,考虑用sum if分组 SELECT product_id,sum(IF(storestore1,price,null)) store1,sum(IF(storestore2,price,null)) store2, sum(IF(st…...

2022年全国职业院校技能大赛(中职组)网络安全竞赛试题A模块第九套解析(详细)

2022年全国职业院校技能大赛(中职组) 网络安全竞赛试题 (9) (总分100分) 赛题说明 一、竞赛项目简介 “网络安全”竞赛共分A.基础设施设置与安全加固;B.网络安全事件响应、数字取证调查和应用安全;C.CTF夺旗-攻击;D.CTF夺旗-防御等四个模块。根据比赛实际情况,竞…...

C++回顾(十六)—— 异常处理机制

16.1 异常的基本语法 1&#xff09; 若有异常则通过throw操作创建一个异常对象并抛掷。2&#xff09; 将可能抛出异常的程序段嵌在try块之中。控制通过正常的顺序执行到达try语句&#xff0c;然后执行try块内的保护段。3&#xff09; 如果在保护段执行期间没有引起异常&#xf…...

【100个 Unity实用技能】 | Unity 在代码中 动态改变RectTransform位置及宽高 的方法整理

Unity 小科普 老规矩&#xff0c;先介绍一下 Unity 的科普小知识&#xff1a; Unity是 实时3D互动内容创作和运营平台 。包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者&#xff0c;借助 Unity 将创意变成现实。Unity 平台提供一整套完善的软件解决方案&#xff…...

哈希表的实现

哈希表概念 二叉搜索树具有对数时间的表现&#xff0c;但这样的表现建立在一个假设上&#xff1a;输入的数据有足够的随机性。哈希表又名散列表&#xff0c;在插入、删除、搜索等操作上具有「常数平均时间」的表现&#xff0c;而且这种表现是以统计为基础&#xff0c;不需依赖…...

搞懂海明码

海明码搞懂之前先了解奇偶校验。例如&#xff1a;1111 对其进行奇偶校验。 奇检验&#xff1a;11111 奇校验使1的个数保持在奇数 偶校验&#xff1a;01111 偶校验使1的个数保持在偶数 海明码可以拆分为三步&#xff1a; 一、确定校验的位数 公式&#xff1a;2^k > k n …...

数据库:Mysql数据库安装及使用

目录 一、数据库介绍 1、基本概念 2、数据库类型 3、版本演变 二、Mysql安装 1、官网下载yum安装 2、手动配置yum安装 三、Mysql基本操作 1、登录与改密 2、检测数据库健康 3、 库的创建与使用 4、数据类型 5、修饰符 6、表的创建与使用 7、分组查询 8、查询排…...

【冲刺蓝桥杯的最后30天】day7

大家好&#x1f603;&#xff0c;我是想要慢慢变得优秀的向阳&#x1f31e;同学&#x1f468;‍&#x1f4bb;&#xff0c;断更了整整一年&#xff0c;又开始恢复CSDN更新&#xff0c;从今天开始更新备战蓝桥30天系列&#xff0c;一共30天&#xff0c;如果对你有帮助或者正在备…...

REG.EXE修改注册表-解决win10微软输入法默认中文,将其全局修改为英文

REG.EXE修改注册表-解决win10微软输入法默认中文&#xff0c;将其全局修改为英文 使用REG.EXE 可以直接强制修改注册表字段 修改注册表&#xff1a; REG.EXE ADD 注册表路径 /v 注册表项字段 /t 注册表字段类型 /d 注册表值 /f 例如&#xff1a; REG. EX ADD HKLM\System\C…...

hive之正则函数研究学习regex/regex_replace/regex_extract

首先学习这个之前要先知道一些正则的基本知识。 随便百度一下正则表达式 – 元字符 | 菜鸟教程 字符描述\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如&#xff0c;n 匹配字符 "n"。\n 匹配一个换行符。序列 \\ 匹…...

Codeforces Round 854 by cybercats (Div. 1 + Div. 2) C、D1

C. Double Lexicographically Minimum 题意 字符串sss&#xff0c;你可以把它按任意顺序组合&#xff0c;保留的是你组合的字符串和它的倒序之间大的那一个&#xff0c;问你在满足上面条件的前提下字典序最小的字符串。 思路 分析不难发现在没达到一个关键的点的时候肯定是…...

API 网关日志的价值,你了解多少?

本文介绍了 API 网关日志的价值&#xff0c;并以知名网关 Apache APISIX 为例&#xff0c;展示如何集成 API 网关日志。 作者钱勇&#xff0c;API7.ai 技术工程师&#xff0c;Apache APISIX Committer。 原文链接 网关日志的价值 在数字化时代&#xff0c;软件架构随着业务成…...

华大单片机、STM32单片机如何做printf串口打印格式化输出

第一种方法&#xff1a;使用标准C库&#xff0c;但使用标准C库你必须关闭半主机模式&#xff08;1&#xff09;添加下面代码就是关闭半主机模式/* 告知连接器不从C库链接使用半主机的函数 */ #pragma import(__use_no_semihosting)/* 定义 _sys_exit() 以避免使用半主机模式 */…...

unity 面试汇总

1、什么是协同程序&#xff1f;答&#xff1a;在主线程运行时同时开启另一段逻辑处理&#xff0c;来协助当前程序的执行。换句话说&#xff0c;开启协程就是开启一个可以与程序并行的逻辑。可以用来控制运动、序列以及对象的行为。2、Unity3D中的碰撞器和触发器的区别&#xff…...

Spring SpringBoot中使用Mybatis-plusDemo1

官网:https://baomidou.com GitHub:GitHub - baomidou/mybatis-plus: An powerful enhanced toolkit of MyBatis for simplify development Gitee:mybatis-plus: mybatis 增强工具包&#xff0c;简化 CRUD 操作。 文档 http://baomidou.com低代码组件库 http://aizuda.com My…...

【18.04Ubuntu中解决无法识别显示屏】

【18.04Ubuntu中解决无法识别外接显示屏】1. 问题来源2. 检查Ubuntu是否识别出外接显示器3. 解决没有识别出外接显示器问题4. 显示器扩展屏幕设置1. 问题来源 实验室的一个dell显示器&#xff0c;通过HDMI连接电脑后&#xff0c;在Windows上连接上就直接可以使用了。由于我电脑…...

Python 协程详解,都在这里了

什么是协程 协程&#xff08;co-routine&#xff0c;又称微线程、纤程&#xff09; 是一种多方协同的工作方式。 协程不是进程或线程&#xff0c; 其执行过程类似于 Python 函数调用&#xff0c; Python 的 asyncio 模块实现的异步IO编程框架中&#xff0c; 协程是对使用 asy…...

百家号如何写文章赚钱,百家号写文章真的赚钱?

随着互联网的快速发展&#xff0c;越来越多的人开始关注到写文章赚钱这个领域。而在众多写作平台中&#xff0c;头条号无疑是最受欢迎的一个。那么&#xff0c;百家号写文章赚钱是真的吗&#xff1f;如何写文章赚钱呢&#xff1f;下面我们就来一一解答。 首先&#xff0c;百家号…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...