第16章 STM32F429必备的HAL库API

发布者:Xiaohan521最新更新时间:2022-04-13 来源: eefocus关键字:STM32F429  HAL库  API 手机看文章 扫描二维码
随时随地手机看文章

16.1 初学者重要提示

对于一些常用的函数,大家一定要熟练的掌握都实现了什么功能,比如HAL_Init,HAL_RCC_OscConfig,HAL_RCC_ClockConfig等。最好的办法是把这些函数的源码读一遍。


16.2 那些是必备的API

这里我们通过一个简单的初始化流程来了解STM32F4的工程模板所必备的库文件和API:


第1步:系统上电复位,进入启动文件startup_stm32f429xx.s,在这个文件里面执行复位中断服务程序。


在复位中断服务程序里面执行函数SystemInit,此函数在文件system_stm32f4xx.c里面。


之后是调用编译器封装好的函数,比如用于MDK的启动文件是调用__main,最终进入到main函数。


第2步:进入到main函数就可以开始用户应用程序编程了。在这个函数里面要做几个重要的初始化,依次是:


HAL库初始化函数HAL_Init,需要用到文件stm32f4xx_hal.c。


系统时钟初始化,需要用到库文件stm32f4xx_hal_rcc.c。

 


前面的两步完成后,就可以开始做用户需要的按键、串口等方面的初始化和应用代码的实现了。这里把我们需要学习的几个库文件整理出来,依次有:


  startup_stm32f429xx.s

  system_stm32f4xx.c

  stm32f4xx_hal.c

  stm32f4xx_hal_cortex.c

  stm32f4xx_hal_rcc.c

  core_cm4.h

其中startup_stm32f429xx.s和system_stm32f4xx.c已经在第13章为大家讲解过,这里不再赘述。。本章教程重点为大家讲解文件stm32f4xx_hal.c、stm32f4xx_hal_cortex.c和sm32f4xx_hal_rcc.c(core_cm4.h文件在后面章节为大家讲解)。


16.3 源文件stm32f4xx_hal.c(重要)

这个文件比较杂,像基准电压大小配置,EXTI配置,IO补偿配置等都在这个文件里面设置。学习这个文件注意事项:


HAL库中各个外设驱动里面的延迟实现是基于此文件提供的时间基准,而这个时间基准既可以使用滴答定时器实现也可以使用通用的定时器实现,默认情况下是用的滴答定时器。


函数HAL_Init里面会调用时间基准初始化函数HAL_InitTick,而调用函数HAL_RCC_ClockConfig也会调用时间基准初始化函数HAL_InitTick。


如果在中断服务程序里面调用延迟函数HAL_Delay要特别注意,因为这个函数的时间基准是基于滴答定时器或者其他通用定时器实现,实现方式是滴答定时器或者其他通用定时器里面做了个变量计数。如此一来,结果是显而易见的,如果其他中断服务程序调用了此函数,且中断优先级高于滴答定时器,会导致滴答定时器中断服务程序一直得不到执行,从而卡死在里面。所以滴答定时器的中断优先级一定要比它们高。


16.3.1 函数HAL_Init

函数原型:


HAL_StatusTypeDef HAL_Init(void)

{


  /* 配置Flash的指令预取,指令Cache和数据Cache */ 

#if (INSTRUCTION_CACHE_ENABLE != 0U)

  __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();

#endif 


#if (DATA_CACHE_ENABLE != 0U)

  __HAL_FLASH_DATA_CACHE_ENABLE();

#endif 


#if (PREFETCH_ENABLE != 0U)

  __HAL_FLASH_PREFETCH_BUFFER_ENABLE();

#endif 


  /* 设置中断优先级分组 */

  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);


/* 使用滴答定时器做为默认时基,配置为1ms滴答,另外系统上电后默认使用的HSI时钟 */

  HAL_InitTick(TICK_INT_PRIORITY);


  /* 初始化底层硬件 */

  HAL_MspInit();


  /* 返回HAL_OK */

  return HAL_OK;

}

函数描述:


此函数用于初始化HAL库,此函数主要实现如下功能:


设置NVIC优先级分组是4。

设置滴答定时器的每1ms中断一次。


HAL库不像之前的标准库,在系统启动函数SystemInit里面做了RCC初始化,HAL库是没有做的,所以进入到main函数后,系统还在用内部高速时钟HSI,对于F4来说,HSI主频是16MHz。


函数HAL_Init里面调用的HAL_MspInit一般在文件stm32f4xx_hal_msp.c里面做具体实现,主要用于底层初始化。当前此函数也在文件stm32f4xx_hal.c里面,只是做了弱定义。

