从源代码来看HAL库函数(一) HAL基础函数

2023-05-16

从源代码来看HAL库函数(一) HAL基础函数


全局变量
  • __IO uint32_t uwtick
    • 这个变量充当了一个运行时长计数的作用,每发生一次SysTick中断就会加一,直至溢出,可以计算一下,溢出时间为2^32/1000/3600(以每1ms+1来算),大概要1193个小时,约50天,一般情况下是不用担心它会溢出的。
      - uint32_t uwTickPrio = (1UL << __NVIC_PRIO_BITS )
    • SysTick计数器中断优先级,应该是最高优先级
  • HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT
    enum   HAL_TickFreqTypeDef { HAL_TICK_FREQ_10HZ = 100U, HAL_TICK_FREQ_100HZ = 10U, HAL_TICK_FREQ_1KHZ = 1U, HAL_TICK_FREQ_DEFAULT = HAL_TICK_FREQ_1KHZ} 
    
    这是一个枚举变量,定义了SysTick的中断频率,也就是1khz,1ms中断一次,这里也可以看到,HAL库中SysTick中断频率只有10HZ,100HZ,1000HZ这三种选择,最高只能支持1ms的计数中断,所以不能用它来产生us级别的中断计数延时,但是我们可以不使用HAL库提供的延时函数,可以利用时钟摘取的方式来实现我们自己的ms和us级延时,参考正点原子提供的delay延时函数实现。

  • HAL_StatusTypeDef HAL_Init (void)
    该函数被调用来初始化HAL库,在main函数里面必须是首先被执行。
    函数一共做了以下几件事:
    • 配置SysTick来产生1ms的时基(此时还并未配置系统时钟来源,因此这时使用的HSI)
    • 配置中断分组
    • 调用HAL_MspInit来进行低级硬件初始化
00142 HAL_StatusTypeDef HAL_Init(void)
00143 {
00144   /* Configure Flash prefetch */
00145 #if (PREFETCH_ENABLE != 0)
00146 #if defined(STM32F101x6) || defined(STM32F101xB) || defined(STM32F101xE) || defined(STM32F101xG) || \
00147     defined(STM32F102x6) || defined(STM32F102xB) || \
00148     defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) || \
00149     defined(STM32F105xC) || defined(STM32F107xC)
00150 
00151   /* Prefetch buffer is not available on value line devices */
00152   __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
00153 #endif
00154 #endif /* PREFETCH_ENABLE */
00155 
00156   /* Set Interrupt Group Priority */
00157   HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
00158 
00159   /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
00160   HAL_InitTick(TICK_INT_PRIORITY);
00161 
00162   /* Init the low level hardware */
00163   HAL_MspInit();
00164 
00165   /* Return function status */
00166   return HAL_OK;
00167 }

  • HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority)
    该函数配置SysTick时钟来产生默认1ms的中断,同时指定了SysTick的中断优先级。
    该函数被HAL_Init调用来初始化SysTick
00234 __weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
00235 {
        //配置SysTick来产生1ms的中断时基  
00237   if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
00238   {
00239     return HAL_ERROR;
00240   }
00241   // 配置SysTick的中断优先级
00243   if (TickPriority < (1UL << __NVIC_PRIO_BITS))
00244   {
00245     HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
00246     uwTickPrio = TickPriority;
00247   }
00248   else
00249   {
00250     return HAL_ERROR;
00251   }
00252 
00254   return HAL_OK;
00255 }

  • __weak void HAL_MspInit(void)
    前面讲了HAL_Init会调用这个函数来完成低等级硬件初始化,那么这个函数实际完成了什么呢?
    以下代码是参考手册里的函数体,可以看到这个函数什么也没干,毕竟我们还没给它分配初始化任务
00200 __weak void HAL_MspInit(void)
00201 {
00202   /* NOTE : This function should not be modified, when the callback is needed,
00203             the HAL_MspInit could be implemented in the user file
00204    */
00205 }

