16.1 初学者重要提示
对于一些常用的函数,大家一定要熟练的掌握都实现了什么功能,比如HAL_Init,HAL_RCC_OscConfig,HAL_RCC_ClockConfig等。最好的办法是把这些函数的源码读一遍。
16.2 那些是必备的API
这里我们通过一个简单的初始化流程来了解STM32H7的工程模板所必备的库文件和API:
第1步:系统上电复位,进入启动文件startup_stm32h743xx.s,在这个文件里面执行复位中断服务程序。
在复位中断服务程序里面执行函数SystemInit,此函数在文件system_stm32h7xx.c里面。
之后是调用编译器封装好的函数,比如用于MDK的启动文件是调用__main,最终进入到main函数。
第2步:进入到main函数就可以开始用户应用程序编程了。在这个函数里面要做几个重要的初始化,依次是:
MPU初始化,需要用到库文件stm32h7xx_hal_cortex.c和stm32h7xx_hal_cortex.h。
Cache初始化,需要用到core_cm7.h文件。
HAL库初始化函数HAL_Init,需要用到文件stm32h7xx_hal.c。
系统时钟初始化,需要用到库文件stm32h7xx_hal_rcc.c。
前面的两步完成后,就可以开始做用户需要的按键、串口等方面的初始化和应用代码的实现了。这里把我们需要学习的几个库文件整理出来,依次有:
startup_stm32h743xx.s
system_stm32h7xx.c
stm32h7xx_hal.c
stm32h7xx_hal_cortex.c
stm32h7xx_hal_rcc.c
core_cm7.h
其中startup_stm32h743xx.s和system_stm32h7xx.c已经在第13章为大家讲解过,这里不再赘述。而MPU和Cache涉及到的文件core_cm7.h在第23和24章为大家讲解。本章教程重点为大家讲解文件stm32h7xx_hal.c、stm32h7xx_hal_cortex.c和sm32h7xx_hal_rcc.c。
16.3 源文件stm32h7xx_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)
{
/* 设置中断优先级分组 */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
/* 使用滴答定时器做为默认时基,配置为1ms滴答,另外系统上电后默认使用的HIS时钟 */
if(HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
{
return HAL_ERROR;
}
/* 初始化底层硬件 */
HAL_MspInit();
/* 返回函数状态 */
return HAL_OK;
}
函数描述:
此函数用于初始化HAL库,此函数主要实现如下功能:
设置NVIC优先级分组是4。
设置滴答定时器的每1ms中断一次。
HAL库不像之前的标准库,在系统启动函数SystemInit里面做了RCC初始化,HAL库是没有做的,所以进入到main函数后,系统还在用内部高速时钟HSI,对于H7来说,HSI主频是64MHz。
函数HAL_Init里面调用的HAL_MspInit一般在文件stm32h7xx_hal_msp.c里面做具体实现,主要用于底层初始化。当前此函数也在文件stm32h7xx_hal.c里面,只是做了弱定义。
函数参数:
返回值,返回HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
注意事项:
必须在main函数里面优先调用此函数。
用户务必保证每1ms一次滴答中断。
关于优先级分组的设置可以看第21章节。
使用举例:
此函数的使用比较简单,上电后优先调用即可。
16.3.2 函数HAL_DeInit
函数原型:
HAL_StatusTypeDef HAL_DeInit(void)
{
/* 复位所有外设 */__set_PRIMASK
__HAL_RCC_AHB3_FORCE_RESET();
__HAL_RCC_AHB3_RELEASE_RESET();
/* 省略未写 */
__HAL_RCC_APB4_FORCE_RESET();
__HAL_RCC_APB4_RELEASE_RESET();
/* 复位底层硬件初始化 */
HAL_MspDeInit();
/* 返回值 */
return HAL_OK;
}
函数描述:
此函数用于复位HAL库和滴答时钟。
复位了AHB1,2,3,4的时钟以及APB1L,APB1H,APB2,3,4的时钟。
函数HAL_DeInit里面调用的HAL_MspDeInit一般在文件stm32h7xx_hal_msp.c里面做具体实现,主要用于底层初始化,跟函数HAL_Init里面调用的HAL_MspInit是一对。当前此函数也在文件stm32h7xx_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 函数HAL_SYSCFG_VREFBUF_VoltageScalingConfig
函数原型:
void HAL_SYSCFG_VREFBUF_VoltageScalingConfig(uint32_t VoltageScaling)
函数描述:
此函数用于配置STM32H7内部电压基准大小。
当形参VoltageScaling = SYSCFG_VREFBUF_VOLTAGE_SCALE0时
输出基准是2.048 V,条件是VDDA >= 2.4V。
当形参VoltageScaling = SYSCFG_VREFBUF_VOLTAGE_SCALE1时
输出基准是2.5 V,条件是VDDA >= 2.8V。
当形参VoltageScaling = SYSCFG_VREFBUF_VOLTAGE_SCALE2时
输出基准是1.5 V,条件是VDDA >= 1.8V。
当形参VoltageScaling = SYSCFG_VREFBUF_VOLTAGE_SCALE3时
输出基准是1.8 V,条件是VDDA >= 2.1V。
16.3.6 H7自带电压基准相关函数
函数原型:
void HAL_SYSCFG_VREFBUF_VoltageScalingConfig(uint32_t VoltageScaling)
void HAL_SYSCFG_VREFBUF_TrimmingConfig(uint32_t TrimmingValue)
HAL_StatusTypeDef HAL_SYSCFG_EnableVREFBUF(void)
void HAL_SYSCFG_DisableVREFBUF(void)
函数描述:
函数HAL_SYSCFG_VREFBUF_VoltageScalingConfig
此函数用于配置STM32H7内部电压基准是否在芯片内部与VREF+引脚接通。
形参为SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE时,表示导通。
形参为SYSCFG_VREFBUF_HIGH_IMPEDANCE_ENABLE时,表示高阻,即不导通。
函数HAL_SYSCFG_VREFBUF_TrimmingConfig
此函数用于内部电压基准的校准调节。
函数HAL_SYSCFG_EnableVREFBUF和HAL_SYSCFG_DisableVREFBUF是一对,分别用于内部电压参考基准的禁止和使能。
16.3.7 函数HAL_SYSCFG_AnalogSwitchConfig
函数原型:
void HAL_SYSCFG_AnalogSwitchConfig(uint32_t SYSCFG_AnalogSwitch , uint32_t SYSCFG_SwitchState )
函数描述:
引脚PA0,PA1,PC2,PC3用于ADC时,还有一组对应的可选引脚PA0_C,PA1_C,PC2_C和PC3_C。此函数的作用就是切换可选引脚。关于这个问题的详情可看此贴:http://forum.armfly.com/forum.php?mod=viewthread&tid=87707 。
16.3.8 BOOST的使能和禁止(用于ADC)
函数原型:
void HAL_SYSCFG_EnableBOOST(void)
void HAL_SYSCFG_DisableBOOST(void)
函数描述:
这两个函数用于使能或者禁止Booster。如果使能了booster的话,在供电电压低于2.7V时,可以减少模拟开关总的谐波失真,这样的话,模拟开关的性能跟正常供电电压时的全范围测量一样。
16.3.9 函数HAL_SYSCFG_CM7BootAddConfig
函数原型:
void HAL_SYSCFG_CM7BootAddConfig(uint32_t BootRegister, uint32_t BootAddress)
函数描述:
用于配置BOOT = 0或者BOOT = 1时的启动地址,详情可以看第13章的13.4小节。
16.3.10 IO补偿相关函数
函数原型:
void HAL_EnableCompensationCell(void)
void HAL_DisableCompensationCell(void)
void HAL_SYSCFG_EnableIOSpeedOptimize(void)
void HAL_SYSCFG_DisableIOSpeedOptimize(void)
void HAL_SYSCFG_CompensationCodeSelect(uint32_t SYSCFG_CompCode)
void HAL_SYSCFG_CompensationCodeConfig(uint32_t SYSCFG_PMOSCode, uint32_t SYSCFG_NMOSCode )
函数描述:
函数HAL_EnableCompensationCell和HAL_DisableCompensationCell
分别用于使能或者禁止IO补偿,只有在供电电压范围是2.4V到3.6V之间时,使用此功能才有意义。
函数HAL_SYSCFG_EnableIOSpeedOptimize和HAL_SYSCFG_DisableIOSpeedOptimize
分别用于优化IO速度或者禁止优化,不过仅在供电电压低于2.5V时可用,高于2.5V是不可以使用的,另外使用这个功能的前提是用户使能了PRODUCT_BELOW_25V(是可选字节配置选项里面的一个bit)。
函数HAL_SYSCFG_CompensationCodeSelect
IO补偿单元的选择,函数形参可以是SYSCFG_CELL_CODE,即寄存器SYSCFG_CCVR,也可以是SYSCFG_REGISTER_CODE,即寄存器SYSCFG_CCCR。
函数HAL_SYSCFG_CompensationCodeConfig
用于设置GPIO内部构造中NMOS和PMOS的补偿值,两个形参的范围都是0-15。根据用户调用函数HAL_SYSCFG_CompensationCodeSelect选择的寄存器,这里仅有一个形参的设置是有效的。
16.3.11 低功耗和EXTI相关函数
低功耗和EXTI相关的函数暂时不做讲解,后面章节用到时候再说明。
16.4 源文件stm32h7xx_hal_rcc.c
这个文件主要是实现内部和外部时钟(HSE、HSI、LSE、CSI、LSI、HSI48、PLL、CSS、MCO)以及总线时钟(SYSCLK、AHB3、 AHB1、AHB2、AHB4、APB3、APB1L、APB1H、APB2、 APB4)的配置。
学习这个文件注意事项:
系统上电复位后,通过内部高速时钟HSI运行(主频64MHz),Flash工作在0等待周期,所有外设除了SRAM、Flash、JTAG 和 PWR,时钟都是关闭的。这里特别注意SRAM,官方手册里面说的太笼统,这个SRAM到底是指的哪个SRAM。关于这个问题,详情看此贴:http://forum.armfly.com/forum.php?mod=viewthread&tid=87784 。
AHB和APB总线无分频,所有挂载这两类总线上的外设都是以HSI频率运行。
所有的GPIO都是模拟模式,除了JTAG相关的几个引脚。
系统上电复位后,用户需要完成以下工作:
选择用于驱动系统时钟的时钟源。
配置系统时钟频率和Flash设置。
配置分频器。
使能外设时钟。
配置外设时钟源,部分外设的时钟可以不来自系统时钟,此时通过配置寄存器RCC_D1CCIPR、RCC_D2CCIP1R、RCC_D2CCIP2R 和 RCC_D3CCIPR 实现。
RCC局限性:
使能了外设时钟后,不能立即操作对应的寄存器,要加延迟。不同外设延迟不同:
如果是AHB的外设,使能了时钟后,需要等待2个AHB时钟周期才可以操作这个外设的寄存器。
如果是APB的外设,使能了时钟后,需要等待2个APB时钟周期才可以操作这个外设的寄存器。
当前HAL库的解决方案是在使能了外设时钟后,再搞一个读操作,算是当做延迟用。
比如下面使能GPIOA的时钟:
#define __HAL_RCC_GPIOA_CLK_ENABLE() do {
__IO uint32_t tmpreg;
SET_BIT(RCC->AHB4ENR, RCC_AHB4ENR_GPIOAEN);
/* Delay after an RCC peripheral clock enabling */
tmpreg = READ_BIT(RCC->AHB4ENR, RCC_AHB4ENR_GPIOAEN);
UNUSED(tmpreg);
} while(0)
关于时钟方面的知识点补充
1、正确理解HCLK1,2,3,4以及PCLK1,2,3,4对应哪些总线的时钟,下面一张图可以说明问题:

