FreeRTOS程序的一般写法

使用状态机编程,编程过程比较繁琐,因此使用FreeRTOS。
只需要把几个独立的部分拆分成独立的任务,单独编写代码,按照mian方法进行编写即可。

例如,2个LED小灯,闪烁周期不同,LED1亮1s,灭1s循环,LED2亮0.3s,灭1.5s循环。有使用FreeRTOS和状态机2种方法。

状态机方法编写2个不同闪灯周期LED

定义变量

123456
/* USER CODE BEGIN PV */uint8_t LED1State = 0;//状态,0-熄灭,1-点亮uint8_t LED3State = 0;uint32_t led1ChangeTime = 0;//记录上次变换状态的时间uint32_t led3ChangeTime = 0;/* USER CODE END PV */

LED的状态机程序

12345678910111213141516171819202122232425262728293031323334353637383940
/* Private user code ---------------------------------------------------------*//* USER CODE BEGIN 0 */void LED1_StateMachine(void){	uint32_t now = HAL_GetTick();//记录当前时间,到now	//如果上次切换亮灭时间大于1000ms,且当前状态是灭灯状态,那么点亮灯,记录状态,更新时间	if((LED1State == 0) && (now-led1ChangeTime >= 1000))	{		HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);		LED1State = 1;		led1ChangeTime = now;	}	//如果上次切换亮灭时间大于1000ms,且当前状态是亮灯状态,那么熄灯,记录状态,更新时间	if((LED1State == 1) && (now-led1ChangeTime >= 1000))	{		HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);		LED1State = 0;		led1ChangeTime = now;	} }void LED3_StateMachine(void){	uint32_t now = HAL_GetTick();//记录当前时间,到now	//如果上次切换亮灭时间大于1000ms,且当前状态是灭灯状态,那么点亮灯,记录状态,更新时间	if((LED3State == 0) && (now-led3ChangeTime >= 1500))	{		HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);		LED3State = 1;		led3ChangeTime = now;	}	//如果上次切换亮灭时间大于1000ms,且当前状态是亮灯状态,那么熄灯,记录状态,更新时间	if((LED3State == 1) && (now-led3ChangeTime >= 300))	{		HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET);		LED3State = 0;		led3ChangeTime = now;	}}/* USER CODE END 0 */

在while(1)中调用这2个函数

12345678
/* USER CODE BEGIN WHILE */while (1){ LED1_StateMachine(); LED3_StateMachine();  /* USER CODE END WHILE */  /* USER CODE BEGIN 3 */}

FreeRTOS编写2个不同闪灯周期LED

先编写2个LED闪灯的程序。

1234567891011121314151617181920212223242526
/* Private user code ---------------------------------------------------------*//* USER CODE BEGIN 0 */void vLED1Task(void *pvParameters){	while(1)	{		HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);		vTaskDelay(pdMS_TO_TICKS(1000));		HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);		vTaskDelay(pdMS_TO_TICKS(1000));	}	vTaskDelete(NULL);} void vLED3Task(void *pvParameters){	while(1)	{		HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET);		vTaskDelay(pdMS_TO_TICKS(300));		HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET);		vTaskDelay(pdMS_TO_TICKS(1500));	}	vTaskDelete(NULL);}/* USER CODE END 0 */

vTaskDelay(pdMS_TO_TICKS(1000));的作用是延时1000ms

在主程序中调用

12345
/* USER CODE BEGIN 2 */xTaskCreate(vLED1Task, "LED1", 128, NULL, 1, NULL);xTaskCreate(vLED3Task, "LED3", 128, NULL, 1, NULL);vTaskStartScheduler();//启用调度器/* USER CODE END 2 */

xTaskCreate的作用就是创建任务,相当于是把任务代码交给调度器。

FreeRTOS程序的一般写法

123456789101112
// 任务函数的一般写法// 任务函数使用void类型的返回值,但是有一个void*类型的参数void vTask1(void *pvParameters){      // 编程方式类似于main()方法,一般写一个无限循环     while(1)     {          // 使用vTaskDelay()而不使用HAL_Delay()进行延迟     }     // 坚决不能写return!     vTaskDelete(NULL); //一旦退出需删除自身}
1234567891011121314151617
int main(void){      //一些底层的初始化代码放这里      .........       //先创建任务      xTaskCreate(vTask1, "Task1", .....); //任务1      xTaskCreate(vTask2, "Task2", .....); //任务2       //再启动调度器      vTaskStartScheduler();       //无限循环      while (1) //代码不会执行到这里,除非因创建空闲任务或者定时器任务失败而退出      {      }}

在FreeRTOS中,延时函数不使用HAL_Delay,比如延时300msvTaskDelay(pdMS_TO_TICKS(300));

🔍 ×