以下代码是通过STM32CubeMx生成的,可以看到,配置完成之后,HAL_MspInit完成了使能需求时钟,配置中断分组,以及配置调试接口的任务。
因此,该函数的函数体内容是根据用户需求来动态修改的,会根据任务的不同拥有不同的函数体,当然你也可以添加你自己的需求代码。但要注意这个函数调用的时机是在main函数的最开始,由HAL_Init来调用的。不需要手动调用。之后你会看到好多类似的Init函数都不用自己来调用。

void HAL_MspInit(void)
{


  __HAL_RCC_AFIO_CLK_ENABLE();
  __HAL_RCC_PWR_CLK_ENABLE();

  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
  
  __HAL_AFIO_REMAP_SWJ_DISABLE();


}

  • void HAL_Delay(uint32_t Delay)
    该函数提供了精确到ms的延时。默认情况下,该函数使用SysTick定时器来当作时钟源。
    该函数定义在stm32f1xx_hal.c的360行。
 __weak void HAL_Delay(uint32_t Delay)
 {
   uint32_t tickstart = HAL_GetTick();
   uint32_t wait = Delay;
  /* Add a freq to guarantee minimum wait */
  if (wait < HAL_MAX_DELAY)
  {
    wait += (uint32_t)(uwTickFreq);
  }

  while ((HAL_GetTick() - tickstart) < wait)
  {
  }
}

从代码可以看出该延时采用阻塞延时的方式,利用时钟摘取的方式获取当前运行时刻,来实现延时。__weak前缀表示该函数可以被重写。


  • uint32_t HAL_GetTick(void)
    该函数返回了一个32位数值,代表了当前运行的时间,以ms为单位
    该函数定义在stm32f1xx_hal.c的304行。
 __weak uint32_t HAL_GetTick(void)
 {
   return uwTick;
 }

从源代码可以看出该函数很简单,只是返回了全局变量uwtick的值,同样,该函数是可以被重写的


  • void HAL_IncTick (void)
    前面讲HAL_GetTick是返回当前的计数值,那么这个函数就是被SysTick_Handler来调用,每次产生中断就调用它来自增uwtick
00293 __weak void HAL_IncTick(void)
00294 {
00295   uwTick += uwTickFreq;   //HAL_TICK_FREQ_1KHZ = 1U,所以这里这么写,如果修改了SysTick的中断频率,这里也相应的改变了
00296 }

  • HAL_TickFreqTypeDef HAL_GetTickFreq(void)
    该函数返回了SysTick的中断频率
00344 HAL_TickFreqTypeDef HAL_GetTickFreq(void)
00345 {
00346   return uwTickFreq;
00347 }

  • uint32_t HAL_GetTickPrio (void)
    该函数返回SysTick的中断优先级
00313 uint32_t HAL_GetTickPrio(void)
00314 {
00315   return uwTickPrio;
00316 }

  • void HAL_SuspendTick ( void )
    停止SysTick计数和中断,
00386 __weak void HAL_SuspendTick(void)
00387 {
00388   /* Disable SysTick Interrupt */
00389   CLEAR_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk);
00390 }

  • void HAL_ResumeTick (void)
    重新开始SysTick计数和中断
