STM32Cube STM32MP157 M4端CAN通讯实战

news2024/11/27 10:25:32

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 Configuration
    PH13     ------> FDCAN1_TX
    PI9     ------> 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_ID
	sFilterConfig.FilterIndex = 0;
	sFilterConfig.FilterType = FDCAN_FILTER_DUAL;//双过滤。FDCAN_FILTER_RANGE
	sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;//过滤存储在rx fifo0
	sFilterConfig.FilterID1 = 0;//范围id
	sFilterConfig.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;//帧ID
	TxHeader.IdType 		= FDCAN_STANDARD_ID;//标准ID
	TxHeader.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 can
	TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;//发送时间FIFO控制,不存储
	TxHeader.MessageMarker = 0; //识别消息状态,范围0到0xFF
	if (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

在这里插入图片描述

总结

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

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

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

相关文章

从LeNet到ResNet:深入探索卷积神经网络

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️&#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

论文解读15——LightGBM: A Highly Efficient Gradient Boosting Decision Tree

目录1、文章贡献2、直方图算法Histogram&#xff08;减少分裂点&#xff09;3、基于梯度的单边采样算法GOSS&#xff08;减少样本量&#xff09;4、互斥特征捆绑算法EFB&#xff08;减少特征&#xff09;在上篇中提到&#xff0c;XGBoost算法的局限是它在寻找最优分裂点算法中需…

AidLux AI应用案例悬赏选题 | 电路板表面瑕疵检测

AidLux AI 应用案例悬赏征集活动 AidLux AI 应用案例悬赏征集活动是AidLux推出的AI应用案例项目合作模式&#xff0c;悬赏选题将会持续更新。目前上新的选题涉及泛边缘、机器人、工业检测、车载等领域&#xff0c;内容涵盖智慧零售、智慧社区、智慧交通、智慧农业、智能家居等…

正点原子裸机开发之C语言点灯程序

一. 简介 本文针对 IMX6ULL 的裸机开发的&#xff08;即不带Linux操作系统的开发&#xff09;。 主要分两部分的工作&#xff1a; 1. 配置 C语言运行环境 2. C 语言编写及运行 二. 配置C语言运行环境 配置 C 语言运行环境的工作分 三部分。如下&#xff1a; 1. 设置…

Nginx配置实例-反向代理案例一

实现效果&#xff1a;使用nginx反向代理&#xff0c;访问 www.suke.com 直接跳转到本机地址127.0.0.1:8080 一、准备工作 Centos7 安装 Nginxhttps://liush.blog.csdn.net/article/details/125027693 1. 启动一个 tomcat Centos7安装JDK1.8https://liush.blog.csdn.net/arti…

YonBuilder 应用构建全新入门指南

用友开发者中心以 YonBuilder 低代码开发为核心&#xff0c;提供可视化 低代码 全代码的一站式开发能力&#xff0c;企业组织和个人开发者可实现业务应用的快速开发。YonBuilder 基于用友 BIP 强大的中台支撑能力&#xff0c;在元数据驱动和运行框架的统一模型架构下&#xf…

Ethercat学习-GD32以太网学习

文章目录1、GD32F4以太网简介2、以太网模框图简介3、以太网主要模块介绍SMI接口RMII接口与MII接口DMA控制器4、以太网配置流程5、其他1、GD32F4以太网简介 GD32F4系列以太网模块包含10/100Mbps以太网MAC&#xff0c;数据的收发都通过DMA进行操作&#xff0c;支持MII&#xff0…

一个C#开发的开源的快速启动工具

更多开源项目请查看&#xff1a;一个专注推荐.Net开源项目的榜单 平常计算机安装软件比较多、或者工作涉及的文件比较多&#xff0c;很多人都会直接放在桌面&#xff0c;一方面不安全&#xff0c;还不容易查找&#xff0c;这时候我们往往&#xff0c;都会放在其他硬盘内&#x…

springboot项目yml文件中${}的使用

作用 项目启动时可以灵活的通过修改环境变量来替换配置中的值&#xff0c;如果没有传该环境变量时&#xff0c;就是用默认值&#xff1b; 格式&#xff1a;${自定义参数名:默认值} 代码举例&#xff0c;已开启应用的端口号为例&#xff1a; server:port: ${SERVER_PORT:960…

AI+人类,实现高效网络安全

导语 聊天机器人和生成式人工智能&#xff08;如 ChatGPT&#xff09;突然成为主流让很多人感到担忧。很多人开始担忧&#xff0c;人工智能取代人的时代已经到来。 幸运的是&#xff0c;事实并非如此。 更有可能的情况是&#xff0c;人类将与 AI 合作创建工作角色的混合模型。…

Mercedes-Benz EDI需求分析

作为奔驰的仓储服务提供商&#xff0c;企业A需要借助EDI实现仓储流程的自动化。奔驰将车存放在企业A处&#xff0c;由企业A将货物提供给4S店。整体业务流程中将通过EDI系统来进行业务数据的传输&#xff0c;今天的文章主要从奔驰EDI需求概览以及EDI项目业务流程两方面展开介绍。…

646. 最长数对链——【Leetcode每日刷题】

646. 最长数对链 给你一个由 n 个数对组成的数对数组 pairs &#xff0c;其中 pairs[i][lefti,righti]pairs[i] [left_i, right_i]pairs[i][lefti​,righti​] 且lefti<rightileft_i < right_ilefti​<righti​。 现在&#xff0c;我们定义一种 跟随 关系&#xff…

MySQL查询索引原则

文章目录 等值匹配原则最左前缀匹配原则范围查找规则等值匹配+范围查找Order By + limit 优化分组查询优化总结MySQL 是如何帮我们维护非主键索引的等值匹配原则 我们现在已经知道了如果是【主键索引】,在插入数据的时候是根据主键的顺序依次往后排列的,一个数据页不够就会分…

保姆级使用PyTorch训练与评估自己的MobileViT网络教程

文章目录前言0. 环境搭建&快速开始1. 数据集制作1.1 标签文件制作1.2 数据集划分1.3 数据集信息文件制作2. 修改参数文件3. 训练4. 评估5. 其他教程前言 项目地址&#xff1a;https://github.com/Fafa-DL/Awesome-Backbones 操作教程&#xff1a;https://www.bilibili.co…

2023最新ELK日志平台(elasticsearch+logstash+kibana)搭建

去年公司由于不断发展&#xff0c;内部自研系统越来越多&#xff0c;所以后来搭建了一个日志收集平台&#xff0c;并将日志收集功能以二方包形式引入自研系统&#xff0c;避免每个自研系统都要建立一套自己的日志模块&#xff0c;节约了开发时间&#xff0c;管理起来也更加容易…

【UE4 RTS游戏】07-控件蓝图显示当前游戏时间

效果步骤新建一个文件夹&#xff0c;命名为“Interfaces”&#xff0c;在该文件夹内新建一个蓝图接口&#xff0c;命名为“I_HUD”打开“Interfaces”&#xff0c;默认的函数名改为“SetClock”&#xff0c;添加一个输入&#xff0c;命名为“Time”&#xff0c;整数数组类型。添…

一套Java语言的云HIS医院信息管理系统SaaS源码

这是一套优秀的云His医院管理系统&#xff0c;它区别于普通的HIS系统&#xff0c;它通过云端管理整个HIS业务 一、HIS使用技术框架&#xff1a;自主研发&#xff0c;系统完全开源。 1、前端&#xff1a;AngularNginx 2、后台&#xff1a;JavaSpring&#xff0c;SpringBoot&…

AidLux AI 应用案例悬赏选题|行车安全辅助

AidLux AI 应用案例悬赏征集活动 AidLux AI 应用案例悬赏征集活动是AidLux推出的AI应用案例项目合作模式&#xff0c;悬赏选题将会持续更新。目前上新的选题涉及泛边缘、机器人、工业检测、车载等领域&#xff0c;内容涵盖智慧零售、智慧社区、智慧交通、智慧农业、智能家居等…

YOLOv5中添加SE模块详解——原理+代码

目录一、SENet1. 设计原理2. SE Block2.1 Squeeze:Global Information Embedding2.2 Excitation:Adaptive Recalibration3. SE-Inception and SE-ResNet二、YOLOv5中添加SENet1.修改common.py2.修改yolo.py3.修改yolov5s.yaml参考文章一、SENet 论文地址&#xff1a;Squeeze-a…

UI设计 ,这7个网站,真的太好用了。

下面这几个UI设计网站&#xff0c;设计师们一定要收藏起来&#xff0c;每天坚持浏览这些网站&#xff0c;可以快速的提升你的UI设计水平。 1、菜鸟图库 https://www.sucai999.com/searchlist/UIsheji----all-0-0.html?vNTYxMjky 菜鸟图库提供了超多免费设计素材&#xff0c;在…