因为官方针对这个HAL还是有不少的例子的,比如官方完整的Demo例子就有HAL的版本,其中涵盖了大多数的函数~
文件夹也有分类的,其中来说Middlewares,Application,Drivers三大类,其中Middlewares,就是中间件,什么是中间件呢,就是不完全底层,不完全上层,属于一个衔接.比如USB库,MSC库,RTOS以及图形库,然后Drivers属于底层,Application自然是上层应用了,上层应用肯定是自己写的.主要从Drivers/BSP/Components先分析,主要关心底层的改变,上层的改变都是我们自己应用层的事情,跟底层并没什么关系的.比如以下片段:
static void I2Cx_Init(void) { if(HAL_I2C_GetState(&I2cHandle) == HAL_I2C_STATE_RESET) { I2cHandle.Instance = DISCOVERY_I2Cx; I2cHandle.Init.ClockSpeed = BSP_I2C_SPEED; I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_2; I2cHandle.Init.OwnAddress1 = 0; I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED; I2cHandle.Init.OwnAddress2 = 0; I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED; I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED; /* Init the I2C */ I2Cx_MspInit(&I2cHandle); HAL_I2C_Init(&I2cHandle); } }
暂且不说I2Cx_MspInit是怎么实现的,而且因为没有HAL前缀,也证明这个东西不是HAL库的,而HAL_I2C_Init才是HAL库的.传入一个结构体,结构体的定义是如下的:
I2C_HandleTypeDef I2cHandle;
换句话说就是I2C_HandleTypeDef,官方文档里就有这个定义了.
而对比没有HAL库的代码:
static void IOE_I2C_Config(void) { I2C_InitTypeDef I2C_InitStructure; /* If the I2C peripheral is already enabled, don't reconfigure it */ if ((IOE_I2C->CR1 & I2C_CR1_PE) == 0) { /* IOE_I2C configuration */ I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = 0x00; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED; /* Initialize the I2C peripheral */ I2C_Init(IOE_I2C, &I2C_InitStructure); /* Enable the I2C peripheral */ I2C_Cmd(IOE_I2C, ENABLE); } }
对比一看,HAL库只需要写I2C速度,就可以大致计算,而且感觉HAL库更深入底层设置.不过HAL还有个优点,发送I2C再也不用担心不会用了.
(#) Blocking mode functions are : (++) HAL_I2C_Master_Transmit() (++) HAL_I2C_Master_Receive() (++) HAL_I2C_Slave_Transmit() (++) HAL_I2C_Slave_Receive() (++) HAL_I2C_Mem_Write() (++) HAL_I2C_Mem_Read() (++) HAL_I2C_IsDeviceReady() (#) No-Blocking mode functions with Interrupt are : (++) HAL_I2C_Master_Transmit_IT() (++) HAL_I2C_Master_Receive_IT() (++) HAL_I2C_Slave_Transmit_IT() (++) HAL_I2C_Slave_Receive_IT() (++) HAL_I2C_Mem_Write_IT() (++) HAL_I2C_Mem_Read_IT() (#) No-Blocking mode functions with DMA are : (++) HAL_I2C_Master_Transmit_DMA() (++) HAL_I2C_Master_Receive_DMA() (++) HAL_I2C_Slave_Transmit_DMA() (++) HAL_I2C_Slave_Receive_DMA() (++) HAL_I2C_Mem_Write_DMA() (++) HAL_I2C_Mem_Read_DMA() (#) A set of Transfer Complete Callbacks are provided in non Blocking mode: (++) HAL_I2C_MemTxCpltCallback() (++) HAL_I2C_MemRxCpltCallback() (++) HAL_I2C_MasterTxCpltCallback() (++) HAL_I2C_MasterRxCpltCallback() (++) HAL_I2C_SlaveTxCpltCallback() (++) HAL_I2C_SlaveRxCpltCallback() (++) HAL_I2C_ErrorCallback()
比如要发送接收都有了,还有非阻塞的,然后通过回调函数来实现功能,真是非常方便的,跟之前说的GPIO中断一样,默认的回调都是weak的,需要你自己额外实现,就可以替换掉这个weak函数了.
__weak void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) { /* Prevent unused argument(s) compilation warning */ UNUSED(hi2c); /* NOTE : This function Should not be modified, when the callback is needed, the HAL_I2C_TxCpltCallback could be implemented in the user file */ }
这样就容易很多了,再也不用有以前的担心了,而且效率也是更高了哦.所以,HAL库应该是以后的发展方向,当然如果ST官方愿意兼容以前的库,就是名字不要改,这样估计会更多人接收,只是这样的分层管理就显得没有那么的方便了.