00402 __weak void HAL_ResumeTick(void)
00403 {
00404   /* Enable SysTick Interrupt */
00405   SET_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk);
00406 }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从源代码来看HAL库函数(一) HAL基础函数 的相关文章

  • Linux:进程创建详解

    Linux xff1a 进程创建详解 进程创建1 fork函数写时拷贝调用失败的原因 2 vfork函数 进程终止正常退出的三种方法 exit和exit的区别 进程创建 现在我们已经知道进程的概念以及怎样创建一个进程 xff0c 接下来我们
  • Linux:简单理解文件系统内附Linux内核设计与实现PDF下载地址

    简单理解文件系统 文件系统ext2文件系统文件的存储文件的获取 文件系统 文件存储的方式有线性存储和离散存储两种 xff0c 线性存储可能会导致磁盘的利用率降低 xff0c 产生磁盘碎片 xff0c 离散存储方式会提高程序对磁盘的利用率 x
  • Linux:网络编程——UDP编程的前期准备

    Linux xff1a 网络编程 UDP编程的前期准备 字节序TCP与UDP的区别UDP编程的流程1 创建套接字创建套接字的意义 2 绑定地址信息 xff08 1 xff09 绑定ip和端口 xff08 2 xff09 函数 3 UDP发送
  • Xshell连接虚拟机时报错Could not connect to ‘192.168.115.133‘ (port 22): Connection failed.

    Xshell连接虚拟机时报错Could not connect to 192 168 115 133 port 22 Connection failed 今天突然想把拨号连接换成宽带连接 结果问题就来了 用下Xshell连接虚拟机的时候一直
  • Linux:简单三步,教你解决ping:www.baidu.com:未知的名称或者服务

    Linux xff1a 简单三步 xff0c 教你解决ping www baidu com 未知的名称或者服务 1 在VMware Workstation中点开编辑 xff0c 找到虚拟网络编辑器2 直接点击更改设置3 点击还原默认设置 x
  • C++:从结构体开始理解this指针

    C 43 43 xff1a 从结构体开始理解this指针 span class token macro property span class token directive keyword include span span class
  • 原来直接插入排序这么简单(附完整代码)

    原来插入排序这么简单 附完整代码 xff09 基本思想带哨兵位的插入排序二分插入排序完整代码 基本思想 做一件是之前我们总是要先知道我们做这件的核心思想 xff0c 这样会让我们做事的效率得到有效的提高 xff1b 现在我们来看看插入排序算
  • 一张图带你了解c/c++的内存分布

    c c 43 43 的内存分布 对照这些代码查看对应内存分布 xff1a span class token keyword int span globalVar span class token operator 61 span span
  • 用一个例子理解希尔排序

    用一个例子理解希尔排序 思想代码 思想 希尔排序是把序列按下标的一定增量分组 xff0c 对每组使用直接插入排序算法排序 xff1b 随着增量的逐渐减少 xff0c 每组包含的关键词越来越多 xff0c 当增量减至1时 xff0c 整个序列
  • c++ pi

    C 43 43 中表示pi的方法有两种 xff08 1 xff09 math库中利用arctan函数算出 span class token function tan span span class token punctuation spa
  • 【非数值数据的编码】西文字符和汉字的编码表示 汉字国标码、机内码详细理解

    西文字符和汉字的编码表示 西文字符概念ASCII码表特点 西文字符特点西文字符表示 xff08 常用编码为7位ASCII码 xff09 西文字符操作 汉字字符编码形式输入码字符集与汉字内码汉字的区位码汉字的国标码汉字内码 汉字的字模点阵码和
  • 修改centos7系统用户最大线程数和最大文件数限制

    修改centos7系统用户最大线程数和最大文件数限制 需要注意 xff0c 不同版本的Linux系统所对应的修改方法不同 ulimit 的作用 ulimit xff1a 显示 xff08 或设置 xff09 用户可以使用的资源的限制 xff
  • (已全部解决)ubantu18运行vins遇到的问题

    1 sudo rosdep init时报错 xff1a 打开hosts文件 sudo gedit etc hosts 在文件末尾添加 151 101 84 133 raw githubusercontent com 保存后退出再尝试 sud
  • ROS只使用思岚A1激光雷达进行slam建图

    使用思岚A1激光雷达 A1的ros功能包下载地址 xff1a https github com slamtec rplidar ros 因为只有激光雷达 xff0c 需要其做SLAM的话 xff0c 就需要有一个laser scan mat
  • STM32 四轴无人机的设计——基于HCSR04超声波模块的距离检测与警报设计

    1 系列总述 从现在开始将会进入四轴无人机的制作 xff0c 我是第一次制作四旋翼 xff0c 从前没有接触过这个方面 xff0c 手边的参考资料只有一本四轴的设计书和正点原子F405飞控的源码 xff0c 所以代码逻辑设计方面肯定有所欠缺
  • 【C++基础】inline与内联函数

    目录 引入 inline 关键字inline使用限制类中的成员函数与inline 引入 inline 关键字 为了解决一些频繁调用的小函数大量消耗栈空间 xff08 栈内存 xff09 的问题 xff0c 特别的引入了 inline 修饰符
  • 串口通信的基本原理详解

    目录 串口通信 串口通信的两种基本方式 异步数据的数据发送过程 异步通信的数据接收过程 9针串口 xff08 DB9 xff09 TTL与RS232区别 TTL RS232 xff1a 串口通信的数据格式 通讯方式 偶校验与奇校验 停止位
  • jeston nano安装Ubuntu镜像时启动遇到问题

    A start job is running for End user configuration after initial OEM installation 开始我跑了一下午 43 一晚上 xff0c 都没成功 xff0c 第二天 xf
  • cmake 常用变量、常用环境变量、常用语法总结

    一 cmake 变量引用的方式 前面我们已经提到了 使用 进行变量的引用 在 IF 等语句中 是直接使用变量名而不通过 取值 二 cmake 自定义变量的方式 主要有隐式定义和显式定义两种 隐式定义的例子 xff1a PROJECT 指令
  • Java基础篇:Iterator迭代器

    一 什么是Iterator xff1a 迭代器 Iterator 是一个对象 xff0c 它的工作是遍历并目标序列中的对象 xff0c 它提供了一种访问一个容器 container 对象中的各个元素的方法 xff0c 把访问逻辑从不同类型的

