多任务

不传递参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
void task1(void *pt) {
pinMode(23, OUTPUT);
while (1) {
digitalWrite(23, !digitalRead(23));
/*
Tick to Time
pdMS_TO_TICKS
portTICK_PERIOD_MS
vTaskDelay(pdMS_TO_TICKS(1000));
vTaskDelay(1000/portTICK_PERIOD_MS);
*/
vTaskDelay(1000); //注意 是 ticks的数量 不是时间
}
}

void task2(void *pt) {
pinMode(21, OUTPUT);
while (1) {
digitalWrite(21, !digitalRead(21));
vTaskDelay(3000);
}
}


void setup() {
Serial.begin(9600);
Serial.print("ESP32 Tick Period - ");
Serial.print(portTICK_PERIOD_MS);
Serial.println("ms");

if (xTaskCreate(task1,
"Blink 23",
1024,
NULL,
1,
NULL) == pdPASS)
Serial.println("Task1 Created.");

if (xTaskCreate(task2,
"Blink 21",
1024,
NULL,
1,
NULL) == pdPASS)
Serial.println("Task2 Created.");


}

void loop() {
}

传递多参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
typedef struct {
byte pin;
int delayTime;
} LEDFLASH;


void ledFlash(void *pt) {
LEDFLASH * ptLedFlash = (LEDFLASH *)pt; //将传递的指针数据读出来
byte pin = ptLedFlash->pin;
int delayTime = ptLedFlash->delayTime;

pinMode(pin,OUTPUT);
while (1) {
digitalWrite(pin, !digitalRead(pin));
vTaskDelay(delayTime);
}
}

LEDFLASH led1, led2;

void setup() {
Serial.begin(9600);


led1.pin = 23; //设置传递参数的值
led1.delayTime = 1000;
led2.pin = 21;
led2.delayTime = 3000;


if (xTaskCreate(ledFlash, //xTaskCreate(任务,命名,分配的内存空间,传递的参数(void指针),操作的指针)
"FLASH LED",
1024,
(void *)&led1,
1,
NULL) == pdPASS)
Serial.println("led1 flash task Created.");

if (xTaskCreate(ledFlash,
"FLASH LED",
1024,
(void *)&led2,
1,
NULL) == pdPASS)
Serial.println("led2 flash task Created.");

}

void loop() {
}

多任务上锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
语法:
SemaphoreHandle_t xHandler; 创建Handler
xHandler = xSemaphoreCreateMutex(); 创建一个MUTEX 返回NULL,或者handler
xSemaphoreGive(xHandler); 释放
xSemaphoreTake(xHanlder, timeout); 指定时间内获取信号量 返回pdPASS, 或者pdFAIL

理解方法:
MUTEX的工作原理可以想象成
共享的资源被锁在了一个箱子里,只有一把钥匙,有钥匙的任务才能对改资源进行访问
*/

// 养成良好习惯,被多进程和中断调用的变量使用 volatile 修饰符
volatile uint32_t inventory = 100; //总库存
volatile uint32_t retailCount = 0; //线下销售量
volatile uint32_t onlineCount = 0; //线上销售量

SemaphoreHandle_t xMutexInventory = NULL; //创建信号量Handler

TickType_t timeOut = 1000; //用于获取信号量的Timeout 1000 ticks


void retailTask(void *pvParam) {
while (1) {

// 在timeout的时间内如果能够获取就继续
// 通俗一些:获取钥匙
if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS) {
//被MUTEX保护的内容叫做 Critical Section


//以下实现了带有随机延迟的 inventory减1;
//等效为 inventory--; retailCount++;
uint32_t inv = inventory;
for (int i; i < random(10, 100); i++) vTaskDelay(pdMS_TO_TICKS(i));
if (inventory > 0) {
inventory = inv - 1;
retailCount++;

//释放钥匙
xSemaphoreGive(xMutexInventory);
} else {
//无法获取钥匙
}


};

vTaskDelay(100); //老板要求慢一些,客户升级后,可以再加快速度
}
}

void onlineTask(void *pvParam) {
while (1) {

// 在timeout的时间内如果能够获取二进制信号量就继续
// 通俗一些:获取钥匙
if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS) {
//被MUTEX保护的内容叫做 Critical Section
//以下实现了带有随机延迟的 inventory减1;
//等效为 inventory--; retailCount++;
uint32_t inv = inventory;
for (int i; i < random(10, 100); i++) vTaskDelay(pdMS_TO_TICKS(i));
if (inventory > 0) {
inventory = inv - 1;
onlineCount++;

//释放钥匙
xSemaphoreGive(xMutexInventory);
} else {
//无法获取钥匙
}
};

vTaskDelay(100); //老板要求慢一些,客户升级后,可以再加快速度
}
}


void showTask(void *pvParam) {
while (1) {

printf("Inventory : %d\n", inventory);
printf(" Retail : %d, Online : %d\n", retailCount, onlineCount);


if (inventory == 0 ) {
uint32_t totalSales = retailCount + onlineCount;
printf("-----SALES SUMMARY-----\n");
printf(" Total Sales: %d\n", totalSales);
printf(" OverSales: %d\n", 100 - totalSales);
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);

xMutexInventory = xSemaphoreCreateMutex(); //创建MUTEX

if (xMutexInventory == NULL) {
printf("No Enough Ram, Unable to Create Semaphore.");
} else {
xTaskCreate(onlineTask,
"Online Channel",
1024 * 4,
NULL,
1,
NULL);
xTaskCreate(retailTask,
"Retail Channel",
1024 * 4,
NULL,
1,
NULL);
xTaskCreate(showTask,
"Display Inventory",
1024 * 4,
NULL,
1,
NULL);
}

}

void loop() {
}