函数参数:


返回值,返回HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。


注意事项:


必须在main函数里面优先调用此函数。

用户务必保证每1ms一次滴答中断。

关于优先级分组的设置可以看第xx章节(注:后面做到这个章节时补上)。

使用举例:


此函数的使用比较简单,上电后优先调用即可。


16.3.2 函数HAL_DeInit

函数原型:


HAL_StatusTypeDef HAL_DeInit(void)

{

  /* 复位所有外设 */

  __HAL_RCC_APB1_FORCE_RESET();

  __HAL_RCC_APB1_RELEASE_RESET();


  __HAL_RCC_APB2_FORCE_RESET();

  __HAL_RCC_APB2_RELEASE_RESET();


  __HAL_RCC_AHB1_FORCE_RESET();

  __HAL_RCC_AHB1_RELEASE_RESET();


  __HAL_RCC_AHB2_FORCE_RESET();

  __HAL_RCC_AHB2_RELEASE_RESET();


  __HAL_RCC_AHB3_FORCE_RESET();

  __HAL_RCC_AHB3_RELEASE_RESET();


  /* 复位底层硬件初始化 */

  HAL_MspDeInit();


  /* 返回值 */

  return HAL_OK;

}

函数描述:


此函数用于复位HAL库和滴答时钟。


  复位了APB1,2的时钟以及AHB1,2,3的时钟。

  函数HAL_DeInit里面调用的HAL_MspDeInit一般在文件stm32f4xx_hal_msp.c里面做具体实现,主要用于底层初始化,跟函数HAL_Init里面调用的HAL_MspInit是一对。当前此函数也在文件stm32f4xx_hal.c里面,只是做了弱定义。

使用举例:


此函数的使用比较简单,需要调用的时候直接调用即可。


16.3.3 函数HAL_InitTick

函数原型:


__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)

{

  /* Configure the SysTick to have interrupt in 1ms time basis*/

  if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)

  {

    return HAL_ERROR;

  }


  /* Configure the SysTick IRQ priority */

  if (TickPriority < (1UL << __NVIC_PRIO_BITS))

  {

    HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);

    uwTickPrio = TickPriority;

  }

  else

  {

    return HAL_ERROR;

  }


  /* Return function status */

  return HAL_OK;

}

函数描述:


此函数用于初始化滴答时钟,此函数相关问题如下:


  此函数有个前缀__weak ,表示弱定义,用户可以重定义。

  此函数用于初始化滴答时钟1ms中断一次,并且为滴答中断配置一个用户指定的优先级。

  此函数由HAL_Init调用,或者任何其它地方调用函数HAL_RCC_ClockConfig配置RCC的时候也会调用HAL_InitTick。

  调用基于此函数实现的HAL_Delay要特别注意,因为这个函数的时间基准是基于滴答定时器或者其他通用定时器实现,实现方式是滴答定时器或者其他通用定时器里面做了个变量计数。如此一来,结果是显而易见的,如果其他中断服务程序调用了此函数,且中断优先级高于滴答定时器,会导致滴答定时器中断服务程序一直得不到执行,从而卡死在里面。所以滴答定时器的中断优先级一定要比它们高。

函数参数:


  形参TickPriority用于设置滴答定时器优先级。

  返回值,返回HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。

使用举例:


此函数由HAL_Init调用,无需用户操作,除非需要重定义。


16.3.4 Systick的相关函数

调用了函数HAL_Init后,Systick相关的函数就可以使用了。这些函数如下:


函数原型:


__weak void HAL_IncTick(void)

__weak uint32_t HAL_GetTick(void)

uint32_t HAL_GetTickPrio(void)

HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq)

HAL_TickFreqTypeDef HAL_GetTickFreq(void)

__weak void HAL_Delay(uint32_t Delay)

__weak void HAL_SuspendTick(void)

__weak void HAL_ResumeTick(void)

函数描述:


这些函数就比较简单了,下面把这些函数实现的功能做个简单的说明:


  函数HAL_IncTick在滴答定时器中断里面被调用,实现一个简单的计数功能,因为一般滴答定时器中断都是配置的1ms,所以计数全局变量uwTick每毫秒加1。

  函数HAL_GetTick用于获取全局变量uwTick当前的计数。

  函数HAL_GetTickPrio用于获取滴答时钟优先级。

  函数HAL_SetTickFreq和HAL_GetTickFreq是一对,前者用于设置滴答中断频率,后再用于获取滴答中断频率。

  函数HAL_Delay用于阻塞式延迟,默认单位是ms。

  函数HAL_SuspendTick和HAL_ResumeTick是一对,前者用于挂起滴答定时器,后者用于恢复。

