ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
* 导师视频讲解:[**去听课**](https://www.bilibili.com/video/BV1k34y1D7Vz?p=30) >[success] **技术支持说明:** >**1**.一般以自主学习为主 > **2**.可到官方问答社区中提问:[**去提问**](https://bbs.csdn.net/forums/zigbee) > **3**.工程师**会尽快**解答社区问题,但他们是一线开发,【**难以保证**】解答时效,解答辛苦,感谢理解! <br/> 本节课继续以SampleSwitch例程为例来讲解HAL的架构。类似地,读者只需要跟随笔者的讲解思路大致了解一下本节课的内容就可以了。 <br/> ## **HAL的架构简介** ### **初始化** HAL的初始化函数Hal_Init()在hal_drivers.c文件中,代码如下: ``` /************************************************************************************************** * @fn Hal_Init * * @brief Hal Initialization function. * * @param task_id - Hal TaskId * * @return None **************************************************************************************************/ void Hal_Init( uint8 task_id ) { /* Register task ID */ Hal_TaskID = task_id; #ifdef CC2591_COMPRESSION_WORKAROUND osal_start_reload_timer( Hal_TaskID, PERIOD_RSSI_RESET_EVT, PERIOD_RSSI_RESET_TIMEOUT ); #endif } ``` <br/> **驱动程序初始化** 在hal_drivers.c文件中,可以找到驱动初始化函数HalDriverInit(),这个函数的主要作用是针对各种硬件外设进行初始化,代码如下: ``` /************************************************************************************************** * @fn Hal_DriverInit * * @brief Initialize HW - These need to be initialized before anyone. * * @return None **************************************************************************************************/ void HalDriverInit (void) { //定时器,通过设置宏定义HAL_TIMER为TRUE来使能该功能 #if (defined HAL_TIMER) && (HAL_TIMER == TRUE) #endif //模数转换功能,通过设置宏定义HAL_ADC为TRUE来使能该功能 #if (defined HAL_ADC) && (HAL_ADC == TRUE) HalAdcInit(); #endif //DMA(直接存储器访问),通过设置宏定义HAL_DMA为TRUE来使能该功能 #if (defined HAL_DMA) && (HAL_DMA == TRUE) HalDmaInit(); #endif //AES(高级加密标准),通过设置宏定义HAL_AES为TRUE来使能该功能 #if (defined HAL_AES) && (HAL_AES == TRUE) HalAesInit(); #endif //显示器,通过设置宏定义HAL_LCD为TRUE来使能该功能 #if (defined HAL_LCD) && (HAL_LCD == TRUE) HalLcdInit(); #endif //LED,通过设置宏定义HAL_LED为TRUE来使能该功能 #if (defined HAL_LED) && (HAL_LED == TRUE) HalLedInit(); #endif //串口,通过设置宏定义HAL_UART为TRUE来使能该功能 #if (defined HAL_UART) && (HAL_UART == TRUE) HalUARTInit(); #endif //按键,通过设置宏定义HAL_KEY为TRUE来使能该功能 #if (defined HAL_KEY) && (HAL_KEY == TRUE) HalKeyInit(); #endif //SPI,通过设置宏定义HAL_SPI为TRUE来使能该功能 #if (defined HAL_SPI) && (HAL_SPI == TRUE) HalSpiInit(); #endif //HID(Human Interface Device),通过设置宏定义HAL_HID为TRUE来使能该功能 #if (defined HAL_HID) && (HAL_HID == TRUE) usbHidInit(); #endif } ``` ### 在实际的开发过程中,开发者可以根据需求来使用指定的外设。在这段代码中可以看出,需要用指定的外设就定义对应宏就可以了,例如如果要用LED,那么就去定义HAL_LED这个宏为TRUE,如果不用用到,那么就不用定义。在定义了对应的宏后就会执行对应的初始化,例如这个LED初始化函数HalLedInit()。后续的章节将会讲述具体的宏定义方法。 ### 开发者如果需要新增其他的外设,那么可以按照协议栈的这个架构新增外设 <br/> **事件处理** HAL的事件处理函数Hal\_ProcessEvent()在hal\_drivers.c文件中,它的主要作用是处理HAL层的事件,代码如下: ``` /************************************************************************************************** * @fn Hal_ProcessEvent * * @brief Hal Process Event * * @param task_id - Hal TaskId * events - events * * @return None **************************************************************************************************/ uint16 Hal_ProcessEvent( uint8 task_id, uint16 events ) { uint8 *msgPtr; (void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG ) { //省略系统事件的处理代码 ......... return events ^ SYS_EVENT_MSG; } //蜂鸣器事件,需要宏定义HAL_BUZZER为TRUE才使能该事件 #if (defined HAL_BUZZER) && (HAL_BUZZER == TRUE) if (events & HAL_BUZZER_EVENT) { HalBuzzerStop(); return events ^ HAL_BUZZER_EVENT; } #endif //RSSI重置事件,需要宏定义PERIOD_RSSI_RESET_EVT为TRUE才使能该事件 #ifdef CC2591_COMPRESSION_WORKAROUND if ( events & PERIOD_RSSI_RESET_EVT ) { macRxResetRssi(); return (events ^ PERIOD_RSSI_RESET_EVT); } #endif //LED闪烁事件 if ( events & HAL_LED_BLINK_EVENT ) { #if (defined (BLINK_LEDS)) && (HAL_LED == TRUE) HalLedUpdate(); #endif /* BLINK_LEDS && HAL_LED */ return events ^ HAL_LED_BLINK_EVENT; } //按键事件 if (events & HAL_KEY_EVENT) { #if (defined HAL_KEY) && (HAL_KEY == TRUE) /* Check for keys */ HalKeyPoll(); /* if interrupt disabled, do next polling */ if (!Hal_KeyIntEnable) { osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100); } #endif return events ^ HAL_KEY_EVENT; } //低功耗事件,需要宏定义HAL_SLEEP_TIMER_EVENT为TRUE才使能该事件 #if defined POWER_SAVING if ( events & HAL_SLEEP_TIMER_EVENT ) { halRestoreSleepLevel(); return events ^ HAL_SLEEP_TIMER_EVENT; } if ( events & HAL_PWRMGR_HOLD_EVENT ) { (void)osal_pwrmgr_task_state(Hal_TaskID, PWRMGR_HOLD); (void)osal_stop_timerEx(Hal_TaskID, HAL_PWRMGR_CONSERVE_EVENT); (void)osal_clear_event(Hal_TaskID, HAL_PWRMGR_CONSERVE_EVENT); return (events & ~(HAL_PWRMGR_HOLD_EVENT | HAL_PWRMGR_CONSERVE_EVENT)); } if ( events & HAL_PWRMGR_CONSERVE_EVENT ) { (void)osal_pwrmgr_task_state(Hal_TaskID, PWRMGR_CONSERVE); return events ^ HAL_PWRMGR_CONSERVE_EVENT; } #endif return 0; } ``` <br/> #### **HAL轮询** 在hal\_drivers.c文件中,可以找到Hal\_ProcessPoll()函数,这个函数的主要作用是轮询那些需要快速处理的功能模块,代码如下: ``` /************************************************************************************************** * @fn Hal_ProcessPoll * * @brief This routine will be called by OSAL to poll UART, TIMER... * * @return None **************************************************************************************************/ void Hal_ProcessPoll () { //是否进入低功耗模式 #if defined( POWER_SAVING ) ALLOW_SLEEP_MODE(); #endif //串口 #if (defined HAL_UART) && (HAL_UART == TRUE) HalUARTPoll(); #endif //SPI #if (defined HAL_SPI) && (HAL_SPI == TRUE) HalSpiPoll(); #endif //HID #if (defined HAL_HID) && (HAL_HID == TRUE) usbHidProcessEvents(); #endif } ``` 到这里,已经为读者简单地介绍了HAL的整体结构,接下来将会讲解如何利用HAL来使用LED、按键、串口、显示器和ADC等基本硬件资源。 <br/> <br/> ## **项目定制** * 如需项目定制开发,可扫码添加项目经理好友(注明“**项目定制**”) * 定制范围:**NB-IoT**、**CATn(4G)**、**WiFi**、**ZigBee**、**BLE Mesh**以及**STM32**、**嵌入式Linux**等IoT技术方案 * 善学坊官网:[www.sxf-iot.com](https://www.sxf-iot.com/) ![](https://img.kancloud.cn/ca/73/ca739f92cab220a3059378642e3bd502_430x430.png =200x) * 非项目定制**勿扰**,此处**非**技术支持