最大的用处就是方便我安排初始化函数和其它函数的等待时机。
//先定义事件组各个位是什么意思
typedef enum {
SYSTEM_INIT_EVENT_SD_MOUNTEDBIT_BIT_POS = 0,
SYSTEM_INIT_EVENT_USB_CONNECTED_BIT_POS = 1,
SYSTEM_INIT_EVENT_ADC_READY_BIT_POS = 2,
SYSTEM_INIT_EVENT_EUBF_READY_BIT_POS = 3,
SYSTEM_INIT_EVENT_TIM3_READY_BIT_POS = 4,
SYSTEM_INIT_EVENT_USART1_READY_BIT_POS = 5,
SYSTEM_INIT_EVENT_SDRAM_READY_BIT_POS = 6,
SYSTEM_INIT_EVENT_LCD_READY_BIT_POS = 7,
SYSTEM_INIT_EVENT_DMA2D_READY_BIT_POS = 8
} SystemInitEventGroupPos_t;
typedef enum
{
//SD卡挂载完成
SYSTEM_INIT_EVENT_SD_MOUNTED = 1<<SYSTEM_INIT_EVENT_SD_MOUNTEDBIT_BIT_POS,
//USB连接完成
SYSTEM_INIT_EVENT_USB_CONNECTED = 1<<SYSTEM_INIT_EVENT_USB_CONNECTED_BIT_POS,
//ADC初始化完成
SYSTEM_INIT_EVENT_ADC_READY = 1<<SYSTEM_INIT_EVENT_ADC_READY_BIT_POS,
//EUBF初始化完成
SYSTEM_INIT_EVENT_EUBF_READY = 1<<SYSTEM_INIT_EVENT_EUBF_READY_BIT_POS,
//TIM3初始化完成
SYSTEM_INIT_EVENT_TIM3_READY = 1<<SYSTEM_INIT_EVENT_TIM3_READY_BIT_POS,
//USART1初始化完成
SYSTEM_INIT_EVENT_USART1_READY = 1<<SYSTEM_INIT_EVENT_USART1_READY_BIT_POS,
//SDRAM初始化完成
SYSTEM_INIT_EVENT_SDRAM_READY = 1<<SYSTEM_INIT_EVENT_SDRAM_READY_BIT_POS,
//LCD初始化完成
SYSTEM_INIT_EVENT_LCD_READY = 1<<SYSTEM_INIT_EVENT_LCD_READY_BIT_POS,
//DMA2D初始化完成
SYSTEM_INIT_EVENT_DMA2D_READY = 1<<SYSTEM_INIT_EVENT_DMA2D_READY_BIT_POS,
} SystemInitEventGroupMask_t;
/* 系统初始化任务:负责按顺序初始化各个硬件外设和软件模块
* 功能说明:
* 1. 初始化SDRAM外部存储器
* 2. 初始化LCD显示屏和DMA2D硬件加速模块
* 3. 初始化USART1串口通信
* 4. 初始化SD卡文件系统
* 5. 初始化EUBF字体库系统
* 6. 启动ADC1模数转换
* 7. 启动定时器3
*
* 事件组机制:
* - 使用xSystemInitEventGroupHandle事件组跟踪各模块初始化状态
* - 每完成一个模块初始化,调用xEventGroupSetBits()设置对应标志位
* - 当所有模块初始化完成后,调用vTaskDelete(NULL)删除当前任务
*
* 参数:
* argument - FreeRTOS任务参数(本任务未使用)
*/
void AppTask_SYS_INIT(void *argument)
{
/* USER CODE BEGIN AppTask_SYS_INIT */
//============================== 初始化 SDRAM =============================
SDRAM_InitSequence();
xEventGroupSetBits(xSystemInitEventGroupHandle, SYSTEM_INIT_EVENT_SDRAM_READY);
// ============================= 初始化 LCD 屏幕 =============================
lcd_init();
lcd_clear(BLACK);
xEventGroupSetBits(xSystemInitEventGroupHandle, SYSTEM_INIT_EVENT_LCD_READY);
lcd_dma2d_init(); // 初始化DMA2D硬件加速模块,用于LCD图形绘制加速
lcd_dma2d_clear(BLACK);
xEventGroupSetBits(xSystemInitEventGroupHandle, SYSTEM_INIT_EVENT_DMA2D_READY);
// ============================= 初始化USART1 =============================
MyUSART_Init();
xEventGroupSetBits(xSystemInitEventGroupHandle, SYSTEM_INIT_EVENT_USART1_READY);
// ============================= 初始化EUBF =============================
EUBF_Port_Config_t font_sd_config = {
.Open = SD_FastSlot_Open_UTF8, // 文件打开接口,支持UTF-8编码
.Close = (void (*)(int8_t))SD_FastSlot_Close, // 文件关闭接口,类型转换避免编译警告
.ReadAt = SD_FastSlot_Read, // 文件随机读取接口
.RootPath = "0:/" // SD卡根目录路径
};
EUBF_Init(&font_sd_config);
xEventGroupSetBits(xSystemInitEventGroupHandle, SYSTEM_INIT_EVENT_EUBF_READY);
//============================== 启动ADC1转换 =============================
HAL_ADC_Start_IT(&hadc1);
xEventGroupSetBits(xSystemInitEventGroupHandle, SYSTEM_INIT_EVENT_ADC_READY);
//============================== 启动定时器3 =============================
HAL_TIM_Base_Start(&htim3);
xEventGroupSetBits(xSystemInitEventGroupHandle, SYSTEM_INIT_EVENT_TIM3_READY);
/* Infinite loop */
for(;;)
{
// ============================= 初始化SD卡 =============================
SD_Mount_StateMachine();
if(SD_Is_Mounted() == 1){
// SD卡挂载成功,在LCD上显示实验标题
lcd_dma2d_show_eubf_str(0, 32, (char*)"事件组实验", "ZCOOL QingKe HuangYou", 25, WHITE);
lcd_dma2d_update_screen();
xEventGroupSetBits(xSystemInitEventGroupHandle, SYSTEM_INIT_EVENT_SD_MOUNTED);
}
//============================== 检查所有模块初始化状态 =============================
if(xEventGroupGetBits(xSystemInitEventGroupHandle) ==
(SYSTEM_INIT_EVENT_SDRAM_READY |
SYSTEM_INIT_EVENT_LCD_READY |
SYSTEM_INIT_EVENT_DMA2D_READY |
SYSTEM_INIT_EVENT_USART1_READY |
SYSTEM_INIT_EVENT_TIM3_READY |
SYSTEM_INIT_EVENT_SD_MOUNTED |
SYSTEM_INIT_EVENT_EUBF_READY |
SYSTEM_INIT_EVENT_ADC_READY)){
// 所有模块初始化完成,删除当前任务以释放系统资源
vTaskDelete(NULL);
}
osDelay(1);
}
/* USER CODE END AppTask_SYS_INIT */
}像这样初始化好一个外设就置相应位为 1,然后我们再需要用到外设资源的地方加上等待条件(程序内容和信号量实验相同,省略):
void App_Task_showADC(void *argument)
{
/* USER CODE BEGIN App_Task_showADC */
//等待ADC初始化完成、定时器3初始化完成、SD卡挂载完成、EUBF初始化完成、DMA2D初始化完成、LCD初始化完成
xEventGroupWaitBits(xSystemInitEventGroupHandle,
SYSTEM_INIT_EVENT_ADC_READY |
SYSTEM_INIT_EVENT_TIM3_READY |
SYSTEM_INIT_EVENT_SD_MOUNTED |
SYSTEM_INIT_EVENT_EUBF_READY |
SYSTEM_INIT_EVENT_DMA2D_READY |
SYSTEM_INIT_EVENT_LCD_READY,
pdFALSE,
pdTRUE,
portMAX_DELAY);
// 等待应用启动完成(多任务同步)
//这里就不定义了,懒了
xEventGroupSync(xAppStartEventGroupHandle,
1 << 0, // APP_START_EVENT_SHOW_ADC_READY
1 << 0|1 << 1, // APP_START_EVENT_SHOW_ADC_READY | APP_START_EVENT_SHOW_CHECKIN_READY
portMAX_DELAY);
/* Infinite loop */
for(;;)
{
//省略内容
osDelay(250);
}
/* USER CODE END App_Task_showADC */
}void App_Task_CheckIn(void *argument)
{
/* USER CODE BEGIN App_Task_CheckIn */
//等待SD卡挂载完成、EUBF初始化完成、DMA2D初始化完成、LCD初始化完成
xEventGroupWaitBits(xSystemInitEventGroupHandle,
SYSTEM_INIT_EVENT_SD_MOUNTED |
SYSTEM_INIT_EVENT_EUBF_READY |
SYSTEM_INIT_EVENT_DMA2D_READY |
SYSTEM_INIT_EVENT_LCD_READY,
pdFALSE,
pdTRUE,
portMAX_DELAY);
// 等待应用启动完成(多任务同步)
xEventGroupSync(xAppStartEventGroupHandle,
1 << 1, // APP_START_EVENT_SHOW_CHECKIN_READY
1 << 0|1 << 1, // APP_START_EVENT_SHOW_ADC_READY | APP_START_EVENT_SHOW_CHECKIN_READY
portMAX_DELAY);
//省略内容
/* Infinite loop */
for(;;)
{
//省略内容
osDelay(100);
}
/* USER CODE END App_Task_CheckIn */
}