注意事项:


  函数有个前缀__weak ,表示弱定义,用户可以重定义。

使用举例:


这些函数都比较简单,这里就不举例了。需要的时候,直接调用即可。


16.3.5 低功耗状态下继续使用调试功能

如果希望在睡眠,停机和待机的低功耗模式下继续使用调试功能,调用下面的函数即可:


/* 睡眠模式下继续使用调试功能 */

void HAL_DBGMCU_EnableDBGSleepMode(void)

{

  SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);

}


/* 停机模式下继续使用调试功能 */

void HAL_DBGMCU_EnableDBGStopMode(void)

{

  SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);

}


/* 待机模式下继续使用调试功能 */

void HAL_DBGMCU_EnableDBGStandbyMode(void)

{

  SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);

}

16.4 源文件stm32f4xx_hal_rcc.c

这个文件主要是实现内部和外部时钟(HSE、HSI、LSE、LSI、PLL、CSS、MCO)以及总线时钟(SYSCLK、AHB1、AHB2、AHB3、APB1)的配置。


学习这个文件注意事项:


1、  系统上电复位后,通过内部高速时钟HSI运行(主频16MHz),Flash工作在0等待周期,所有外设除了SRAM、Flash、JTAG 和 PWR,时钟都是关闭的。


  AHB和APB总线无分频,所有挂载这两类总线上的外设都是以HSI频率运行。

  所有的GPIO都是模拟模式,除了JTAG相关的几个引脚。

2、  系统上电复位后,用户需要完成以下工作:


  选择用于驱动系统时钟的时钟源。

  配置系统时钟频率和Flash设置。

  配置分频器。

  使能外设时钟。

  配置外设时钟源,部分外设的时钟可以不来自系统时钟(I2S, RTC, ADC, USB OTG FS/SDIO/RNG)。

RCC局限性:


使能了外设时钟后,不能立即操作对应的寄存器,要加延迟。不同外设延迟不同:


  如果是AHB的外设,使能了时钟后,需要等待2个AHB时钟周期才可以操作这个外设的寄存器。

  如果是APB的外设,使能了时钟后,需要等待2个APB时钟周期才可以操作这个外设的寄存器。

 


当前HAL库的解决方案是在使能了外设时钟后,再搞一个读操作,算是当做延迟用。


 


比如下面使能GPIOA的时钟:


#define __HAL_RCC_GPIOA_CLK_ENABLE()   do {

                                        __IO uint32_t tmpreg = 0x00U;

                                        SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);

                                        /* Delay after an RCC peripheral clock enabling */

                                        tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);

                                        UNUSED(tmpreg);

                                        } while(0U)

  关于时钟方面的知识点补充

1、正确理解PCLK1,2和HCLK对应哪些总线的时钟,下面一张图可以说明问题:

由上图可以得出:


PCLK1、PC对应的是APB总线APB1,APB2时钟。


HCLK对应的AHB总线。


2、内部和外部时钟配置:


  HSI (high-speed internal)

高速内部RC振荡器,可以直接或者通过PLL倍频后做系统时钟源。缺点是精度差些,即使经过校准。


  LSI (low-speed internal)

低速内部时钟,主要用于独立看门狗和RTC的时钟源。


  HSE (high-speed external)

高速外部晶振,可接4 - 26z的晶振,可以直接或者通过PLL倍频后做系统时钟源,也可以做RTC的是时钟源。


  LSE (low-speed external)

低速外部晶振,主要用于RTC。


  CSS (Clock security system)

时钟安全系统,一旦使能后,如果HSE启动失败(不管是直接作为系统时钟源还是通过PLL输出后做系统时钟源),系统时钟将切换到HSI。如果使能了中断的话,将进入不可屏蔽中断NMI。


  MCO1 (micro controller clock output)

可以在PA8引脚输出SYSCLK、PLLI2SCLK、HSE和PLLCLK。


  MCO2 (micro controller clock output)

可以在PC9引脚输出LSE、HSE、HSI和PLLCLK。


  PLL锁相环,时钟输入来自HSI , HSE 或者CSI

16.4.1 函数HAL_RCC_DeInit

函数原型:


__weak HAL_StatusTypeDef HAL_RCC_DeInit(void)

{

  return HAL_OK;

}

函数描述:


文件stm32f4xx_hal_rcc.c里面的此函数是空的(做了__weak弱定义,方便用户再其它文件里面重定义),ST将具体实现放在了stm32f4xx_hal_rcc_ex.c里面的此函数里面


此函数用于RCC复位函数,主要实现如下功能:


  HSI 打开作为系统时钟。

  HSE和PLL关闭。

  AHB, APB1和APB2总线无分频 。

  CSS, MCO1 和 MCO2 关闭。

  所有中断关闭。

注意事项:


此函数不会修改外设时钟,LSI、LSE和RTC时钟。

使用举例:


此函数的使用比较简单,需要调用的时候直接调用即可。


16.4.2 函数HAL_RCC_OscConfig

函数原型:

函数描述:


通过上面函数原型,我们可以一目了然的看出此函数的作用,配置了HSE、HSI、LSI、LSE和PLL。


函数参数:


  函数的形参是RCC_OscInitTypeDef类型结构体变量,这个结构体的定义如下(主要是HSE、HSI、LSI、LSE和PLL的配置变量):

/**

  * @brief  RCC Internal/External Oscillator (HSE, HSI, LSE and LSI) configuration structure definition

  */

typedef struct

{

  uint32_t OscillatorType;       

  uint32_t HSEState;            

  uint32_t LSEState;            

  uint32_t HSIState;           

  uint32_t HSICalibrationValue;  

  uint32_t LSIState;            

  RCC_PLLInitTypeDef PLL;        

}RCC_OscInitTypeDef;

注意事项:


LSE Bypass 切换到 LSE On 或者 LSE On切换到 LSE Bypass都不支持,用需要先关闭LSE,然后才可以切换到LSE Bypass 或者LSE On。

HSE Bypass 切换到 HSE On 或者 LSE On切换到 LSE Bypass都不支持,用需要先关闭HSE,然后才可以切换到HSE Bypass 或者HSE On。

使用举例:


    RCC_OscInitTypeDef RCC_OscInitStruct;


    /* 使能HSE,并选择HSE作为PLL时钟源 */

    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

    RCC_OscInitStruct.HSEState = RCC_HSE_ON;

    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

    RCC_OscInitStruct.PLL.PLLM = 8;

    RCC_OscInitStruct.PLL.PLLN = 336;

    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;

    RCC_OscInitStruct.PLL.PLLQ = 4;

    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

    {

        Error_Handler(__FILE__, __LINE__);

    }

16.4.3 函数HAL_RCC_ClockConfig

函数原型:

函数描述:


通过上面函数原型,我们可以一目了然的看出此函数的作用,配置了HCLK、SYSCLK、PLCK1和PLCK2。

[1] [2]
关键字:STM32F429  HAL库  API 引用地址:第16章 STM32F429必备的HAL库API

上一篇:第17章 STM32F429之GPIO的HAL库API
下一篇:第15章 STM32F429的GPIO基础知识(重要)

推荐阅读最新更新时间:2024-11-13 11:45

