目录
1. 前言
ST 为开发者提供了非常方便的开发库:有标准外设库(SPL库)、HAL 库(Hardware Abstraction Layer,硬件抽象层库)、LL 库(Low-Layer,底层库)三种。前者是ST的老库已经停更了,后两者是ST现在主推的开发库。
相比标准外设库,STM32Cube HAL库表现出更高的抽象整合水平,HAL API集中关注各外设的公共函数功能,这样便于定义一套通用的用户友好的API函数接口,从而可以轻松实现从一个STM32产品移植到另一个不同的STM32系列产品。HAL库是ST未来主推的库,ST新出的芯片已经没有STD库了。目前,HAL库已经支持STM32全线产品。
2. Hal库特点
- 最大可移植性。
- 提供了一整套一致的中间件组件,如RTOS,USB,TCP / IP和图形等。
- 通用的用户友好的API函数接口。
- ST新出的芯片已经没有标准库。
- HAL库已经支持STM32全线产品。
3. 获取方法
3.1 下载
3.2 所在目录
选择Drivers。
选择Stm32F4xx_HAL_Driver。
选择STM32F417xx_User_Manual,STM32F407也应用该文档。
4. HAL库用户手册结构
4.1 用户手册的文档
用户手册文档结构如下图所示。
4.2 “ADC”外设解析
选择“STM32F4xx_HAL_Driver”,并选择“ADC”外设,文档结构如下图所示。
图中圈出的两部分中,相对于HAL库来说,含有“Exported”的对外,可供我们使用,含有 “Private”的对内,为HAL库的私有内容,我们不可以使用。
以ADC外设为例,对外的有Function(函数)、Types(类型)、Constants(常量)和Macros(宏定义),对内有Constants、Macros、Functions。下面在看看各部分具体内容。
4.3 Exported Functions
主要包括初始化、运行、外设控制、外设状态等相关的函数,可供用户使用。如下:
HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc)
{
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
/* Check ADC handle */
if(hadc == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
assert_param(IS_ADC_CLOCKPRESCALER(hadc->Init.ClockPrescaler));
assert_param(IS_ADC_RESOLUTION(hadc->Init.Resolution));
assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ScanConvMode));
assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
assert_param(IS_ADC_EXT_TRIG(hadc->Init.ExternalTrigConv));
assert_param(IS_ADC_DATA_ALIGN(hadc->Init.DataAlign));
assert_param(IS_ADC_REGULAR_LENGTH(hadc->Init.NbrOfConversion));
assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DMAContinuousRequests));
assert_param(IS_ADC_EOCSelection(hadc->Init.EOCSelection));
assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DiscontinuousConvMode));
if(hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START)
{
assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge));
}
if(hadc->State == HAL_ADC_STATE_RESET)
{
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
/* Init the ADC Callback settings */
hadc->ConvCpltCallback = HAL_ADC_ConvCpltCallback; /* Legacy weak callback */
hadc->ConvHalfCpltCallback = HAL_ADC_ConvHalfCpltCallback; /* Legacy weak callback */
hadc->LevelOutOfWindowCallback = HAL_ADC_LevelOutOfWindowCallback; /* Legacy weak callback */
hadc->ErrorCallback = HAL_ADC_ErrorCallback; /* Legacy weak callback */
hadc->InjectedConvCpltCallback = HAL_ADCEx_InjectedConvCpltCallback; /* Legacy weak callback */
if (hadc->MspInitCallback == NULL)
{
hadc->MspInitCallback = HAL_ADC_MspInit; /* Legacy weak MspInit */
}
/* Init the low level hardware */
hadc->MspInitCallback(hadc);
#else
/* Init the low level hardware */
HAL_ADC_MspInit(hadc);
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
/* Initialize ADC error code */
ADC_CLEAR_ERRORCODE(hadc);
/* Allocate lock resource and initialize it */
hadc->Lock = HAL_UNLOCKED;
}
/* Configuration of ADC parameters if previous preliminary actions are */
/* correctly completed. */
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL))
{
/* Set ADC state */
ADC_STATE_CLR_SET(hadc->State,
HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
HAL_ADC_STATE_BUSY_INTERNAL);
/* Set ADC parameters */
ADC_Init(hadc);
/* Set ADC error code to none */
ADC_CLEAR_ERRORCODE(hadc);
/* Set the ADC state */
ADC_STATE_CLR_SET(hadc->State,
HAL_ADC_STATE_BUSY_INTERNAL,
HAL_ADC_STATE_READY);
}
else
{
tmp_hal_status = HAL_ERROR;
}
/* Release Lock */
__HAL_UNLOCK(hadc);
/* Return function status */
return tmp_hal_status;
}
4.4 Exported Types
Hal库中用到的宏定义、自定义类型、枚举、结构体等,可供用户使用。
4.5 Exported Constants
Hal库中用到的常量,可供用户使用。
4.6 Exported Macros
用define方式定义的函数,可供用户使用。
4.6 Private Contants
Hal库自用的常量,不对外。
4.7 Private Macros
Hal库自用的宏定义,不对外。
4.8 Private Functions
Hal库自用的函数,一般函数前加static,不对外。如下:
static void ADC_Init(ADC_HandleTypeDef* hadc)
{
ADC_Common_TypeDef *tmpADC_Common;
/* Set ADC parameters */
/* Pointer to the common control register to which is belonging hadc */
/* (Depending on STM32F4 product, there may be up to 3 ADCs and 1 common */
/* control register) */
tmpADC_Common = ADC_COMMON_REGISTER(hadc);
/* Set the ADC clock prescaler */
tmpADC_Common->CCR &= ~(ADC_CCR_ADCPRE);
tmpADC_Common->CCR |= hadc->Init.ClockPrescaler;
/* Set ADC scan mode */
hadc->Instance->CR1 &= ~(ADC_CR1_SCAN);
hadc->Instance->CR1 |= ADC_CR1_SCANCONV(hadc->Init.ScanConvMode);
/* Set ADC resolution */
hadc->Instance->CR1 &= ~(ADC_CR1_RES);
hadc->Instance->CR1 |= hadc->Init.Resolution;
/* Set ADC data alignment */
hadc->Instance->CR2 &= ~(ADC_CR2_ALIGN);
hadc->Instance->CR2 |= hadc->Init.DataAlign;
/* Enable external trigger if trigger selection is different of software */
/* start. */
/* Note: This configuration keeps the hardware feature of parameter */
/* ExternalTrigConvEdge "trigger edge none" equivalent to */
/* software start. */
if(hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START)
{
/* Select external trigger to start conversion */
hadc->Instance->CR2 &= ~(ADC_CR2_EXTSEL);
hadc->Instance->CR2 |= hadc->Init.ExternalTrigConv;
/* Select external trigger polarity */
hadc->Instance->CR2 &= ~(ADC_CR2_EXTEN);
hadc->Instance->CR2 |= hadc->Init.ExternalTrigConvEdge;
}
else
{
/* Reset the external trigger */
hadc->Instance->CR2 &= ~(ADC_CR2_EXTSEL);
hadc->Instance->CR2 &= ~(ADC_CR2_EXTEN);
}
/* Enable or disable ADC continuous conversion mode */
hadc->Instance->CR2 &= ~(ADC_CR2_CONT);
hadc->Instance->CR2 |= ADC_CR2_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode);
if(hadc->Init.DiscontinuousConvMode != DISABLE)
{
assert_param(IS_ADC_REGULAR_DISC_NUMBER(hadc->Init.NbrOfDiscConversion));
/* Enable the selected ADC regular discontinuous mode */
hadc->Instance->CR1 |= (uint32_t)ADC_CR1_DISCEN;
/* Set the number of channels to be converted in discontinuous mode */
hadc->Instance->CR1 &= ~(ADC_CR1_DISCNUM);
hadc->Instance->CR1 |= ADC_CR1_DISCONTINUOUS(hadc->Init.NbrOfDiscConversion);
}
else
{
/* Disable the selected ADC regular discontinuous mode */
hadc->Instance->CR1 &= ~(ADC_CR1_DISCEN);
}
/* Set ADC number of conversion */
hadc->Instance->SQR1 &= ~(ADC_SQR1_L);
hadc->Instance->SQR1 |= ADC_SQR1(hadc->Init.NbrOfConversion);
/* Enable or disable ADC DMA continuous request */
hadc->Instance->CR2 &= ~(ADC_CR2_DDS);
hadc->Instance->CR2 |= ADC_CR2_DMAContReq((uint32_t)hadc->Init.DMAContinuousRequests);
/* Enable or disable ADC end of conversion selection */
hadc->Instance->CR2 &= ~(ADC_CR2_EOCS);
hadc->Instance->CR2 |= ADC_CR2_EOCSelection(hadc->Init.EOCSelection);
}
5. 结论
看过本文后,相信您对HAL库的结构有了初步了解,将来的编程中不再迷茫。要学习更多实战经验,请关注博主,后续会陆续推出更多实战经验,还请多多关注、批评指正!