由上图可以得出:
HCLK1,2,3,4对应的是AHB总线AHB1,AHB2,AHB3和AHB4时钟。
PCLK1、2、3、4对应的是APB总线APB1,APB2,APB3和APB4时钟。
2、内部和外部时钟配置:
HSI (high-speed internal)
高速内部RC振荡器,可以直接或者通过PLL倍频后做系统时钟源。缺点是精度差些,即使经过校准。
CSI (Low-power internal oscillator)
低功耗内部RC振荡器,作用同HSI,不过主要用于低功耗。
LSI (low-speed internal)
低速内部时钟,主要用于独立看门狗和RTC的时钟源。
HSE (high-speed external)
高速外部晶振,可接4 - 48MHz的晶振,可以直接或者通过PLL倍频后做系统时钟源,也可以做RTC的是时钟源。
LSE (low-speed external)
低速外部晶振,主要用于RTC。
CSS (Clock security system)
上一篇:【STM32H7教程】第17章 STM32H7之GPIO的HAL库API
下一篇:【STM32H7教程】第15章 STM32H7的GPIO基础知识(重要)
推荐阅读
史海拾趣
EICHHOFF公司成立于XX世纪XX年代,当时由创始人XXX在德国的一个小镇上开设了一个小型的电子元件加工厂。由于XXX对电子技术的热爱和对市场需求的敏锐洞察,他专注于生产高质量的连接器和其他电子组件。在初创阶段,EICHHOFF的产品主要供应给当地的电子制造商和维修店。随着口碑的逐渐传播和产品质量的不断提升,公司开始接到来自更广泛地区的订单。
为了应对不断增长的市场需求,EICHHOFF公司逐步扩大了生产规模,并引入了先进的生产设备和技术。同时,公司也注重人才培养和团队建设,吸引了一批有才华的工程师和技术人员加入。这些努力使得EICHHOFF在电子行业中逐渐崭露头角。
1954年至1973年,Emerson在总裁帕森斯的领导下,开始实施多元化战略。公司通过一系列并购活动,成功收购了包括威诺、美国电气电机、里奇工具等在内的36家公司,进一步拓宽了业务范围。同时,Emerson还注重研发和创新,通过不断推出新产品和技术,巩固了其在电气行业的领先地位。在此期间,公司的规模迅速扩大,从最初的2家工厂、4000名员工和5600万美元产值发展到82家工厂、31000名员工和8亿美元产值。
在追求经济效益的同时,Horn公司也注重可持续发展。公司积极采用环保材料和绿色生产工艺,减少对环境的影响。此外,Horn公司还注重人才培养和团队建设,为公司的长期发展奠定了坚实的人才基础。展望未来,Horn公司将继续秉承“创新、质量、服务”的企业理念,致力于成为切削工具行业的领导者,为全球客户提供更加优质的产品和服务。
随着公司业务的不断拓展,科通技术开始与国际知名品牌展开合作。通过与Xilinx、Intel、SanDisk等全球领先的芯片原厂建立紧密的合作关系,科通技术获得了这些品牌的产品线授权,并为其在中国市场的拓展提供了有力的支持。这些合作不仅提升了科通技术的品牌影响力,也为其带来了更多的市场机会。
|
[i=s] 本帖最后由 jameswangsynnex 于 2015-3-3 19:58 编辑 [/i]哪位仁兄手上有RICHTEK品牌,規格爲:RT9193-33PB SOT-23-5 3.3V LDO的規格書呀?兄弟我現在急需,如能提供感激不盡。 … 查看全部问答∨ |
大家都知道做PCB板就是把设计好的原理图变成一块实实在在的PCB电路板,请别小看这一过程,有很多原理上行得通的东西在工程中却难以实现,或是别人能实现的东西另一些人却实现不了,因此说做一块PCB板不难,但要做好一块PCB板却不是一件容易的事情。 微 ...… 查看全部问答∨ |
|
呵呵,这是我第一次做单片机学习板,用的AVR芯片。ATmega16单片机学习板。 学习板总要起个名字啊,想来想去想不到好名字,干脆用我儿子的名字来命名吧。于是就叫“傲飞电子 AVR-ATmega16”学习板。 说明:板子的功能说一下, 1、所有的IO口除在 ...… 查看全部问答∨ |
|
|
学了一段时间单片机,主要是AT89C52 其中遇到了关于AT89C52内部ram和sfr是不是物理相同的部分?或者说地址为80H 到0FFH之间的特殊功能寄存器 和 RAM 中 80H到0FFH中的堆栈或数据存贮器是否相同? 一直没有搞 ...… 查看全部问答∨ |
|
|
2410/2440裸奔时MMU以及寄存器访问和植入Wince时候有何不同? 最近想把内存改为128M,现在正在看u241mon启动代码,里面也涉及到MMU等,但是我看到2410addr.Inc文件里面的寄存器地址是物理地址的 GBLL BIG_ENDIAN__ BIG_ENDIAN__ SETL {FALSE} ;================= ; Me ...… 查看全部问答∨ |
大三了才发现自己对硬件最感兴趣,专家建议一下要学哪方面的知识? rt,大三了自己也感觉有点晚了,不过还是想根据自己的爱好来学习一下;我的本来专业是网络工程,数电、模电、电路分析都学过,还有一些硬件的基础知识;高手帮忙介绍一下硬件方面目前的就业情况,以及哪方面或哪几方面的知识比较重要?谢谢了@… 查看全部问答∨ |
|
evc的联机帮助Microsoft Foundation Class Library for Windows CE.NET中 对CListBox的DrawItem的说明,说DrawItem 可以重写,如果重写了,请问,如何让系统调用自己重写的DrawItem函数。 msdn中,有段代码 // CMyListBox is my owner-drawn lis ...… 查看全部问答∨ |
- 新春寻宝记,泰克送福利!快来开启你的寻宝之旅~
- 【EEWORLD大学堂】玩转LaunchPad及TI MSP430G2XX系列超值单片机!!!
- 有奖直播 11月27日上午10:00 准时开启!富士通赋能汽车电子技术变革
- 芯币竞拍:感恩教师节专场
- 【TI 培训】年度盘点:2019 TI 培训课程集锦,好评有礼!
- 【EEWORLD第十七届社区明星人物】伙拼七月明星人物胜出!
- 如何加快你的FPGA设计步伐
- 【干货上新】电源解决方案和技术第二趴 | DigiKey 应用探索站
- PI 有奖直播|电机开发很复杂?MotorXpert™助您事半功倍!
- 下载信息娱乐系统精品文章,赢【米家台灯、小米保温杯、米家蓝牙温湿计】,开启MPS汽车技术进阶之旅!





ASM10DTBD-S664






京公网安备 11010802033920号