随机推荐

  • 2022-2-19 ros环境变量

    学习时间及标题 xff1a 2022 2 19 ros环境变量 学习内容 xff1a 1 添加环境变量 xff1a source span class token operator span span class token operato
  • EGO-Planner: An ESDF-free Gradient-based Local Planner for Quadrotors(论文学习)

    EGO规划器 xff1a 一种基于ESDF自由梯度的四转子局部规划器 摘要 ESDF地图被广泛运用在局部地图的梯度方向和大小估计之中 xff0c 但是由于我们在进行轨迹优化的过程中 xff0c 只用到了ESDF地图中很小的一部分 xff0c
  • cmake "undefined reference to"

    main函数在调用其他 c或 cpp文件的函数时 xff0c 有以下几种情况 函数名写错 没有将其他 c或 cpp文件链接到main o xff0c 导致main函数在执行时找不到需要调用的函数 的解决方法 修改CMakeLists txt
  • STM32串口详解

    实验一 xff1a 简单的利用串口接收中断回调函数实现数据的返回 关于串口调试助手 xff0c 还应知道 xff1a 发送英文字符需要用一个字符即8位 xff0c 发送汉字需要两个字符即16位 xff0c 如上图 xff0c 发送汉字 姜
  • RLException: [xx.launch] is neither a launch file in package [x] nor is [x] a launch file name的解决方法

    ROS学习过程中 xff0c 遇到问题 xff1a RLException xx launch is neither a launch file in package x nor is x a launch file name 出现的问题
  • numpy 中 shape 与 size 属性

    因为需要生成一个和现有矩阵大小相等的矩阵 xff0c 故查找了相关资料 span class token operator gt gt span span class token operator gt span span class to
  • Ubtuntu+C语言实现网络通信附源代码

    下面这个案例是我用C在ubtuntu上面写的网络编程案例 2 网络编程 xff08 1 xff09 OSI七层模型理想化 应用层 xff1a app xff0c 应用程序 表示层 xff1a 对数据进行加工 会话层 xff1a 建立会话 x
  • Jetson Nano的GPIO口学习

    1 配置GPIO库 https github com NVIDIA jetson gpio 1 安装pip工具 sudo apt get update sudo apt get install python3 pip sudo apt ge
  • 22.11.22 TCP与UDP 客户端与服务器 协议搭建

    ubuntu 64 ubuntu yuyu yu 11 cat Tcp Cli c 客户端 include lt stdio h gt include lt sys types h gt include lt sys socket h gt
  • cmake交叉编译配置

    cmake交叉编译配置 很多时候 xff0c 我们在开发的时候是面对嵌入式平台 xff0c 因此由于资源的限制需要用到相关的交叉编译 即在你host宿主机上要生成target目标机的程序 里面牵扯到相关头文件的切换和编译器的选择以及环境变量
  • OS——gcc、g++、gdb、vim、vs code的基本使用

    文章目录 g 43 43 的使用gdb的使用vim的使用vscode的使用vs code的安装vs code中C 43 43 的编译运行配置 如果想要学习如何在CentOS 7中安装配置gcc g 43 43 gdb zhs和oh my z
  • make和cmake

    编程人员已经使用CMake和Make很长一段时间了 当你加入一家大公司或者开始在一个具有大量代码的工程上开展工作时 xff0c 你需要注意所有的构建 你需要看到处跳转的 CMakeLists txt 文件 你应该会在终端使用 cmake 和
  • ubuntu自带python与anaconda python环境的切换

    ubuntu的python可分为三大类 xff1a 1 ubuntu自带的python环境 一般安装在 usr bin 中python2和python3可以共存 2 anaconda自带的base环境 3 在anaconda中创建的虚拟py
  • 详细介绍如何在ubuntu20.04中安装ROS系统,以及安装过程中出现的常见错误的解决方法,填坑!!!

    本篇文章写于2020 10 xff0c 经过很多小伙伴的验证 xff0c 文章所介绍的步骤是可以正常完成安装的 xff0c 现在是2021 10 xff0c 经过近期的探索 xff0c 我将安装步骤进行了进一步的优化 xff0c 使安装变得
  • VScode进行python开发出现 No module named “XXX“的解决方法

    VScode进行python开发出现 No module named 34 XXX 34 的解决方法 最近从pycharm转向vscode的时候 xff0c 遇到了如下问题 span class token keyword import s
  • CM3寄存器简介

    Cortex M3基础 寄存器组 通用目的寄存器组R0 R7 也被称为低组寄存器 xff0c 所有指令都能访问字长32位 通用目的寄存器组R8 R12 高组寄存器 32位寄存器 复位后的初始值不可预料 堆栈指针R13 CM3中共有两个堆栈指
  • 基于亚博K210开发板的学习之旅(一)

    本文参考亚博智能官方K210开源课程 五月份购买了亚博的K210开发板 xff0c 但由于课程压力就搁置了 xff0c 最近暑假得空又恰逢电赛清单里有这个 芯片 xff0c 就抽空学习一下 xff0c 特写下这些 xff0c 以作记录 按照
  • STM32标准库通用软件模拟IIC

    STM32标准库通用软件模拟IIC 继上次通用可移植的矩阵键盘之后 xff0c 便继续寻找着下一个能够拿来只需改改引脚就可以使用的通用方案 恰好最近在研究PCA9685 xff0c 这是一片能够产生最多十六路PWM信号的芯片 xff0c 通
  • STM32F103控制PCA9685产生16路PWM波控制SG90舵机

    STM32控制PCA9685产生16路PWM波控制SG90舵机 如果你能点开这篇文章 xff0c 说明你已经知道PCA9685是多么强大 xff0c NXP公司原本做这片芯片是为了提供给LED使用 xff0c 在其官方文档里也能看到所有PW
  • 从源代码来看HAL库函数(一) HAL基础函数

    从源代码来看HAL库函数 xff08 一 xff09 HAL基础函数 全局变量 IO uint32 t uwtick 这个变量充当了一个运行时长计数的作用 xff0c 每发生一次SysTick中断就会加一 xff0c 直至溢出 xff0c