🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习 🎬擅长领域:驱动开发,嵌入式软件开发,BSP开发 ❄️作者主页:一个平凡而乐于分享的小比特的个人主页 ✨收录专栏:UCOS-III,本专栏为UCOS-III学习记录 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖
信号量:用于同步和资源计数(关心"有没有") 消息队列:用于数据传输(关心"是什么")
OS_SEM mutex_sem;
void task1(void *p_arg) {
OSSemPend(&mutex_sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
// 访问共享资源(如全局变量、外设)
OSSemPost(&mutex_sem, OS_OPT_POST_1, &err);
}
void task2(void *p_arg) {
OSSemPend(&mutex_sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
// 访问同一共享资源
OSSemPost(&mutex_sem, OS_OPT_POST_1, &err);
}特点:只关心资源是否被占用,不传输数据
OS_SEM sync_sem;
// 任务A完成工作后通知任务B
void task_a(void *p_arg) {
// 完成某些工作
OSSemPost(&sync_sem, OS_OPT_POST_1, &err); // 通知任务B
}
void task_b(void *p_arg) {
OSSemPend(&sync_sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
// 收到通知后开始工作
}特点:只关心事件是否发生,不传递具体信息
OS_SEM resource_sem;
void init(void) {
OSSemCreate(&resource_sem, "Buffer Pool", 5, &err); // 5个缓冲区
}
void consumer_task(void *p_arg) {
OSSemPend(&resource_sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
// 获取到一个缓冲区,可以使用了
// 使用完后...
OSSemPost(&resource_sem, OS_OPT_POST_1, &err);
}特点:只关心可用资源数量
OS_Q data_queue;
typedef struct {
uint8_t sensor_id;
float value;
uint32_t timestamp;
} sensor_data_t;
void sensor_task(void *p_arg) {
sensor_data_t data;
data.sensor_id = 1;
data.value = Read_Sensor();
data.timestamp = OSTimeGet();
OSQPost(&data_queue, &data, sizeof(data), OS_OPT_POST_FIFO, &err);
}
void process_task(void *p_arg) {
sensor_data_t *p_data;
OS_MSG_SIZE size;
p_data = OSQPend(&data_queue, 0, OS_OPT_PEND_BLOCKING, &size, 0, &err);
// 处理具体的传感器数据
printf("Sensor %d: %.2f at %lu\n", p_data->sensor_id, p_data->value, p_data->timestamp);
}特点:需要传递具体的数据内容
OS_Q cmd_queue;
typedef enum {
CMD_START,
CMD_STOP,
CMD_SET_SPEED,
CMD_GET_STATUS
} command_t;
void ui_task(void *p_arg) {
command_t cmd = CMD_SET_SPEED;
int speed = 100;
// 发送命令和参数
OSQPost(&cmd_queue, &cmd, sizeof(cmd), OS_OPT_POST_FIFO, &err);
}
void motor_task(void *p_arg) {
command_t *p_cmd;
OS_MSG_SIZE size;
p_cmd = OSQPend(&cmd_queue, 0, OS_OPT_PEND_BLOCKING, &size, 0, &err);
switch(*p_cmd) {
case CMD_SET_SPEED:
// 设置电机速度
break;
// 处理其他命令...
}
}特点:需要传递具体的命令和参数
OS_Q audio_queue;
void adc_task(void *p_arg) {
int16_t audio_buffer[128];
// 采集音频数据
OSQPost(&audio_queue, audio_buffer, sizeof(audio_buffer), OS_OPT_POST_FIFO, &err);
}
void audio_process_task(void *p_arg) {
int16_t *p_audio_data;
OS_MSG_SIZE size;
p_audio_data = OSQPend(&audio_queue, 0, OS_OPT_PEND_BLOCKING, &size, 0, &err);
// 对音频数据进行处理(滤波、编码等)
}特点:需要传递大量的数据块
当你只需要回答这些问题时:
当你需要回答这些问题时:
实际项目中经常组合使用:
OS_SEM data_ready_sem; // 数据就绪信号量
OS_Q sensor_data_q; // 传感器数据队列
void sensor_task(void *p_arg) {
sensor_data_t data;
while(1) {
data = Read_Sensor();
OSQPost(&sensor_data_q, &data, sizeof(data), OS_OPT_POST_FIFO, &err);
OSSemPost(&data_ready_sem, OS_OPT_POST_1, &err); // 通知有数据
OSTimeDly(100, OS_OPT_TIME_DLY, &err);
}
}
void display_task(void *p_arg) {
sensor_data_t *p_data;
OS_MSG_SIZE size;
while(1) {
OSSemPend(&data_ready_sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
p_data = OSQPend(&sensor_data_q, 0, OS_OPT_PEND_BLOCKING, &size, 0, &err);
LCD_Display(*p_data);
}
}简单决策树:
要传递具体数据吗?
├── 是 → 使用消息队列
└── 否 →
只需要同步或资源管理吗?
├── 是 → 使用信号量
└── 否 → 可能需要两者结合记住: