单片机开发中裸机系统有哪些(轮询、时间片、前后台.....)
单片机开发中常听说 裸机系统、前后系统、轮询系统、时间片轮询系统......。到底是啥?接下来对其发表个人理解和总结。
概念与总结
裸机系统:是对无操作系统(RTOS、Linux...)等一类系统架构应用程序的统称。主要两类实现机制和设计思想。
实现机制:解决 “任务如何触发/调度”,底层运行逻辑
设计思想:解决 “任务逻辑如何组织”,上层方法论
维度 | 核心概念 | 子概念 / 组成 | 定义 | 优点 | 缺点 | 典型应用场景 |
实现机制 | 轮询机制 | 基础轮询系统 | 主循环(while(1))中顺序地查询每个任务的就绪条件,条件满足则执行。 | 简单、省资源 | 实时差、任务多延迟大 | 简单电路控制(如 LED 闪烁、单一传感器周期性读取)、无紧急响应需求的场景。 |
时间片轮询系统 | 基于基础轮询,通过定时器中断划分 “时间片”,主循环按时间片轮流执行不同周期性任务。 | 支持多周期、实现简 | 实时受限、超时易出问题 | 多周期性任务调度(如温湿度采集 + 屏幕刷新,周期固定且无严格优先级)。 | ||
中断驱动机制 | 基础中断触发系统 | 任务依赖硬件 / 软件中断信号触发,中断为任务调度核心。 | 实时极强 | ISR 忌复杂、易冲突 | 需要快速响应外部事件的场景(如按键触发、异常报警)。 | |
前后台系统(裸机主流架构) | 前台:中断服务程序(ISR),处理紧急任务(快进快出); 后台:主循环(while(1)),以轮询方式处理非紧急、周期性的任务。 | 兼顾实时 / 复杂 | 后台延迟增加、需同步 | 需区分任务优先级的场景(如电机过流保护 ISR + 后台参数配置、红外遥控接收 ISR + 后台解码)。 | ||
设计思想 | 状态机系统 | - | 将复杂的任务流程分解为多个离散的状态,通过状态转移规则(条件触发)管理流程,逻辑可复用。 | 逻辑清、易维护 | 多状态复杂、不适合连续态 | 流程化任务控制(如按键长按 / 短按识别、设备启动 / 运行 / 待机状态切换、协议解析)。 |
事件驱动系统 | - | 引入 “事件队列” 管理中断 / 外部触发的 “事件”,后台按序处理,解耦任务与触发源。 | 解耦、支持多源 | 有延迟、队列繁、耗资源 | 多模块交互场景(如按键、传感器、通信模块的事件统一管理,避免模块间直接耦合)。 |
代码示例
轮询系统
void main()
{init_system(); // 初始化系统while(1){Led(); // 读取按键delay(10); // 简单延时}
}
时间片轮询系统
// 多功能电饭煲 - 时间片轮询
volatile uint8_t time_slice = 0;void timer_isr() // 定时器中断
{time_slice = (time_slice + 1) % 4;
}void main()
{init_system();enable_timer_interrupt();while(1){switch(time_slice){case 0:read_temperature(); // 读取温度break;case 1:read_buttons(); // 读取按键break;case 2:update_display(); // 更新显示break;case 3:control_heater(); // 控制加热器break;}}
}
基础中断触发系统
// 燃气泄漏报警器 - 中断驱动系统
volatile uint8_t gas_detected = 0;
volatile uint8_t battery_low = 0;void gas_sensor_isr() // 气体传感器中断
{gas_detected = 1;
}void battery_isr() // 电池检测中断
{battery_low = 1;
}void main()
{init_system();enable_interrupts();while(1){if (gas_detected){sound_alarm(); // 发出警报send_alert_sms(); // 发送短信gas_detected = 0;}if (battery_low){indicate_low_battery(); // 低电量指示battery_low = 0;}enter_deep_sleep(); // 进入深度休眠}
}
前后台系统
// 电热水壶前后台系统伪代码
volatile unsigned char water_boiled_flag = 0;
volatile unsigned char button_pressed_flag = 0;// 前台:中断服务程序
void timer_interrupt() interrupt 1
{static unsigned int count = 0;count++;if(count >= 1000){ // 1秒定时count = 0;check_water_temp(); // 快速温度检查if(water_temp >= 100){water_boiled_flag = 1; // 设置标志}}
}void button_interrupt() interrupt 0
{button_pressed_flag = 1; // 按钮按下标志
}// 后台:主循环
void main()
{init_hardware();enable_interrupts(); // 使能中断while(1){// 处理按钮事件if(button_pressed_flag){button_pressed_flag = 0;toggle_heating();}// 处理水沸腾事件if(water_boiled_flag){water_boiled_flag = 0;stop_heating();sound_buzzer();}// 低优先级任务update_led_indicator();}
}
状态机系统
// 自动门控制器 - 状态机系统
typedef enum {DOOR_CLOSED, // 门关闭DOOR_OPENING, // 门打开中DOOR_OPEN, // 门打开DOOR_CLOSING // 门关闭中
}DoorStateTypeE;DoorStateTypeE current_state = DOOR_CLOSED;void main()
{init_system();while(1){switch(current_state){case DOOR_CLOSED:if (sensor_triggered()){start_motor_open();current_state = DOOR_OPENING;}break;case DOOR_OPENING:if (door_fully_open()){start_timer(5000); // 5秒延时current_state = DOOR_OPEN;}break;case DOOR_OPEN:if (timer_expired() || sensor_triggered()){start_motor_close();current_state = DOOR_CLOSING;}break;case DOOR_CLOSING:if (door_fully_closed()){stop_motor();current_state = DOOR_CLOSED;}else if (sensor_triggered()){start_motor_open(); // 防夹current_state = DOOR_OPENING;}break;}}
}
事件驱动系统
// 智能门锁事件驱动系统伪代码
typedef enum
{CARD_EVENT, // 卡片事件KEY_EVENT, // 按键事件BUTTON_EVENT, // 按钮事件TIMEOUT_EVENT // 超时事件
}EventType;typedef struct
{EventType type;unsigned char data;
}Event;// 事件队列
Event event_queue[10];
unsigned char queue_head = 0, queue_tail = 0;// 事件处理函数
void process_card_event(unsigned char card_id)
{if(valid_card(card_id)){unlock_door();start_timer(5000); // 5秒后自动上锁}
}void process_key_event(unsigned char key)
{add_key_to_buffer(key); // 处理密码输入逻辑if(password_complete()){if(valid_password()) unlock_door();else beep_error();}
}// 主循环:事件处理
void main()
{init_peripherals();while(1){// 检查是否有事件if(queue_head != queue_tail){Event current_event = event_queue[queue_tail];queue_tail = (queue_tail + 1) % 10;// 分发事件switch(current_event.type){case CARD_EVENT:process_card_event(current_event.data);break;case KEY_EVENT:process_key_event(current_event.data);break;case BUTTON_EVENT:process_button_event(current_event.data);break;case TIMEOUT_EVENT:lock_door();break;}}}
}// 中断中添加事件到队列
void card_interrupt() interrupt 0
{unsigned char card_id = read_card_id();event_queue[queue_head].type = CARD_EVENT;event_queue[queue_head].data = card_id;queue_head = (queue_head + 1) % 10;
}
总结
在实际的裸机单片机开发中,不存在 “唯一最优” 的架构,选择的核心是匹配项目需求、硬件资源和维护成本。大多数场景下,开发者会根据任务复杂度、实时性要求、硬件限制等因素,选择混合架构(多种基础架构的组合)。
如:“前后台 + 状态机”、“前后台 + 事件驱动”
轮询/时间片:主循环主导任务顺序;
中断/前后台:中断触发,区分紧急 / 非紧急;
状态机:用 “状态→条件” 简化复杂流程;
事件驱动:用队列隔离 “触发” 与 “处理”;
不同场景的架构选择
项目复杂度 | 推荐架构 | 示例 |
---|---|---|
简单项目 | 前后台系统 | LED控制、简单传感器 |
中等项目 | 前后台 + 状态机 | 电饭煲、洗衣机 |
复杂项目 | 前后台 + 状态机 + 事件驱动 | 智能家居、工业控制器 |
极高实时性 | 中断驱动 + 前后台 | 电机保护、安全系统 |