🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习 🎬擅长领域:驱动开发,嵌入式软件开发,BSP开发 ❄️作者主页:一个平凡而乐于分享的小比特的个人主页 ✨收录专栏:UCOS-III,本专栏为UCOS-III学习记录 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖
delay_ms 是一个忙等待延时函数,用于裸机程序。OSTimeDly 是一个任务调度延时函数,用于RTOS(如uC/OS)delay_ms 的实现通常是通过执行一个空循环来消耗特定的CPU时钟周期。在延时期间,CPU被完全占用,不能做任何其他事情。
// 一个简化的 delay_ms 实现思路
void delay_ms(uint32_t ms) {
for (uint32_t i = 0; i < ms; i++) {
// 通过计算CPU频率,执行一个耗时约1ms的空循环
for (uint32_t j = 0; j < DELAY_1MS_LOOP_COUNT; j++) {
__NOP(); // 无操作指令
}
}
} 在裸机程序中,代码通常在一个大的 while(1) 超级循环中运行。使用 delay_ms 会阻塞整个循环的执行。
// 裸机程序示例
void main() {
while(1) {
LED1_ON();
delay_ms(500); // 在此期间,CPU空转,无法响应按键或刷新显示
LED1_OFF();
delay_ms(500); // 同上
// 如果这里有一个按键检测函数,在delay期间按键是无法被响应的。
// check_button();
}
} 在延时期间,CPU资源被白白浪费,效率很低
如果一个程序中有多个需要定时执行的任务(如扫描按键、刷新显示屏、读取传感器),在一个任务的 delay_ms 期间,其他所有任务都会被挂起,导致系统响应迟钝。
OSTimeDly 是RTOS提供的一个系统服务。当一个任务(线程)调用 OSTimeDly 时,它主动请求RTOS将自己挂起指定的时间片(ticks)。RTOS会立即将这个任务从就绪态移入等待态,然后执行任务调度,切换到另一个就绪的、优先级最高的任务去运行。
// RTOS 任务示例
void LED_Task(void *p_arg) {
while(1) {
LED1_ON();
OSTimeDly(500); // 挂起本任务500个tick,让出CPU
LED1_FF();
OSTimeDly(500); // 再次挂起本任务,让出CPU
}
}
void Button_Task(void *p_arg) {
while(1) {
check_button(); // 这个任务可以独立运行,不受LED_Task延时的干扰
OSTimeDly(50); // 自己也延时一小段时间,让出CPU给其他任务
}
} 在RTOS中,程序被划分为多个独立的任务。每个任务都有自己的堆栈和运行上下文。
在任务延时期间,CPU不会被空转,而是去执行其他有实际工作的任务(如上面的 Button_Task),极大地提高了CPU的利用率和系统的整体效率。
因为高优先级的任务可以抢占低优先级的任务,所以紧急事件能够得到快速响应。各个任务在宏观上看起来是“同时”运行的。
函数 | 任务状态 | 是否让出CPU | 其他任务能否运行 |
|---|---|---|---|
delay_ms() | 运行态 | ❌ 不让出 | ✅ 能(通过中断抢占) |
OSTimeDly() | 挂起态 | ✅ 让出 | ✅ 能(主动放弃CPU) |