/* 非阻塞性延时函数
arg:需要延迟多少tick
portTICK_PERIOD_MS:表1个tick的时间,arduino里通常为1ms
*/
vTaskDelay(delaytime/portTICK_PERIOD_MS);
/* 创建任务
返回值:如果任务创建成功,返回pdPASS
*/
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 传递需要任务处理的函数的地址
const char * const pcName, // 确定该任务的名字
const configSTACK_DEPTH_TYPE usStackDepth, // 任务占内存大小(字节)
void * const pvParameters, // 传入到处理函数的参数
UBaseType_t uxPriority, // 优先级,s数值越大优先级越高
TaskHandle_t * const pxCreatedTask ) // 对任务操作,一般填NULL
// 杀掉该任务(进程)
vTaskDelete( xTaskHandle xTaskToDelete );
在下文中使用到了句柄这个概念,我的理解是:在多线程任务中,如果我要使用某个对象,那么需要在内存中开辟空间,每个线程或任务分配独立的对象副本,这会导致内存的浪费。为了节约资源,从而引入句柄。通过使用句柄,程序可以在内存中只存储一个对象的引用或指针,而不是为每个线程或任务创建独立的对象副本。这样,多个线程或任务可以通过共享同一个对象引用而访问同一个对象,从而节省内存空间。那么此刻的句柄就可以理解为一个地址簿,记录共享对象的内存地址。
// MUTEX 全局共享变量防止竞争冒险操作
SemaphoreHandle_t xxx; // 创建xxx句柄
xxx = xSemaphoreCreateMutex(); //创建MUTEX
xSemaphoreTake(xxx, timeOut); // 请求权限,timeOut为请求时间
xSemaphoreGive(xMutexMPU6050); // 释放权限、
// 这里可以用if语句来尝试请求权限,如果请求成功,则执行{}内操作。
// xxx就像一把钥匙,拥有钥匙的人才能访问房间
上面这段代码的理解:
句柄(Handle)
句柄可以看作是一个“标签”或“指针”,它指向了一个具体的对象(在这个案例中是互斥量对象)。句柄本身不包含对象的全部数据,而只是指向对象在内存中的位置或提供了一种访问对象的方式。
互斥量(Mutex)
互斥量是一种同步原语,用于保护共享资源,防止多个任务或线程同时访问,造成数据混乱。
图文解释
想象一下你有一个保险箱(代表共享资源),多个人(代表多个任务或线程)都想要打开这个保险箱取东西。为了确保一次只有一个人可以打开保险箱,你使用了一把锁(代表互斥量)来锁住保险箱。
现在,每个人都知道保险箱的位置,但他们不知道锁的密码或钥匙在哪里。这时,管理员(代表操作系统或RTOS)给每个人分发了一张纸条(代表句柄),纸条上写着锁的密码或指示了钥匙的位置。
图示说明:
保险箱:代表共享资源,需要被保护以防止同时访问。
锁:代表互斥量,用于锁住保险箱。
人:代表多个任务或线程,想要访问保险箱。
纸条:代表句柄,提供了访问锁(互斥量)的方法。
在这个例子中,每个人通过他们手中的纸条(句柄)找到了锁的密码或钥匙,然后依次打开保险箱。当一个人打开保险箱时,其他人必须等待,直到保险箱再次被锁住,下一个人才可以使用他的纸条来打开保险箱。
这就是句柄在互斥量中的作用:它提供了一种机制,让任务或线程能够有序地访问共享资源,确保数据的一致性和系统的稳定性。
// 将任务放入核心0,最后一个参数表放入核心多少
xTaskCreatePinnedToCore(task1, "Task1", 1024, NULL, 1, NULL,0);
// 查看当前执行任务在核心几
Serial.println(xPortGetCoreID());
// 绝对频率的绝对延时
TickType_t xxx = xTaskGetTickCount(); // xxx装入此时的tick计数值
const TickType_t xFrequency = 3000; // 间隔 3000 ticks = 3 seconds
vTaskDelayUntil(&xxx, xFrequency); // 传入计数值,和频率时间。从xxx开始延迟3s
//软件定时器
TimerHandle_t xxx; // 创建句柄
/*创建一个定时器
返回值:一个句柄,用于后续引用和操作这个定时器。
*/
TimerHandle_t xTimerCreate(
const char * const pcTimerName, // 定时器的名称,用于标识定时器。
TickType_t xTimerPeriodInTicks, // 定时器的周期,以时钟节拍为单位。
UBaseType_t uxAutoReload, // 指定定时器是否自动重载。如果设置为pdTRUE,则当定时
// 器达到其周期时,它将自动重置并重新开始计时。如果设置为
// pdFALSE,则定时器只会在达到其周期时触发一次回调函数。
void * pvTimerID, // 一个指针,存储与定时器关联的标识符。可以设置为 NULL。
TimerCallbackFunction_t pxCallbackFunction // 一个指向回调函数的指针,该函数将在定时器达到
// 其周期时被调用。
);
//回调函数例子。xTimer:定时器的句柄,用于标识被触发的定时器。
void timerCallbackFunction(TimerHandle_t xTimer);
//开始定时
BaseType_t xTimerStart( TimerHandle_t xTimer, // 要启动的定时器的句柄
TickType_t xTicksToWait ); // 等待启动操作的时间,以时钟节拍为单位。
// 如果设置为0,则函数会立即返回而不等待。