/* FreeRTOS头文件 */ #include "FreeRTOS.h" #include "task.h" #include "rgb.h" #include "usart.h" /**************************** 任务句柄 ********************************/ /* * 任务句柄是一个指针,用于指向一个任务,当任务创建好之后,它就具有了一个任务句柄 * 以后我们要想操作这个任务都需要通过这个任务句柄,如果是自身的任务操作自己,那么 * 这个句柄可以为NULL。 */ static TaskHandle_t AppTaskCreate_Handle = NULL;/* 创建任务句柄 */ static TaskHandle_t Test_Task_Handle = NULL;/* LED任务句柄 */ static TaskHandle_t KEY_Task_Handle = NULL;/* KEY任务句柄 */ /********************************** 内核对象句柄 *********************************/ /* * 信号量,消息队列,事件标志组,软件定时器这些都属于内核的对象,要想使用这些内核 * 对象,必须先创建,创建成功之后会返回一个相应的句柄。实际上就是一个指针,后续我 * 们就可以通过这个句柄操作这些内核对象。 * * 内核对象说白了就是一种全局的数据结构,通过这些数据结构我们可以实现任务间的通信, * 任务间的事件同步等各种功能。至于这些功能的实现我们是通过调用这些内核对象的函数 * 来完成的 * */ /******************************* 全局变量声明 ************************************/ /* * 当我们在写应用程序的时候,可能需要用到一些全局变量。 */ /* ************************************************************************* * 函数声明 ************************************************************************* */ static void AppTaskCreate(void);/* 用于创建任务 */ static void Test_Task(void* pvParameters);/* Test_Task任务实现 */ static void KEY_Task(void* pvParameters);/* KEY_Task任务实现 */ static void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; //配置时钟源HSE/HSI/LSE/LSI RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_LSI; RCC_OscInitStruct.HSIState = RCC_HSI_OFF; RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1; // RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_8MHz; //配置HSI输出时钟为8MHz //RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_4MHz; //配置HSI输出时钟为4MHz //RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_16MHz; //配置HSI输出时钟为16MHz //RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_22p12MHz; //配置HSI输出时钟为22.12MHz RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_24MHz; //配置HSI输出时钟为24MHz RCC_OscInitStruct.HSEState = RCC_HSE_ON; //开启HSE RCC_OscInitStruct.HSEFreq = RCC_HSE_16_32MHz; //HSE工作频率范围16M~32M RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.LSIState = RCC_LSI_ON; //开启LSI if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) //初始化RCC振荡器 { // Error_Handler(); } //初始化CPU,AHB,APB总线时钟 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1; //RCC系统时钟类型 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //SYSCLK的源选择为HSE RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; //APH时钟不分频 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; //APB时钟2分频 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) //初始化RCC系统时钟(FLASH_LATENCY_0=24M以下;FLASH_LATENCY_1=48M) { // Error_Handler(); } } /** * @brief 初始化外设相关 */ static void BSP_Init(void) { /* LED 初始化 */ RGB_Init(); /* 串口初始化 */ USART_Config(); } /***************************************************************** * @brief 主函数 * @param 无 * @retval 无 * @note 第一步:开发板硬件初始化 第二步:创建APP应用任务 第三步:启动FreeRTOS,开始多任务调度 ****************************************************************/ int main(void) { BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */ SystemClock_Config(); HAL_Init(); /* 开发板硬件初始化 */ BSP_Init(); /* 创建AppTaskCreate任务 */ xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate, /* 任务入口函数 */ (const char* )"AppTaskCreate",/* 任务名字 */ (uint16_t )configMINIMAL_STACK_SIZE, /* 任务栈大小 */ (void* )NULL,/* 任务入口函数参数 */ (UBaseType_t )1, /* 任务的优先级 */ (TaskHandle_t* )&AppTaskCreate_Handle);/* 任务控制块指针 */ /* 启动任务调度 */ if(pdPASS == xReturn) vTaskStartScheduler(); /* 启动任务,开启调度 */ else return -1; while(1); /* 正常不会执行到这里 */ } /*********************************************************************** * @ 函数名 : AppTaskCreate * @ 功能说明: 为了方便管理,所有的任务创建函数都放在这个函数里面 * @ 参数 : 无 * @ 返回值 : 无 **********************************************************************/ static void AppTaskCreate(void) { BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */ taskENTER_CRITICAL(); //进入临界区 /* 创建Test_Task任务 */ xReturn = xTaskCreate((TaskFunction_t )Test_Task, /* 任务入口函数 */ (const char* )"Test_Task",/* 任务名字 */ (uint16_t )configMINIMAL_STACK_SIZE, /* 任务栈大小 */ (void* )NULL, /* 任务入口函数参数 */ (UBaseType_t )2, /* 任务的优先级 */ (TaskHandle_t* )&Test_Task_Handle);/* 任务控制块指针 */ if(pdPASS == xReturn) { printf("创建Test_Task任务成功!\r\n"); } /* 创建KEY_Task任务 */ xReturn = xTaskCreate((TaskFunction_t )KEY_Task, /* 任务入口函数 */ (const char* )"KEY_Task",/* 任务名字 */ (uint16_t )configMINIMAL_STACK_SIZE, /* 任务栈大小 */ (void* )NULL,/* 任务入口函数参数 */ (UBaseType_t )3, /* 任务的优先级 */ (TaskHandle_t* )&KEY_Task_Handle);/* 任务控制块指针 */ if(pdPASS == xReturn) { printf("创建KEY_Task任务成功!\r\n"); } vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务 taskEXIT_CRITICAL(); //退出临界区 } int test = 0; /********************************************************************** * @ 函数名 : Test_Task * @ 功能说明: Test_Task任务主体 * @ 参数 : * @ 返回值 : 无 ********************************************************************/ static void Test_Task(void* parameter) { (void)parameter; while (1) { test = configCPU_CLOCK_HZ; HAL_GPIO_WritePin(LED4_GPIO_PORT, LED4_PIN, GPIO_PIN_RESET); printf("Test_Task Running,LED1_ON\r\n"); vTaskDelay(pdMS_TO_TICKS(500)); /* 延时500个tick */ HAL_GPIO_WritePin(LED4_GPIO_PORT, LED4_PIN, GPIO_PIN_SET); printf("Test_Task Running,LED1_OFF\r\n"); vTaskDelay(500); /* 延时500个tick */ } } /********************************************************************** * @ 函数名 : Test_Task * @ 功能说明: Test_Task任务主体 * @ 参数 : * @ 返回值 : 无 ********************************************************************/ static void KEY_Task(void* parameter) { (void)parameter; static uint8_t key_flag = 0; while (1) { /* 等待按键按下 */ // if(BSP_PB_GetState(BUTTON_USER)) // { // vTaskDelay(20);/* 延时20个tick */ // continue; // } key_flag = key_flag ? 0 : 1; // if(key_flag) { // printf("挂起Test任务!\n"); // vTaskSuspend(Test_Task_Handle);/* 挂起LED任务 */ // printf("挂起Test任务成功!\n"); // } // // if(!key_flag) {/* K2 被按下 */ // printf("恢复Test任务!\n"); // vTaskResume(Test_Task_Handle);/* 恢复LED任务! */ // printf("恢复Test任务成功!\n"); // } vTaskDelay(20);/* 延时20个tick */ } } #ifdef USE_FULL_ASSERT void assert_failed(uint8_t* file, uint32_t line) { (void)file; (void)line; /* User can add their own implementation here */ while (1) { /* Infinite loop - you could also log the error or trigger a system reset */ } } #endif /********************************END OF FILE****************************/