12.1 初学者重要提示
学习使用HAL库前,有必要对他们的基本设计框架有所了解,然后深入学习,效果更好。
为了方便调用,HAL库为各种外设基本都配了三套API,查询,中断和DMA。
12.2 HAL库的配置文件
HAL库有一个专门的配置文件叫stm32h7xx_hal_conf.h,这个文件里面有一个很重要的参数,就是HSE_VALUE,大家所设计板子使用的实际晶振大小一定要与这个数值一致。比如V7的外置晶振是25MHz,那么这里就务必配置宏定义为:
#define HSE_VALUE ((uint32_t)25000000)
完整的代码如下:
/* ########################## Module Selection ############################## */
/**
* @brief This is the list of modules to be used in the HAL driver
*/
#define HAL_MODULE_ENABLED
#define HAL_ADC_MODULE_ENABLED
#define HAL_CEC_MODULE_ENABLED
/* 省略未写 */
/* ########################## Oscillator Values adaptation ####################*/
/**
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */
/**
* @brief Internal oscillator (CSI) default value.
* This value is the default CSI value after Reset.
*/
#if !defined (CSI_VALUE)
#define CSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* CSI_VALUE */
/**
* @brief Internal High Speed oscillator (HSI) value.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL).
*/
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)64000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @brief External Low Speed oscillator (LSE) value.
* This value is used by the UART, RTC HAL module to compute the system frequency
*/
#if !defined (LSE_VALUE)
#define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/
#endif /* LSE_VALUE */
#if !defined (LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */
/**
* @brief External clock source for I2S peripheral
* This value is used by the I2S HAL module to compute the I2S clock source
* frequency, this source is inserted directly through I2S_CKIN pad.
*/
#if !defined (EXTERNAL_CLOCK_VALUE)
#define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External clock in Hz*/
#endif /* EXTERNAL_CLOCK_VALUE */
/* Tip: To avoid modifying this file each time you need to use different HSE,
=== you can define the HSE value in your toolchain compiler preprocessor. */
/* ########################### System Configuration ######################### */
/**
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY ((uint32_t)0x0F) /*!< tick interrupt priority */
#define USE_RTOS 0
/* #define USE_SD_TRANSCEIVER 1U */ /*!< use uSD Transceiver */
/* ########################### Ethernet Configuration ######################### */
#define ETH_TX_DESC_CNT 4 /* number of Ethernet Tx DMA descriptors */
#define ETH_RX_DESC_CNT 4 /* number of Ethernet Rx DMA descriptors */
#define ETH_MAC_ADDR0 ((uint8_t)0x02)
#define ETH_MAC_ADDR1 ((uint8_t)0x00)
#define ETH_MAC_ADDR2 ((uint8_t)0x00)
#define ETH_MAC_ADDR3 ((uint8_t)0x00)
#define ETH_MAC_ADDR4 ((uint8_t)0x00)
#define ETH_MAC_ADDR5 ((uint8_t)0x00)
/* ########################## Assert Selection ############################## */
/**
* @brief Uncomment the line below to expanse the "assert_param" macro in the
* HAL drivers code
*/
/* #define USE_FULL_ASSERT 1 */
/* ################## SPI peripheral configuration ########################## */
/**
* @brief Used to activate CRC feature inside HAL SPI Driver
* Activated (1U): CRC code is compiled within HAL SPI driver
* Deactivated (0U): CRC code excluded from HAL SPI driver
*/
#define USE_SPI_CRC 1U
/* Includes ------------------------------------------------------------------*/
/**
* @brief Include module's header file
*/
#ifdef HAL_RCC_MODULE_ENABLED
#include "stm32h7xx_hal_rcc.h"
#endif /* HAL_RCC_MODULE_ENABLED */
/* 省略未写 */
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */
除了HSE_VALUE,下面几个也要作为了解:
第72行,滴答定时器的优先级设置。这个优先级的设置至关重要。因为HAL库中各个外设驱动里面的延迟实现是基于此文件提供的时间基准。
如果在中断服务程序里面调用基于此时间基准的延迟函数HAL_Delay要特别注意,因为这个函数的时间基准是基于滴答定时器或者其他通用定时器实现,实现方式是滴答定时器或者其他通用定时器里面对变量计数。如此以来,结果是显而易见的,如果其他中断服务程序调用了此函数,且中断优先级高于滴答定时器,会导致滴答定时器中断服务程序一直得不到执行,从而卡死在里面。所以滴答定时器的中断优先级一定要比他们高。
另外这个时间基准既可以使用滴答定时器实现也可以使用通用的定时器实现,默认情况下是用的滴答定时器。
第73行,当前HAL库还不支持RTOS方式。
第74行,STM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)的SD卡,需要1.8的电平转换器,此选项就是来使能此功能用的。
第92行,用于使能断言功能,在HAL库的API里面都有用到,用来判断函数形参是否有效。默认情况下是关闭的。
第126行,使能断言功能后,实际对应的代码位置。这里没有对函数void assert_failed(uint8_t* file, uint32_t line)做具体实现,大家可以根据自己的需求去实现,这里提供一个参考:
/*
ST库函数使用了C编译器的断言功能,如果定义了USE_FULL_ASSERT,那么所有的ST库函数将检查函数形参
是否正确。如果不正确将调用 assert_failed() 函数,这个函数是一个死循环,便于用户检查代码。
关键字 __LINE__ 表示源代码行号。
关键字__FILE__表示源代码文件名。
断言功能使能后将增大代码大小,推荐用户仅在调试时使能,在正式发布软件是禁止。
用户可以选择是否使能ST固件库的断言供能。使能断言的方法有两种:
(1) 在C编译器的预定义宏选项中定义USE_FULL_ASSERT。
(2) 在本文件取消"#define USE_FULL_ASSERT 1"行的注释。
*/
/*
*********************************************************************************************************
* 函 数 名: assert_failed
* 形 参:file : 源代码文件名称。关键字__FILE__表示源代码文件名。
* line :代码行号。关键字 __LINE__ 表示源代码行号
* 返 回 值: 无
*********************************************************************************************************
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/*
用户可以添加自己的代码报告源代码文件名和代码行号,比如将错误文件和行号打印到串口
printf("Wrong parameters value: file %s on line %drn", file, line) */
*/
/* 这是一个死循环,断言失败时程序会在此处死机,以便于用户查错 */
while (1)
{
}
}
12.3 HAL库的时间基准
为了方便各种外设延迟的实现,HAL库专门搞了一个时间基准,默认来源是滴答定时器,也可以通过重定向使用其他定时器实现。相关函数全部集中在stm32h7xx_hal.c文件里面实现,关于这些函数在本教程的第16章有详细讲解。
12.4 HAL库的启动流程
这里通过V7板子初始化流程做个说明:
/*
******************************************************************************************************
* 函 数 名: bsp_Init
* 功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
* 只需要调用一次
* 形 参:无
* 返 回 值: 无
******************************************************************************************************
*/
void bsp_Init(void)
{
/* 配置MPU */
MPU_Config();
/* 使能L1 Cache */
CPU_CACHE_Enable();
/*
STM32H7xx HAL 库初始化,此时系统用的还是H7自带的64MHz,HSI时钟:
- 调用函数HAL_InitTick,初始化滴答时钟中断1ms。
- 设置NVIV优先级分组为4。
*/
HAL_Init();
/*
配置系统时钟到400MHz
- 切换使用HSE。
- 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。
*/
SystemClock_Config();
bsp_InitKey(); /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */
bsp_InitTimer(); /* 初始化滴答定时器 */
bsp_InitUart(); /* 初始化串口 */
bsp_InitExtIO(); /* 初始化FMC总线74HC574扩展IO. 必须在 bsp_InitLed()前执行 */
bsp_InitLed(); /* 初始化LED */
bsp_InitLPTIMOutPWM(); /* 低功耗定时器PWM输出 */
}
第13 – 16行,配置MPU和使能Cache,对于H7而已,这两个函数要优先执行,因为Flash速度,SRAM速度跟CPU和TCM有些差距的,所以要使能Cache。而不同存储区的Cache策略要通过MPU分别进行配置。
第23行,调用函数HAL_Init时,系统依然使用的64MHz HSI时钟,这点要特别注意。此函数会调用函数HAL_InitTick,初始化滴答时钟中断1ms,并设置NVIV优先级分组为4。
这里就隐含了一个知识点,就是它会开启滴答定时器中断,如果用户也要使用滴答定时器中断,此问题就要引起注意,我们的bsp_timer.C文件解决办法如下:
/*
*********************************************************************************************************
* 函 数 名: SysTick_Handler
* 功能说明: 系统嘀嗒定时器中断服务程序。启动文件中引用了该函数。
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
上一篇:【STM32H7教程】第13章 STM32H7启动过程详解
下一篇:【STM32H7教程】第11章 STM32H7移植SEGGER的硬件异常分析
推荐阅读最新更新时间:2024-11-10 01:36
设计资源 培训 开发板 精华推荐
- MPC86XADS、MPC8xx 参考板,基于 MPC862SR MPU PowerQUICC MPC8xx 处理器
- 【物联网】鸿蒙智能WIFI开关+4226863A
- 使用 Microchip Technology 的 MCP2510T-E 的参考设计
- TS39103CP518 RO 1A、1.8V超低压差多功能稳压器典型应用电路
- 使用 LTC4162EUFD-LADM 1-8 节、3.2A 降压型开关电池充电器和 PowerPath 的典型应用
- USB供电评估板,使用STM32F072 Type-C端口管理器和安森美半导体的FUSB307B Type-C端口控制器
- 【嵌入式】逐梦贰号-基于STC32的智能小车
- LT1634CCZ-5 单节锂离子电池监控电路的典型应用 (IQ = 20uA)
- L6726ATR单相PWM控制器典型应用
- 逐飞方案_电磁四路运放板OPA4377_略宽
- 答题赢好礼|平稳控制与位置服务中至关重要的 ADI MEMS IMU
- 【双11特别推荐】新产品,新方案,#TI“芯”世界#之电机驱动器
- 【EE征集令】LaunchPad学习全体验
- 有奖直播:瑞萨电子 R-Car 先进驾驶辅助系统方案
- 身临其境不足以窥全貌,《TI嵌入式产品研讨会》比现场更有料的小小书
- WEBENCH轻松注册,尽享精彩好礼!
- 模电怎么学?TI帮你定制课程清单!体验“模电选课测试”功能,赢精彩好礼
- Vicor白皮书下载——双向电源:“安静”改变世界的驱动力
- STM32全国巡回研讨会!(走进11城,9/12-10/27)
- 学习有礼,分享也有礼!跟着小梅哥,一起intel SoC FPGA走起!