网页游戏网站斗地主,深圳找工作哪个网站好,智慧团建网址,定制开发一个app需要多少钱目录 一、任务管理方式二、任务堆栈溢出检测三、二值信号量#xff08;任务同步#xff09;四、计数信号量五、互斥信号量六、队列 一、任务管理方式 1.任务创建成功后会添加到就绪链表中#xff0c;开启调度器#xff0c;此时任务调度器会去就绪链表中找优先级最高的任务执… 目录 一、任务管理方式二、任务堆栈溢出检测三、二值信号量任务同步四、计数信号量五、互斥信号量六、队列 一、任务管理方式 1.任务创建成功后会添加到就绪链表中开启调度器此时任务调度器会去就绪链表中找优先级最高的任务执行。若优先级一样则按照创建任务的先后来执行。 2.任务被执行时就会变为运行态时该任务就会从就绪链表删除若此时执行到任务中的vTaskDelay等函数时该任务就会被挪到阻塞链表中。调度器此时会去执行其他任务。 3.当阻塞解除时该任务会从阻塞链表中删掉移动到就绪链表中。若解除任务的优先级很高那么此时该任务会直接打断cpu正在执行的任务抢占位置去执行自己。
二、任务堆栈溢出检测
详情见FreeRTOS中的任务堆栈溢出检测机制 主要作用就是方便调试工程做完之后没问题了就关掉 写检测函数之前需要更改宏定义我们采用的是第二种堆栈检测方法。
void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{printf(任务%s-栈溢出\r\n,pcTaskName);printf(任务剩余空间%d\r\n,(int)uxTaskGetStackHighWaterMark(xTask));while(1)//栈溢出时卡死到钩子函数中{}
}本质上就是一个钩子函数在任务上下文切换的时候做检测具有一定的滞后性需要在任务发生上下文切换时才会进行任务堆栈溢出时并不能马上检测到问题。 但大多常见情况下这种检测机制依然是非常实用的功能可以帮助用户减少代码中的错误并提高应用程序代码的质量。
三、二值信号量任务同步
任务同步任务B需要等待任务A执行完再去执行。 二值信号量也一样谁拥有谁执行比如任务B需要获得信号量才能执行那么他就要等待A给他一个信号量然后再去执行。
1.添加头文件
#include semphr.h2.创建一个SemaphoreHandle_t 类型的二值信号量句柄
SemaphoreHandle_t Binary;3.主函数创建二值信号量返回值为该信号量的句柄 //创建一个二值信号量Binary xSemaphoreCreateBinary();4.使用函数xSemaphoreGive给出二值信号量参数为二值信号量的句柄
xSemaphoreGive(Binary)5.使用xSemaphoreTake函数接收二值信号量参数为句柄和超时时间也可填写portMAX_DELAY表示死等 若返回值为pdTRUE则表示获取到该信号量。
if(xSemaphoreTake(Binary,1000) pdTRUE) {printf(按键按下获取到信号量\r\n);}完整代码
//包含支持stm32f1系列的头文件
#include stm32f10x.h
#include led.h
#include delay.h
#include usart.h
#include key.h
#include adc.h
#include kqm.h
#include dht11.h//使用FreeRTOS相关头文件之前先包含FreeRTOS.h
#include FreeRTOS.h
#include task.h
#include semphr.h
/********************信号量句柄***********************/
SemaphoreHandle_t Binary;//传感器任务
TaskHandle_t Sensor_TaskHandle;
void Sensor_Task(void *p)
{while(1){taskENTER_CRITICAL();//进入临界区Dht11ReadData();//DHT11读取函数不能被打断taskEXIT_CRITICAL();//退出临界区KQMDealData();//该函数的调用时间小于等于1秒ADC_DataFliter();//ADC均值滤波vTaskDelay(1000);//阻塞1秒}
}//任务本体 闪灯任务
TaskHandle_t LED_TaskHandle;
void LED_Task(void *p)
{uint8_t i0;while(1){if(xSemaphoreTake(Binary,1000) pdTRUE) {printf(按键按下获取到信号量\r\n);}else{printf(获取到信号量等待超时\r\n);}i;printf(i%d\r\n,i);Led_Toggle(1);//printf(LED任务剩余空间%d\r\n,(int)uxTaskGetStackHighWaterMark(NULL));
// Delay_nms(200);//也能延时但是会一直占用CPU//也是延时200ms但是FreeRTOS提供的函数有阻塞机制能够让任务从运行态变为阻塞态vTaskDelay(200);}
}
//任务本体 按键任务
TaskHandle_t KEY_TaskHandle;
void KEY_Task(void *p)
{while(1){switch(key_getvalue()){case 1:vTaskSuspend(LED_TaskHandle);break;case 2:vTaskResume(LED_TaskHandle);break;case 3:xSemaphoreGive(Binary);break;case 4:break;}vTaskDelay(10);//MS级别的延时带有阻塞性质任务会从运行态变为阻塞态}
} int main()
{Led_Init();//初始化LEDKey_init();//初始化按键Usart1_Config();//初始化串口1ADC_Config();//初始化ADCKqm_U4Config();//初始化KQMDHT11_Mode();//初始化DHT11BaseType_t Ret pdPASS;//创建一个二值信号量Binary xSemaphoreCreateBinary();//1,如何创建一个任务Ret xTaskCreate(Sensor_Task,Sensor_Task,200,NULL,1,Sensor_TaskHandle);Ret xTaskCreate(LED_Task, //创建任务的任务函数名LED1_Toggle,//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL3,//任务优先级LED_TaskHandle);//任务的句柄用于后边删除挂起任务if(Ret pdPASS){printf(LED_Task创建完成\r\n);}Ret xTaskCreate(KEY_Task, //创建任务的任务函数名KEY_Task,//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL2,//任务优先级KEY_TaskHandle);//任务的句柄用于后边删除挂起任务if(Ret pdPASS){printf(KEY_Task创建完成\r\n);}printf(开启FreeRTOS调度器\r\n);//调度器启动完成之后FreeRTOS会获取CPU控制权会按照任务优先级执行创建的任务vTaskStartScheduler();while(1){ }
}void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{printf(任务%s-栈溢出\r\n,pcTaskName);printf(任务剩余空间%d\r\n,(int)uxTaskGetStackHighWaterMark(xTask));while(1)//栈溢出时卡死到钩子函数中{}
}
四、计数信号量
一般在资源有限的情况下使用如停车场坐位传感器的访问等。 计数信号量测试按键和灯按键按下几次灯翻转几次。 1.创建计数信号量的句柄
SemaphoreHandle_t Count_Handle;//计数信号量句柄2.创建计数信号量 返回值为该信号量的句柄参数为最大信号量为多少和初始信号量有几个。
Count_Handle xSemaphoreCreateCounting(10,5);//创建计数信号量3.给出信号量 参数为计数信号量的句柄
xSemaphoreGive(Count_Handle);4.消耗信号量 参数和二值信号量一样一个是对应的句柄一个是超时。 成功返回pdTRUE。
if(xSemaphoreTake(Count_Handle,portMAX_DELAY) pdTRUE) 完整代码
#include stm32f10x.h
#include led.h
#include delay.h
#include delay.h
#include string.h
#include pwm.h
#include adc.h
#include su03t.h
#include dht11.h
#include kqm.h
#include usart.h
#include key.h//使用FreeRtos相关头文件之前一定要先包含这个#include FreeRtos.h
#include FreeRtos.h
#include task.h
#include semphr.h
#include queue.hTaskHandle_t Deal_TaskHandle;//数据处理
SemaphoreHandle_t Binary;//二值信号量句柄
SemaphoreHandle_t Count_Handle;//计数信号量句柄
TaskHandle_t LED_TaskHandle;//任务本体 闪灯任务
TaskHandle_t KEY_TaskHandle;//任务本体 按键任务
void Data_Task(void *p)
{while(1){Get_Smoke_Light_MidValue();DHT11_ReadData();vTaskDelay(300);KQM_DealData();Su03tDealData();}
}void KEY_Task(void *p)
{while(1){switch(key_getvalue()){case 1:vTaskSuspend(LED_TaskHandle);break;case 2:vTaskResume(LED_TaskHandle);break;case 3:xSemaphoreGive(Count_Handle);printf(给一个计数信号量\r\n);break;case 4:break;}vTaskDelay(10);//MS级别的延时带有阻塞性质任务会从运行态变为阻塞态}
}
void LED_Task(void *p)
{uint8_t i0;while(1){if(xSemaphoreTake(Count_Handle,portMAX_DELAY) pdTRUE) {printf(消耗计数信号量\r\n);i;printf(i%d\r\n,i);Led_Toggle(1);vTaskDelay(1000);}}
}int main()
{RGBpwm_Config();Kqm_U4Config();Su03t_U5Config();DHT11_Config(); Adc_Config();Led_Init();key_Init();Usart1_Config();BaseType_t Ret pdPASS;
// Ret xTaskCreate(Data_Task,DealData,300,NULL,2,Deal_TaskHandle);
// if(RetpdPASS)
// {
// printf(数据创建成功\r\n);
// }Binary xSemaphoreCreateBinary();//计数信号量最大值 初始时有多少个信号量可用Count_Handle xSemaphoreCreateCounting(10,5);//创建计数信号量Ret xTaskCreate(LED_Task, //创建任务的任务函数名LED1_Toggle,//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL3,//任务优先级LED_TaskHandle);//任务的句柄用于后边删除挂起任务if(Ret pdPASS){printf(LED_Task创建完成\r\n);}Ret xTaskCreate(KEY_Task, //创建任务的任务函数名KEY_Task,//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL2,//任务优先级KEY_TaskHandle);//任务的句柄用于后边删除挂起任务if(Ret pdPASS){printf(KEY_Task创建完成\r\n);}printf(开启FreeRTOS调度器成功\r\n);vTaskStartScheduler();while(1){}
}void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{printf(任务%s-栈溢出\r\n,pcTaskName);printf(任务剩余空间%d\r\n,(int)uxTaskGetStackHighWaterMark(xTask));while(1)//栈溢出时卡死到钩子函数中{}
}
五、互斥信号量
用于共享资源的保护 资源A是共享资源此时如果被任务1使用那么就不能被其他任务使用。 任务1小A你让我使用了可就不能让别人使用了哦 ~ 1.创建句柄
SemaphoreHandle_t Mutex_HandleNULL;2.创建互斥信号量 返回值为互斥信号量的句柄
Mutex_Handle xSemaphoreCreateMutex();//创建互斥信号量3.获取信号给出信号 保护printf使printf能够完整打印。
void MyPrintf(char *p)
{xSemaphoreTake(Mutex_Handle,portMAX_DELAY);//获取信号量printf(%s,p);xSemaphoreGive(Mutex_Handle);//还回去
}完整代码
#include delay.h
#include FreeRTOS.h
#include task.h
#include semphr.h
#include usart.h
#include stdio.h
#include led.h
#include key.h
#include dht.h
#include adc.h
#include kqm.h/*******************信号量句柄*********************/
SemaphoreHandle_t Binary_HandleNULL;
SemaphoreHandle_t Count_HandleNULL;
SemaphoreHandle_t Mutex_HandleNULL;
/*******************互斥信号量保护资源*********************/
void MyPrintf(char *p)
{xSemaphoreTake(Mutex_Handle,portMAX_DELAY);//获取信号量printf(%s,p);xSemaphoreGive(Mutex_Handle);//还回去
}/*******************LED任务*********************/
TaskHandle_t LEDtask_Handle NULL;
//任务函数本身
void LED_Task(void * p)
{MyPrintf(LED任务创建成功\r\n);LED_Config();BEEP_Config();while(1){ if(xSemaphoreTake(Count_Handle,portMAX_DELAY) pdTRUE){MyPrintf(LED反转\r\n);LED1_Toggle();}else{MyPrintf(超时结束\r\n);}vTaskDelay(500);//控制任务的执行周期}
}
/*******************按键任务*********************/
TaskHandle_t KEYtask_Handle NULL;
//任务函数本身
void KEY_Task(void * p)
{MyPrintf(按键任务创建成功\r\n);KEY_Config();while(1){ switch(KEY_Scan()){case 1:BEEP_Toggle(); break;case 2:
// xSemaphoreGive(Binary_Handle);//给出二值信号量if(xSemaphoreGive(Count_Handle) pdTRUE)//给出计数信号量{MyPrintf(成功给出计数信号量\r\n);}else{MyPrintf(信号量已满\r\n);}break;case 3: break;case 4:vTaskDelete(LEDtask_Handle);break;}vTaskDelay(10);}
}
/*******************传感器任务*********************/
TaskHandle_t Senortask_Handle NULL;
//任务函数本身
void Senor_Task(void * p)
{MyPrintf(传感器任务创建成功\r\n);uint8_t cnt 0;ADC_Config();//初始化ADCUART4_Config();//初始化KQM传感器while(1){ cnt;if(KQM_Anlyze() 0){printf(CO2:%d\r\n,kqmdata.CO2);}else{MyPrintf(KQM数据错误\r\n);}if(cnt3){cnt 0;taskENTER_CRITICAL();//进入临界区if(DHT11_ReadData() 0){printf(温度数据%.2f 湿度数据%d\r\n,TEM,HUM);}else{MyPrintf(温湿度数据获取失败\r\n);}taskEXIT_CRITICAL();//退出临界区 }vTaskDelay(1000);}
}
int main(void)
{USART_Config();BaseType_t Ret pdPASS;Binary_Handle xSemaphoreCreateBinary();//创建二值信号量// 计数信号量最大值 初始时有多少个信号量可用Count_Handle xSemaphoreCreateCounting(10,5);//创建计数信号量Mutex_Handle xSemaphoreCreateMutex();//创建互斥信号量//动态创建任务Ret xTaskCreate(LED_Task,//任务函数的入口也就是函数名LED_Task,//任务别名方便FreeRTOS管理100,//任务分配的堆栈空间 32单片机就是50*4 200字节NULL,//任务函数的参数无参数就写NULL1,//任务优先级LEDtask_Handle);//任务的句柄指针,可以用来管理任务if(Ret pdPASS){printf(LED任务创建成功\r\n);}//动态创建任务Ret xTaskCreate(KEY_Task,//任务函数的入口也就是函数名KEY_Task,//任务别名方便FreeRTOS管理100,//任务分配的堆栈空间 32单片机就是50*4 200字节NULL,//任务函数的参数无参数就写NULL1,//任务优先级KEYtask_Handle);//任务的句柄指针,可以用来管理任务if(Ret pdPASS){printf(按键任务创建成功\r\n);}Ret xTaskCreate(Senor_Task,//任务函数的入口也就是函数名Senor_Task,//任务别名方便FreeRTOS管理100,//任务分配的堆栈空间 32单片机就是50*4 200字节NULL,//任务函数的参数无参数就写NULL2,//任务优先级Senortask_Handle);//任务的句柄指针,可以用来管理任务if(Ret pdPASS){printf(传感器任务创建成功\r\n);}vTaskStartScheduler();//启动调度器printf(调度器启动失败\r\n);while (1){}
}//函 数 功 能任务栈溢出钩子函数调试阶段用
void vApplicationStackOverflowHook(TaskHandle_t xTask,signed char *pcTaskName)
{printf(任务#%s #栈溢出\r\n,pcTaskName);printf(任务栈空间剩余%d\r\n,uxTaskGetStackHighWaterMark(xTask));while(1){}
}
六、队列 主要用于任务间数据传输采用FIFO先进先出模式新数据通常发到队列后面但也可以发到队列前面。 1.创建句柄
QueueHandle_t Queue;2.创建队列
//创建队列 长度为10 队列中每个数据的大小2字节Queue xQueueCreate(10,2);3.接收数据 参数1要发送数据的目标队列的句柄。 参数2指向要发送数据的指针。 参数3发送数据时等待的最长时间 返回值 pdPASS数据成功发送到队列。 errQUEUE_FULL队列已满无法发送数据。
if(xQueueReceive(Queue,buff2,100)pdTRUE)4.发送数据
if(xQueueSend(Queue,buff,100) pdTRUE)完整代码
//包含支持stm32f1系列的头文件
#include stm32f10x.h
#include led.h
#include delay.h
#include usart.h
#include key.h
#include adc.h
#include kqm.h
#include dht11.h//使用FreeRTOS相关头文件之前先包含FreeRTOS.h
#include FreeRTOS.h
#include task.h
#include semphr.h
/********************信号量句柄***********************/
SemaphoreHandle_t Binary;
SemaphoreHandle_t Count;
SemaphoreHandle_t Mutex;
/********************队列句柄***********************/
QueueHandle_t Queue;
QueueHandle_t KqmQueue;
/*********************互斥锁保护Printf****************/
void MyPrintf(char *p)
{xSemaphoreTake(Mutex,portMAX_DELAY);printf(%s,p);xSemaphoreGive(Mutex);
}//传感器任务
TaskHandle_t Sensor_TaskHandle;
void Sensor_Task(void *p)
{uint8_t recv[8] {0};MyPrintf(Sensor Task Begin\r\n);while(1){if(xQueueReceive(KqmQueue,recv,100)pdTRUE){printf(接受数据%x %x %x %x %x %x %x %x\r\n,recv[0],recv[1],\recv[2],recv[3],recv[4],recv[5],recv[6],recv[7]);}else{printf(队列为空接收失败\r\n);}taskENTER_CRITICAL();//进入临界区Dht11ReadData();//DHT11读取函数不能被打断ADC_DataFliter();//ADC均值滤波taskEXIT_CRITICAL();//退出临界区vTaskDelay(1000);//阻塞1秒}
}//任务本体 闪灯任务
TaskHandle_t LED_TaskHandle;
void LED_Task(void *p)
{uint8_t i0;MyPrintf(LED_Task Begin\r\n);while(1){if(xSemaphoreTake(Count,portMAX_DELAY) pdTRUE) {MyPrintf(按键按下获取到信号量\r\n);}else{MyPrintf(获取到信号量等待超时\r\n);}printf(i%d\r\n,i);Led_Toggle(1);//printf(LED任务剩余空间%d\r\n,(int)uxTaskGetStackHighWaterMark(NULL));
// Delay_nms(200);//也能延时但是会一直占用CPU//也是延时200ms但是FreeRTOS提供的函数有阻塞机制能够让任务从运行态变为阻塞态vTaskDelay(1000);}
}
//任务本体 按键任务
TaskHandle_t KEY_TaskHandle;
void KEY_Task(void *p)
{uint8_t buff[2] {0xAA,0x55};uint8_t buff2[2] {0};MyPrintf(KEY_Task Begin\r\n);while(1){switch(key_getvalue()){case 1:if(xQueueSend(Queue,buff,100) pdTRUE){printf(发送成功\r\n);}else{printf(队列已满发送失败\r\n);}break;case 2:if(xQueueReceive(Queue,buff2,100)pdTRUE){printf(接受数据%x %x\r\n,buff2[0],buff2[1]);}else{printf(队列为空接收失败\r\n);}break;case 3:xSemaphoreGive(Count);break;case 4: break;}vTaskDelay(10);//MS级别的延时带有阻塞性质任务会从运行态变为阻塞态}
} int main()
{Led_Init();//初始化LEDKey_init();//初始化按键Usart1_Config();//初始化串口1ADC_Config();//初始化ADCKqm_U4Config();//初始化KQMDHT11_Mode();//初始化DHT11BaseType_t Ret pdPASS;//创建一个二值信号量Binary xSemaphoreCreateBinary();//创建一个计数信号量Count xSemaphoreCreateCounting(10,5);//创建互斥锁Mutex xSemaphoreCreateMutex();//创建队列 长度为10 队列中每个数据的大小2字节Queue xQueueCreate(10,2);KqmQueue xQueueCreate(1,8);//1,如何创建一个任务Ret xTaskCreate(Sensor_Task,Sensor_Task,200,NULL,1,Sensor_TaskHandle);
// Ret xTaskCreate(LED_Task, //创建任务的任务函数名
// LED1_Toggle,//任务名字
// 100,//任务栈深度。32位单片机*4
// NULL,//创建任务时传递参数,没有就给NULL
// 1,//任务优先级
// LED_TaskHandle);//任务的句柄用于后边删除挂起任务
// if(Ret pdPASS){
// printf(LED_Task创建完成\r\n);
// }Ret xTaskCreate(KEY_Task, //创建任务的任务函数名KEY_Task,//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL1,//任务优先级KEY_TaskHandle);//任务的句柄用于后边删除挂起任务if(Ret pdPASS){printf(KEY_Task创建完成\r\n);}printf(开启FreeRTOS调度器\r\n);//调度器启动完成之后FreeRTOS会获取CPU控制权会按照任务优先级执行创建的任务vTaskStartScheduler();printf(开启FreeRTOS调度器成功\r\n);while(1){ }
}void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{printf(任务%s-栈溢出\r\n,pcTaskName);printf(任务剩余空间%d\r\n,(int)uxTaskGetStackHighWaterMark(xTask));while(1)//栈溢出时卡死到钩子函数中{}
}