《STM32 HAL库》CAN通信系列函数详尽解析——HAL_CAN_Init()

news2024/11/26 12:37:03

食用指南:本文主要内容为梳理CAN初始化函数主要运行逻辑及重点功能实现代码的详尽解析。函数源码在文末,建议在阅读源码之后观看。
CAN相关寄存器图:

主要逻辑分析:

下面分点梳理函数的主要逻辑(注意逻辑序号,后文依次为点进行分析):

  1. 首先,函数会检查传入的参数hcan是否为NULL,如果是NULL,则返回错误代码HAL_ERROR

  2. 接下来,函数会使用assert_param宏对传入的hcan结构体的各个参数进行检查,确保它们的取值范围符合要求。

  3. 如果宏USE_HAL_CAN_REGISTER_CALLBACKS的值为1并且hcan的状态为HAL_CAN_STATE_RESET,则表示使用了回调函数,并且需要将回调函数重置为默认的“legacy”函数。如果hcan->MspInitCallback为空,则将其设置为默认的初始化函数HAL_CAN_MspInit。然后调用hcanMspInitCallback函数,用于初始化底层硬件。

  4. 如果USE_HAL_CAN_REGISTER_CALLBACKS的值不为1或者hcan的状态不为HAL_CAN_STATE_RESET,则直接调用HAL_CAN_MspInit函数初始化底层硬件。

  5. 在初始化之前,首先需要将CAN控制器从睡眠模式唤醒。通过清除CAN_MCR_SLEEP位实现。

  1. 接着,获取当前的系统滴答计数器值tickstart,用于超时判断。

  2. 检查CAN控制器是否成功离开了睡眠模式。通过检查CAN_MSR_SLAK位,如果该位为0,则表示成功离开了睡眠模式。如果超时时间超过了预设的超时值CAN_TIMEOUT_VALUE,则更新错误代码并返回错误。

  3. 发送初始化请求,通过设置CAN_MCR_INRQ位实现。

  4. 获取当前的系统滴答计数器值tickstart,用于超时判断。

  5. 等待CAN控制器接受初始化请求。通过检查CAN_MSR_INAK位,如果该位为1,则表示CAN控制器已经接受了初始化请求。如果超时时间超过了预设的超时值CAN_TIMEOUT_VALUE,则更新错误代码并返回错误。

  6. 根据初始化参数设置CAN控制器的各种工作模式和配置,包括时间触发通信模式、自动总线断开管理、自动唤醒模式、自动重传、接收FIFO锁定模式和传输FIFO优先级等。

  1. 设置位时序寄存器BTR,将各个参数值写入寄存器中。

  2. 初始化错误代码和CAN状态。

  3. 返回函数执行状态HAL_OK

重点部分分析

逻辑 3

#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
  if (hcan->State == HAL_CAN_STATE_RESET)
  {
    /* Reset callbacks to legacy functions */
    hcan->RxFifo0MsgPendingCallback  =  HAL_CAN_RxFifo0MsgPendingCallback;  /* Legacy weak RxFifo0MsgPendingCallback */
    hcan->RxFifo0FullCallback        =  HAL_CAN_RxFifo0FullCallback;        /* Legacy weak RxFifo0FullCallback */
    hcan->RxFifo1MsgPendingCallback  =  HAL_CAN_RxFifo1MsgPendingCallback;  /* Legacy weak RxFifo1MsgPendingCallback */
    hcan->RxFifo1FullCallback        =  HAL_CAN_RxFifo1FullCallback;        /* Legacy weak RxFifo1FullCallback */
    hcan->TxMailbox0CompleteCallback =  HAL_CAN_TxMailbox0CompleteCallback; /* Legacy weak TxMailbox0CompleteCallback */
    hcan->TxMailbox1CompleteCallback =  HAL_CAN_TxMailbox1CompleteCallback; /* Legacy weak TxMailbox1CompleteCallback */
    hcan->TxMailbox2CompleteCallback =  HAL_CAN_TxMailbox2CompleteCallback; /* Legacy weak TxMailbox2CompleteCallback */
    hcan->TxMailbox0AbortCallback    =  HAL_CAN_TxMailbox0AbortCallback;    /* Legacy weak TxMailbox0AbortCallback */
    hcan->TxMailbox1AbortCallback    =  HAL_CAN_TxMailbox1AbortCallback;    /* Legacy weak TxMailbox1AbortCallback */
    hcan->TxMailbox2AbortCallback    =  HAL_CAN_TxMailbox2AbortCallback;    /* Legacy weak TxMailbox2AbortCallback */
    hcan->SleepCallback              =  HAL_CAN_SleepCallback;              /* Legacy weak SleepCallback */
    hcan->WakeUpFromRxMsgCallback    =  HAL_CAN_WakeUpFromRxMsgCallback;    /* Legacy weak WakeUpFromRxMsgCallback */
    hcan->ErrorCallback              =  HAL_CAN_ErrorCallback;              /* Legacy weak ErrorCallback */

    if (hcan->MspInitCallback == NULL)
    {
      hcan->MspInitCallback = HAL_CAN_MspInit; /* Legacy weak MspInit */
    }

    /* Init the low level hardware: CLOCK, NVIC */
    hcan->MspInitCallback(hcan);
  }

让我们一句一句地详细分析这段代码:

#if USE_HAL_CAN_REGISTER_CALLBACKS == 1

这是一个条件编译的预处理指令,它检查宏定义USE_HAL_CAN_REGISTER_CALLBACKS是否等于1。如果等于1,则表示要使用回调函数注册功能。

if (hcan->State == HAL_CAN_STATE_RESET)
{

这是一个条件语句,它检查CAN的状态hcan->State是否等于HAL_CAN_STATE_RESET。只有当CAN处于复位状态时,才会执行接下来的代码块。

/* Reset callbacks to legacy functions */
hcan->RxFifo0MsgPendingCallback  =  HAL_CAN_RxFifo0MsgPendingCallback;  /* Legacy weak RxFifo0MsgPendingCallback */
……

这一系列的语句将CAN处理器结构体hcan中的回调函数成员设置为默认的回调函数。这些默认的回调函数被称为”Legacy weak”,表示它们是在历史版本中使用的弱定义回调函数。以第一句为例,作用是将HAL_CAN_RxFifo0MsgPendingCallback的回调函数的地址赋值给hcan->RxFifo0MsgPendingCallback,即将CAN模块的RxFIFO0消息待处理回调函数指针指向一个特定的函数。在CAN模块中,当RxFIFO0内有消息待处理时,可以通过注册一个回调函数来通知应用程序进行相应的处理。

点击《STM32 HAL库》CAN通信系列函数详尽解析——HAL_CAN_Init()——古月居可查看全文

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

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

相关文章

为何云原生是未来?企业IT架构的颠覆与重构

🐇明明跟你说过:个人主页 🏅个人专栏:《未来已来:云原生之旅》🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、什么是云原生 2、云原生的背景和起源 背景 起源 关…

打字侠,中小学生暑期的打字练习神器

亲爱的家长们,暑假来临,孩子们又要开始“沙发上的咸鱼”模式了!与其看着他们抱着手机、平板不放,不如让他们成为“打字侠”,在快乐中提升打字技能! “打字侠”是一款为中小学生量身打造的打字练习神器。别…

WPF 程序 分布式 自动更新 登录 打包

服务器server端 core api 客户端WPF // 检查应用更新 //1、获取最新文件列表 // var files fileService.GetUpgradeFiles(); // 2、文件判断,新增的直接下载;更新的直接下载;删除的直接删除 // 客户端本地需要一个记录…

宇宙星空星辰美景素材哪里找?高清无水印分享

宇宙星空的美丽总能激发人们的无限遐想和灵感,不仅在科学教育领域,更在电影制作和视觉艺术中占有一席之地。为了帮助您找到高质量的宇宙星空视频素材,以下平台将成为您获取令人难忘天体视频素材的首选。 蛙学府 蛙学府作为新媒体创作者的宝库…

如何将图片转换为表格?方法并不难!

如何将图片转换为表格?在数字化时代,图片中的表格信息提取和整理成为了我们日常工作中不可或缺的一部分。不论是学术研究、商业分析还是个人生活,快速、准确地将图片转换为表格都显得尤为重要。今天,我们就来介绍四款强大的图片转…

经验总结--开关MOS管发热的一般原因/电源开发经验总结

开关MOS管发热的一般原因 做电源设计,或者做驱动方面的电路,难免要用到场效应管,也就是人们常说的MOS管。MOS管有很多种类,也有很多作用。做电源或者驱动的使用,当然就是用它的开关作用。 无论N型或者P型MOS管,其工作原理本质是一样的。MOS管是由加在输入端栅极的电压来控…

Android蓝牙开发(二)之蓝牙配对和蓝牙连接

BluetoothDevice.class.getMethod 进行配对,代码如下: Method method BluetoothDevice.class.getMethod(“createBond”); Log.e(getPackageName(), “开始配对”); method.invoke(listdevice.get(position)); invoke传的参数就是要配对的设备&…

ffmpeg音视频开发从入门到精通——ffmpeg日志及目录操作

文章目录 FFMPEG1. 操作日志2. 文件移动和删除3. 操作目录重要函数 FFMPEG 1. 操作日志 日志级别 AV LOG ERROR AV LOG WARNING AV LOG INFO AV LOG DEBUG cmake_minimum_required(VERSION 3.27) project(FFmpeg_exercise) set(CMAKE_CXX_STANDARD 14)# 定义FFmpeg的安装路…

Android自定义View之不得不知道的文件attrs

其中demo_style如下:一般都是放的.9图片,为了方便就放个颜色了 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190820183209784.png?x-oss-processimage/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLm NzZG4ubmV0L3FxXzQyNzYxMz…

海外云手机自动化管理,高效省力解决方案

不论是企业还是个人,对于海外社媒的营销都是需要自动化管理的,因为自动化管理不仅省时省力,而且还节约成本; 海外云手机的自动化管理意味着什么?那就是企业无需再投入大量的人力和时间去逐一操作和监控每一台设备。 通…

鞋子分类数据集17399张69类别

数据集类型:图像分类用,不可用于目标检测无标注文件 数据集格式:仅仅包含jpg图片,每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数):17399 分类类别数:69 类别名称:[“0”,“1”,“2”,“3”,“4”…

全国实体商铺店铺商家采集工具,一键采集商家手机号,让你轻松找到目标客户

随着互联网的发展,越来越多的商家开始在网上开展业务,实体商铺的竞争也日益激烈。为了更好地吸引客户,很多商家都选择了线上推广和营销。然而,仅仅依靠线上推广是远远不够的,线下的实体商铺也需要积极拓展客源。因此&a…

DBeaver 数据结果集设置不显示逗号(太丑了)

从Navicat切换过来使用DBeaver,发现类似bigint 这种数据类型在结果集窗口中显示总是给我加上一个逗号,看着很不习惯,也比较占空间,个人觉得这种可读性也不好。 于是我在网上尝试搜索设置方法,可能我的关键词没命中&…

数据更新-插入元组(VALUES)、修改属性(SET)、删除元组(DELETE)

一、插入元组 1、插入单个元组&#xff08;使用的是VALUES子句&#xff09; &#xff08;1&#xff09;语句格式 INSERT INTO <表名> 【&#xff08;<属性名1【&#xff0c;<属性名2>&#xff0c;...】&#xff09;】 VALUES &#xff08;<常量1>【&a…

CATO原理中的数学与魔术(十四)——流程设计思路与升华

早点关注我&#xff0c;精彩不错过&#xff01; 系列终于进入尾声&#xff01;前面13篇文章已经穷尽搜刮掉我目力所及的全部CATO魔术的相关内容&#xff0c;并重新建立理论&#xff0c;分门别类进行了介绍。详情请戳&#xff1a; CATO原理中的数学与魔术&#xff08;十三&#…

aardio - 日历

写了个日历小例程&#xff0c;因 lunar 农历库存在问题&#xff0c;经过研究算是变相解决了&#xff0c;日历也完成了雏形&#xff0c;先开源出来&#xff0c;感兴趣的玩玩。 请下载最新paint库、customPlus库、lunar库。 不同的颜色搭配&#xff0c;实现不同的风格&#xff1…

小区业主管理系统

摘 要 随着城市化进程的加速和人口的不断增加&#xff0c;小区的数量也在不断增加。小区作为城市居民居住的主要场所&#xff0c;其管理工作也变得越来越重要。传统的小区业主管理方式存在诸多问题&#xff0c;如信息传递不畅、业务处理效率低下等。因此&#xff0c;开发一个高…

循环赛日程表

描述 n 2 ^ k个选手 每个选手必须与其他n-1个选手各赛一次每个选手一天赛一次比赛打n-1天 思路 k 3时的解 我们先进行假设&#xff1a;每个选手第一天和自己比&#xff0c;然后分解成4个子问题&#xff1a; (1)14号的第14天&#xff0c;对手1~4号; (2)14号的第58天&a…

数据结构——优先级队列(堆)Priority Queue详解

1. 优先级队列 队列是一种先进先出(FIFO)的数据结构&#xff0c;但有些情况下&#xff0c;操作的数据可能带有优先级&#xff0c;一般出队列时&#xff0c;可能需要优先级高的元素先出队列&#xff0c;该场景下&#xff0c;使用队列不合适 在这种情况下&#xff0c;数据结构应…

python-爬虫篇-爬取百度贴吧,段友之家的图片和视频

#!/usr/bin/env python # -*- coding: utf-8 -*-""" 爬取百度贴吧&#xff0c;段友之家的图片和视频 author: cuizy time&#xff1a;2018-05-19 """import requests import bs4 import osdef write_file(file_url, file_type):""&quo…