Scale推出传感器融合标注API,为自动驾驶技术更快注入数据燃料
Scale推出传感器融合标注API,为自动驾驶技术更快注入数据燃料 Scale API最近推出传感器融合标注API(Sensor Fusion Annotation API),能够支持所有主流传感器的高级3D感知,包括激光雷达(30米内稠密3D场景理解)、相机(70米内图像目标识别)和Radar(150米内稀疏场景理解),以帮助汽车制造商和自动驾驶汽车公司加速感知算法的开发。 Scale API基于云服务,用户可以上传大量未标记的数据集,由公司对其进行标注,以便用于计算机视觉模型的训练。同时能处理各种数据集,幕后工作人员“Scaler”可以确保标注质量和可扩展性,他们的工作效率会随时被跟踪记录,用于构建自动化质量管线。
[汽车电子]
【STM32】HAL库-DMA
DMA 直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。 无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。 DMA控制器和Cortex™-M3核心共享系统数据总线,执行直接存储器数据传输。当CPU和DMA同时访问相同的目标(RAM或外设)时,DMA请求会暂停CPU访问系统总线达若干个周期,总线仲裁器执行循环调度,以保证CPU至少可以得到一半的系统总线(存储器或外设)带宽。 DMA配置过程 DMA的数据对齐 一句话,如果目标的容量存放不了源数据,则只能尽可能存放源数据(小端模式) 操作一个不支持字节或半字写的AHB设备 当DMA模块开始一个
[单片机]
【STM32】<font color='red'>HAL库</font>-DMA
FreeRTOS移植,基于STM32 HAL库
一、硬件准备 一个STM32开发板(STM32F429IGT6),及其电源线等; 一个ST-Link下载器及其连接线等。 二、软件准备 FreeRTOS源码(V9.0.0); 一个基于STM32 HAL库的基础例程(跑马灯例程)。 三、移植FreeRTOS 3.1 添加FreeRTOS源码至工程 添加源代码至工程目录,添加至工程分组中,添加相关头文件路径 编译,提示找不到 FreeRTOSConfig.h 3.2 添加 FreeRTOSConfig.h 文件来源:事先参考众多例程中的 FreeRTOSConfig.h 后,总结出来的 编译结果为:2个error。SVC_Handler() 和 PendSV_Handler()
[单片机]
HAL库中断处理以及相关的回调函数
今天就分享一个读者问到的关于中断处理的问题。 很多人都知道STM32CubeMX这套工具的一个目的:减少开发者对STM32底层驱动的开发时间,把重心放在应用代码上。 但是,STM32CubeMX只是生成了底层驱动的初始化代码。所以,我们还需要掌握:应用层代码如何调用HAL库函数(API接口),以及HAL库中断处理机制等相关知识。 HAL库牵涉的内容较多,下面简单描述一下HAL库中断处理,以及相关的回调函数。 1HAL库中断处理机制 之前使用标准外设库开发时,中断程序(函数)由我们自己实现。 而HAL库的中断处理函数是按照HAL处理机制来实现,如USART1,统一由HAL_UART_IRQHandler来进行处理,如下图: 其
[单片机]
<font color='red'>HAL库</font>中断处理以及相关的回调函数
使用STM32hal库usart的接收中断分析及出现部分问题的解决
最近开始使用ST的hal库,这个库相较于之前的标准库,优缺点兼具吧,hal库封装了更多底层的细节,我们可以很轻易的实现我们需要的功能,但是由于封装了太多的细节,导致一旦出问题,你就很难发现问题,内部调用的复杂让你觉得懵逼。 (一)hal库接收中断的分析 这几天在使用hal库的USART,其中用到的是接收中断,官方推荐的使用接收中断的方式是:在初始化函数上面先开启接收中断(这里就不介绍串口的配置,网上一大推,我就不给世界增加无谓的存储量了),开启的函数如下: HAL_UART_Receive_IT(&huart2,(uint8_t*)aRxBuffer, 1);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设
[单片机]
第29章 STM32F429的系统bootloader之USB DFU方式固件升级
29.1 初学者重要提示 学习本章节前,务必优先学习第28章。 本章用到的相关软件和文档下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=96573 。 软件STM32CubeProg和DfuSe都支持USB DFU,但是两个软件不能都安装使用,因为这两个软件的USB驱动不同,导致工作在系统bootloader模式的板子通过USB线接到电脑端时,只有一个软件的驱动被识别。 DfuSe是老版的USB DFU软件,不推荐大家使用了。建议使用STM32CubeProg,此软件实现了之前的DfuSe,STLINK小软件和Flashloader三合一,并且支持外部EEPRO
[单片机]
第29章 <font color='red'>STM32F429</font>的系统bootloader之USB DFU方式固件升级
STM32F1XX系列 HAL库 CAN大量收发数据
大量收发数据时,会产生收发数据0-3分钟后不再收发数据的现象,此时是由于库函数内部将CAN总线状态改为忙碌。 可在While(1)中填写如下代码 if( HAL_BUSY == HAL_CAN_Receive_IT(hcanx, CAN_FIFO0))//开启中断接收 { /* Enable FIFO 0 overrun and message pending Interrupt */ __HAL_CAN_ENABLE_IT(&hcan1, CAN_IT_FOV0 | CAN_IT_FMP0); }
[单片机]
英特尔1.8亿美元收购API管理公司Mashery
4月19日消息,据国外媒体报道, 英特尔 已经同意用1.80亿美元收购位于旧金山的应用程序编程接口(API)管理创业企业Mashery。此举旨在向软件与服务市场扩张。这次收购将是英特尔为企业提供一套跨平台服务的核心部分。   英特尔发言人称,这个收购交易是英特尔构建一个集成的英特尔成套服务的下一个步骤。Mashery带来了管理和显示企业API的技术和专长。Mashery在关键垂直市场的技术专长将使英特尔能够进一步提供由服务能力增强的用户体验。   Mashery提供一套管理API的工具。这些工具能够在企业内部使用,也可以作为云中的服务使用。   此外,这个工具包还包括一个门户网站,除了缓存、安全工具、用户仪表板和使用报告之外
[工业控制]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved