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

食用指南:本文主要内容为梳理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()------古月居可查看全文

相关推荐
山河君19 小时前
webrtc之高通滤波——HighPassFilter源码及原理分析
算法·音视频·webrtc·信号处理
勇往直前plus19 小时前
Sentinel微服务保护
java·spring boot·微服务·sentinel
星辰大海的精灵19 小时前
SpringBoot与Quartz整合,实现订单自动取消功能
java·后端·算法
小鸡脚来咯19 小时前
一个Java的main方法在JVM中的执行流程
java·开发语言·jvm
江团1io019 小时前
深入解析三色标记算法
java·开发语言·jvm
data myth19 小时前
力扣1210. 穿过迷宫的最少移动次数 详解
算法·leetcode·职场和发展
天天摸鱼的java工程师19 小时前
RestTemplate 如何优化连接池?—— 八年 Java 开发的踩坑与优化指南
java·后端
惯导马工19 小时前
【论文导读】AI-Assisted Fatigue and Stamina Control for Performance Sports on IMU-Gene
深度学习·算法
m0_7381207219 小时前
CTFshow系列——PHP特性Web97-100
开发语言·安全·web安全·php·ctfshow
你我约定有三19 小时前
java--泛型
java·开发语言·windows