开源硬件
Arduino
客制化键盘
Arduino_寄存器
二进制运算
寄存器+二进制运算
LCD-逐字显示
密码依次录入
等待输入
WiFi Duck(无线击键注入攻击平台)
WiFi Duc-New
WiFi Duc-Old
蓝牙无线烧录
ESP8266
ESP-NOW
ESP8266看门狗
ESP8266-休眠模式
ESP01/01S使用说明
WIFI_SD
ESP8266-Web服务器
ESP8266-WIFI自动认证
ESP32
ESP32 ADC2
ESP32_PWM
ESP32_CAM
ESP32 小坦克
ESP32_限电保护
Arduino IDE 添加 ESP32
ESP32-iPhone BLE攻击
STM32
STM32F103-虚拟键盘
STC
STC8G1K08(A)
树莓派-触摸屏
Arduino IDE
Arduino_自制库
Arduino库收集
常见排序算法
冒泡排序
选择排序
插入排序
希尔排序
归并排序
快速排序
计数排序
预处理
millis(运行时长)
Arduino IDE 2.X-修改数据位置
Mixly
Mixly安装教程
Mixly 模块介绍
Mixly-添加ESP32CAM支持
Mixly-库定制工具
模块
4G模块连接物联网
GPS模块
语音模块(JQ8900)
安信可VB语音识别
28BYJ-48(5V步进)
FreeRTOS
FreeRTOS-多任务基础
FreeRTOS-任务共享全局变量
FreeRTOS-多核多任务
FreeRTOS-MUTEX
FreeRTOS-常规程序改多任务
FreeRTOS-定时器
LaserGRBL(激光雕刻)
LaserGRBL-GRBL
GRBL-CNC Shield v4
MicroPython
Scratch
Wokwi(在线仿真)
html转无符号数组
待做开源项目
本文档使用 MrDoc 发布
-
+
首页
FreeRTOS-MUTEX
**MUTEX 的工作原理:** 共享的资源被锁在了一个箱子里,只有一把钥匙,有钥匙的任务才能对改资源进行访问 `对加密的共享资源使用时间越短越好,防止影响到其他任务使用` ```c++ SemaphoreHandle_t xHandler; //创建 Handler 信号量 xHandler = xSemaphoreCreateMutex(); //创建一个MUTEX 返回NULL(失败,FreeRTOS堆栈不足),或者handler xSemaphoreGive(xHandler); //释放 xSemaphoreTake(xHanlder, timeout); //尝试获取信号量的最大时间 返回pdPASS(), 或者pdFAIL() ``` ## 使用 MUTEX 进行共享资源保护 ```c++ // 养成良好习惯,被多进程和中断调用的变量使用 volatile 修饰符(易挥发性,防止程序给优化掉) volatile uint16_t inventory = 100; //总库存 volatile uint32_t retailCount = 0; //线下销售量 volatile uint32_t onlineCount = 0; //线上销售量 SemaphoreHandle_t xMutexInventory = NULL; //创建 Handler 信号量 TickType_t timeOut = 1000; //尝试获取信号量的最大时间 1000 ticks(1 tick = 1ms) // 计算线下销售,两个计算销售的基本一致 void retailTask(void *pvParam) { while (1) { // 获取钥匙,在设定时间内如果能够获取就继续 if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS) { //被MUTEX保护的内容叫做 Critical Section 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(10); //老板要求慢一些,客户升级后,可以再加快速度 } } // 计算线上销售,两个计算销售的基本一致 void onlineTask(void *pvParam) { while (1) { // 获取钥匙,在设定时间内如果能够获取就继续 if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS) { //被MUTEX保护的内容叫做 Critical Section 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(10); //老板要求慢一些,客户升级后,可以再加快速度 } } // 显示销售 void showTask(void *pvParam) { while (1) { printf("库存 : %d", inventory); printf(" 线下零售 : %d 线上零售 : %d\n", retailCount, onlineCount); if (inventory == 0 ) { printf("\n-----销售总结-----\n"); printf(" 总销售额: %d\n", retailCount + onlineCount); printf(" 超售: %d\n\n", 100 - retailCount - onlineCount); } // pdMS_TO_TICKS(),ms转tick vTaskDelay(pdMS_TO_TICKS(100)); } } void setup() { Serial.begin(115200); xMutexInventory = xSemaphoreCreateMutex(); //创建MUTEX if (xMutexInventory == NULL) { // 因堆栈不足,信号量创建失败,这里进行失败处理 printf("Ram不足,无法创建"); } else { // 信号量可以使用。信号量句柄存储在变量xMutexInventory中 // 创建的信号量初始是无效(空)的 // 创建两个任务,分别对应计算销售和显示库存 xTaskCreate(retailTask, "计算线下销售", 1024 * 4, NULL, 1, NULL); xTaskCreate(onlineTask, "计算线上销售", 1024 * 4, NULL, 1, NULL); xTaskCreate(showTask, "显示库存", 1024 * 4, NULL, 1, NULL); } } void loop() { } ``` ## MUTEX读写做保护 ```c++ // 加载 MPU6050 和 LCD 所需库 #include <Adafruit_MPU6050.h> #include <Adafruit_Sensor.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> // 创建 LCD 2004 对象 LiquidCrystal_I2C lcd(0x27, 20, 4); // 创建 MPU6050 对象 Adafruit_MPU6050 mpu; // 创建 mpu6050 三类参数指针 Adafruit_Sensor *mpu_temp, *mpu_accel, *mpu_gyro; // 创建 MPU6050 结构图 typedef struct { float temp; // 温度 float accX; // 加速度 float accY; float accZ; float gyroX; // 角度 float gyroY; float gyroZ; } MPU6050; MPU6050 mpu6050; // 结构体对象 SemaphoreHandle_t xMutexMPU6050 = NULL; // 创建信号量Handler TickType_t timeOut = 1000; // 尝试获取信号量的最大时间 1000 ticks(1 tick = 1ms) // MPU6050 任务主体 void mpu6050Task(void *pvParam) { // 初始化 MPU6050,setup() mpu.begin(); // 启用 mpu6050 通讯 mpu_temp = mpu.getTemperatureSensor(); mpu_temp->printSensorDetails(); mpu_accel = mpu.getAccelerometerSensor(); mpu_accel->printSensorDetails(); mpu_gyro = mpu.getGyroSensor(); mpu_gyro->printSensorDetails(); sensors_event_t accel; sensors_event_t gyro; sensors_event_t temp; while (1) { // 获取信号量(申请钥匙) if (xSemaphoreTake(xMutexMPU6050, timeOut) == pdPASS) { //获取MPU数据 mpu_temp->getEvent(&temp); mpu_accel->getEvent(&accel); mpu_gyro->getEvent(&gyro); // 对结构体进行数据写入 mpu6050.temp = temp.temperature; mpu6050.accX = accel.acceleration.x; mpu6050.accY = accel.acceleration.y; mpu6050.accZ = accel.acceleration.z; mpu6050.gyroX = gyro.gyro.x; mpu6050.gyroY = gyro.gyro.y; mpu6050.gyroZ = gyro.gyro.z; xSemaphoreGive(xMutexMPU6050); //释放钥匙 } else { // 无法获取钥匙 } vTaskDelay(500); } } //LCD 任务主体 void lcdTask(void *ptParam) { lcd.init(); lcd.backlight(); //定义是 2004 LCD byte lcdLine = 4; byte lcdChar = 20; //创建一个二维的的数组 //注意长度是 lcdChar+1 最后还有一个位置要给换行符 char line0[lcdChar + 1], line1[lcdChar + 1], line2[lcdChar + 1], line3[lcdChar + 1]; char * line[] = { line0, line1, line2, line3, }; while (1) { if (xSemaphoreTake(xMutexMPU6050, timeOut) == pdPASS) { // 组合数据,并存入数组 // 共享数据时间越短越好,可以快速操作完并释放,以免影响其他对共享数据的操作 sprintf(line0, " MPU6050 %d", xTaskGetTickCount() / 100); sprintf(line1, " Temperature %.2f", mpu6050.temp); sprintf(line2, " ACC %.2f %.2f %.2f", mpu6050.accX, mpu6050.accY, mpu6050.accZ); sprintf(line3, " GYRO %.2f %.2f %.2f", mpu6050.gyroX, mpu6050.gyroY, mpu6050.gyroZ); xSemaphoreGive(xMutexMPU6050); //释放钥匙 } else { // 无法获取钥匙 } // 显示数据 for (int i = 0; i < 4; i++) { lcd.setCursor(0, i); lcd.print(line[i]); } vTaskDelay(1000); } } void setup() { Serial.begin(115200); xMutexMPU6050 = xSemaphoreCreateMutex(); //创建MUTEX // xTaskCreate(<函数名称>,"<任务描述>",<分配内存空间(bit)>,<传入参数>,<优先级>,<任务参数>) xTaskCreate(mpu6050Task, "MPU6050", 1024 * 8, NULL, 1, NULL); vTaskDelay(1000); //让MPU6050提前先运行一秒获取第一笔数据 xTaskCreate(lcdTask, "lcd", 1024 * 8, NULL, 1, NULL); } void loop() { } ``` **相关内容视频** [任务共享全局变量](https://www.bilibili.com/video/BV1vB4y1D7Cj)|[使用Mutex保护变量](https://wokwi.com/projects/333321518201176660) [使用MUTEX对MPU6050的读写做保护](https://www.bilibili.com/video/BV1nt4y1W7mQ)|[MPU6050 & MUTEX](https://wokwi.com/projects/333400924498166356)
造物者W
2022年6月17日 10:38
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码