嵌入式系统基础:定义、RTOS与常用MCU平台
各位同学,咱们今天聊聊嵌入式系统的基础。说实话,这个领域我摸爬滚打了十几年,踩过的坑比走过的路还多。但正是这些基础概念,决定了你设计的系统能不能稳定跑上十年八年。
嵌入式系统到底是什么?
嵌入式系统,说白了就是「专门干一件事的计算机」。它不像你桌上的PC,能打游戏、写文档、刷网页。嵌入式系统从出生那天起,任务就定死了——比如分拣机里的控制板,一辈子就负责读传感器、算位置、发脉冲。
我个人习惯把嵌入式系统拆成三块看:
- 硬件层:MCU、传感器、执行器、通信接口。这是骨架。
- 软件层:裸机程序或RTOS、驱动、应用逻辑。这是血肉。
- 中间层:协议栈、算法库、硬件抽象层。这是筋腱。
我在项目中遇到过最典型的误解——有人觉得嵌入式就是「单片机编程」。其实不对。嵌入式系统强调的是「资源受限下的可靠运行」。你想想看,分拣机一天要处理几万个包裹,MCU的RAM可能只有几百KB,Flash也就几MB。在这种条件下,还要保证99.99%的可靠性,这才是真功夫。
核心特征:
- 专用性:软硬件针对特定任务定制
- 实时性:必须在规定时间内响应外部事件
- 可靠性:常年7×24小时运行,不能死机
- 资源受限:CPU主频低、内存小、存储有限
实时操作系统(RTOS)概念
为什么要用RTOS?嗯,这个问题我当年也纠结过。裸机也能跑分拣机啊,一个超级循环搞定一切。但后来我发现,当系统复杂度上去以后,裸机就是给自己挖坑。
RTOS的核心价值在于——任务调度。它让你把复杂的控制逻辑拆成多个独立任务,每个任务有自己的优先级和周期。RTOS负责决定「现在该跑哪个任务」。
我建议你记住这几个关键概念:
| 概念 | 说明 | 分拣机中的例子 |
|---|---|---|
| 任务(Task) | 独立的执行线程,有自己的栈空间 | 读编码器任务、控制电机任务 |
| 信号量(Semaphore) | 用于任务间同步或资源互斥 | 包裹到位信号量,通知电机启动 |
| 消息队列(Queue) | 任务间传递数据 | 扫码结果传给分拣决策任务 |
| 中断(ISR) | 硬件事件触发,优先级最高 | 编码器脉冲中断,记录位置 |
我曾经在一个项目中,因为信号量使用不当,导致两个任务互相等待——死锁了。分拣机直接卡住,包裹堆了一地。那次教训让我明白:RTOS不是万能药,用不好反而添乱。
我的经验:新手用RTOS,最容易犯的错误是「任务切得太碎」。比如把读一个传感器就搞成一个任务,结果上下文切换开销比实际干活还多。我建议:任务粒度以「功能模块」为单位,一个模块一个任务就够了。
分拣机常用MCU平台
分拣机控制器的MCU选型,说白了就是平衡「性能」和「成本」。我这些年用过不少平台,但最常用的就两个系列。
STM32系列
STM32,尤其是F4和H7系列,在分拣机领域用得特别多。为什么?
- 生态成熟:HAL库、CubeMX、各种例程,上手快
- 外设丰富:多路定时器、PWM、ADC、CAN、以太网
- 性价比高:几十块钱的芯片,能搞定大部分分拣控制
我记得有个项目,用STM32F407控制一条小型分拣线。主频168MHz,驱动4个步进电机、读取8个光电传感器、还要跑Modbus TCP和上位机通信。嗯,跑得稳稳的。
代码示例——用STM32的定时器产生PWM控制步进电机:
// 初始化定时器TIM2,输出PWM控制步进电机
void Stepper_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
// 使能时钟
__HAL_RCC_TIM2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置PA0为TIM2_CH1
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置PWM参数
htim2.Instance = TIM2;
htim2.Init.Prescaler = 84 - 1; // 84MHz / 84 = 1MHz
htim2.Init.Period = 1000 - 1; // 1MHz / 1000 = 1kHz PWM
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_PWM_Init(&htim2);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500; // 50%占空比
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}
NXP i.MX RT系列
当分拣机需要更高性能时——比如要跑视觉算法、要处理高速编码器信号、要支持EtherCAT——i.MX RT就派上用场了。
这个系列的特点:
- 主频高:最高可达1GHz,Cortex-M7内核
- 大内存:内部SRAM可达2MB,还支持SDRAM扩展
- 高速外设:千兆以太网、USB HS、FlexCAN、ENET
我有个朋友做高速交叉带分拣机,用的就是i.MX RT1064。主频600MHz,同时控制32个交叉带小车,每个小车独立控制转向和卸货。这要是用STM32,光中断处理就够呛。
注意:i.MX RT虽然性能强,但功耗和散热也要考虑。我见过有人把i.MX RT当普通单片机用,不加散热片,结果跑着跑着就过热降频了。分拣机是工业环境,夏天车间温度可能到40°C以上,散热设计不能省。
选型建议
说了这么多,到底怎么选?我个人的经验是:
- 小型分拣线(10个以下分拣口):STM32F4系列,够用,成本低
- 中型分拣线(10-50个分拣口):STM32H7或i.MX RT1020,性能有富余
- 大型高速分拣线(50个以上,带视觉):i.MX RT1060以上,必要时上FPGA配合
记住一句话:选MCU不是选最强的,而是选最合适的。我见过有人用i.MX RT只干了一个定时器中断的活,纯属浪费。也见过有人用STM32F1硬扛高速分拣,结果CPU占用率99%,稍微有点干扰就丢脉冲。
好了,这一章的内容就这些。嵌入式系统的基础,说白了就是理解「资源受限」和「实时可靠」这两个核心。下一章咱们聊聊分拣机的软件架构分层设计,那才是真正考验架构能力的地方。