关注+星标公众,不错过精彩内容

编排 | strongerHuang

微信公众号 | 嵌入式专栏

很多初学者都是从裸机开始学起,不能明白裸机和操作系统的区别。甚至有不少人认为用中断就能代替多任务处理,你认同吗?

裸机系统

裸机系统通常分成轮询系统前后台系统

1、轮询系统

轮询系统即是在裸机编程的时候,先初始化好相关的硬件,然后让主程序在一个死循环里面不断循环,顺序地做各种事情,大概的伪代码具体如代码清单所示:

int main(void)
{/* 硬件相关初始化 */HardWareInit();/* 无限循环 */for (;;) {/* 处理事情 1 */DoSomething1();/* 处理事情 2 */DoSomethingg2();/* 处理事情 3 */DoSomethingg3();}
}

轮询系统是一种非常简单的软件结构,通常只适用于那些只需要顺序执行代码且不需要外部事件来驱动的就能完成的事情。在代码清单 1-1 中,如果只是实现 LED 翻转,串口输出,液晶显示等这些操作,那么使用轮询系统将会非常完美。但是,如果加入了按键操作等需要检测外部信号的事件,用来模拟紧急报警,那么整个系统的实时响应能力就不会那么好了。

假设DoSomethingg3 是按键扫描,当外部按键被按下,相当于一个警报,这个时候,需要立马响 应 , 并 做 紧 急 处 理 , 而 这 个 时 候 程 序 刚 好 执 行 到 DoSomethingg1 , 要 命 的 是DoSomethingg1 需要执行的时间比较久,久到按键释放之后都没有执行完毕,那么当执行到 DoSomethingg3 的时候就会丢失掉一次事件。足见,轮询系统只适合顺序执行的功能代码,当有外部事件驱动时,实时性就会降低。

2、前后台系统

相比轮询系统,前后台系统是在轮询系统的基础上加入了中断。外部事件的响应在中断里面完成,事件的处理还是回到轮询系统中完成,中断在这里我们称为前台, main 函数里面的无限循环我们称为后台,大概的伪代码见代码清单所示:

int flag1 = 0;
int flag2 = 0;
int flag3 = 0;int main(void)
{/* 硬件相关初始化 */HardWareInit();/* 无限循环 */for (;;) {if (flag1) {/* 处理事情 1 */DoSomething1();}if (flag2) {/* 处理事情 2 */DoSomethingg2();}if (flag3) {/* 处理事情 3 */DoSomethingg3();}}
}void ISR1(void)
{/* 置位标志位 */flag1 = 1;/* 如果事件处理时间很短,则在中断里面处理如果事件处理时间比较长,在回到后台处理 */DoSomething1();
}void ISR2(void)
{/* 置位标志位 */flag2 = 2;/* 如果事件处理时间很短,则在中断里面处理如果事件处理时间比较长,在回到后台处理 */DoSomething2();
}void ISR3(void)
{/* 置位标志位 */flag3 = 1;/* 如果事件处理时间很短,则在中断里面处理如果事件处理时间比较长,在回到后台处理 */DoSomething3();
}

在顺序执行后台程序的时候,如果有中断来临,那么中断会打断后台程序的正常执行流,转而去执行中断服务程序,在中断服务程序里面标记事件,如果事件要处理的事情很简短,则可在中断服务程序里面处理,如果事件要处理的事情比较多,则返回到后台程序里面处理。

虽然事件的响应和处理是分开了,但是事件的处理还是在后台里面顺序执行的,但相比轮询系统,前后台系统确保了事件不会丢失,再加上中断具有可嵌套的功能,这可以大大的提高程序的实时响应能力。在大多数的中小型项目中,前后台系统运用的好,堪称有操作系统的效果。

多线程系统

相比前后台系统,多线程系统的事件响应也是在中断中完成的,但是事件的处理是在线程中完成的。在多线程系统中,线程跟中断一样,也具有优先级,优先级高的线程会被优先执行。

当一个紧急的事件在中断被标记之后,如果事件对应的线程的优先级足够高,就会立马得到响应。相比前后台系统,多线程系统的实时性又被提高了。

多线程系统大概的伪代码具体见代码清单所示:

int flag1 = 0;
int flag2 = 0;
int flag3 = 0;int main(void)
{/* 硬件相关初始化 */HardWareInit();/* OS 初始化 */RTOSInit();/* OS 启动,开始多线程调度,不再返回 */RTOSStart();
}void ISR1(void)
{/* 置位标志位 */flag1 = 1;
}void ISR2(void)
{/* 置位标志位 */flag2 = 2;
}void ISR3(void)
{/* 置位标志位 */flag3 = 1;
}void DoSomething1(void)
{/* 无限循环,不能返回 */for (;;) {/* 线程实体 */if (flag1) {}}
}void DoSomething2(void)
{/* 无限循环,不能返回 */for (;;) {/* 线程实体 */if (flag2) {}}
}void DoSomething3(void)
{/* 无限循环,不能返回 */for (;;) {/* 线程实体 */if (flag3) {}}
}

相比前后台系统中后台顺序执行的程序主体,在多线程系统中,根据程序的功能,我们把这个程序主体分割成一个个独立的,无限循环且不能返回的小程序,这个小程序我们称之为线程。

每个线程都是独立的,互不干扰的,且具备自身的优先级,它由操作系统调度管理。加入操作系统后,我们在编程的时候不需要精心地去设计程序的执行流,不用担心每个功能模块之间是否存在干扰。

加入了操作系统,我们的编程反而变得简单了。整个系统随之带来的额外开销就是操作系统占据的那一丁点的 FLASH 和 RAM。现如今,单片机的 FLASH 和 RAM 是越来越大,完全足以抵挡 RTOS 那点开销。

轮询、前后台和多线程系统软件模型区别:

最后,附上一个视频,用动画形象比喻裸机和RTOS的区别:

声明:本文素材来源网络,版权归原作者所有。如涉及作品版权问题,请与我联系删除。

------------ END ------------

关注公众号回复“加群”按规则加入技术交流群,回复“1024”查看更多内容。

点击“阅读原文”查看更多分享

单片机裸机 vs RTOS多线程相关推荐

  1. RTOS rt-thread裸机系统与多线程系统

    裸机系统与多线程系统 裸机系统 裸机系统通常分成轮询系统和前后台系统 轮询系统 轮询系统即在裸机编程过程中,先初始化相关的硬件,然后让主程序在一个死循环里面不断循环,顺序地做各种事情,大概的伪代码参见 ...

  2. 工程师实战:单片机裸机程序框架是怎样炼成的?

    前言 前不久,我有位做测试的朋友转去做开发的工作,面试遇到了一个问题,他没明白,打电话问了我.题目大概就是: 在单片机裸机开发时,单片机要处理多个任务,此时你的程序框架是怎样的呢? 这其实是个经典面试 ...

  3. 在51单片机上跑RTOS有没有意义?

    关注+星标公众号,不错过精彩内容 作者 | strongerHuang 微信公众号 | 嵌入式专栏 最近看见我的一个技术交流群在讨论一个问题:在51单片机上跑RTOS有没有意义? 今天就来围绕51和R ...

  4. 单片机裸机实用组件--软件定时器、时间戳

    单片机裸机实用组件–软件定时器.时间戳 之前写过一篇关于单片机定时器延时计时功能的博客 ,刚工作的时候搞得现在看来还是比较糙的,是时候整一个新的了. base_timer 单片机裸机适用的定时器小组件 ...

  5. 裸机和RTOS系统区别与联系

    1. 裸机和rtos的多任务处理 试想一种场景,我们正在打游戏,但女朋友在你打游戏的过程中给你发送消息,你需要回复消息   1.1 裸机处理方式 while(1) { 打游戏();回复信息(); } ...

  6. SpiFlash同步/异步读写单片机裸机实例

    单片机裸机开发中会经常遇到外设速度过慢,长时间读忙等待,但CPU又不能长时间阻塞的问题. 这种问题可以通过实现一个状态机来异步处理. 异步状态机代码结构示例: enum {eIDLE = 0,eSTA ...

  7. STM32单片机裸机程序-高级实现实时性处理方法

    概述 这篇文章是对刚刚学习单片机的小伙伴们,提的一些处理技巧思维.(我在项目上经常使用这样的处理思路) 现在举个栗子,应用场景是这样的,比如:在while(1)中在处理一些裸机,然后碰巧又在延时时候, ...

  8. 单片机MCU51系列RTOS多任务超微操作系统精髓 简单实现 汇编及C语言混合 keil9.0工程源码

    系统设计核心意图:使用定时器,在延时过程中运行其它的任务. 工程源码:链接: https://pan.baidu.com/s/1LEV9qYmUn6SdemGz7TH6dw 提取码: iua5 切换任 ...

  9. 一文搞懂栈(stack)、堆(heap)、单片机裸机内存管理malloc

    大家好,我是无际. 有一周没水文了,俗话说夜路走多了难免遇到鬼. 最近就被一个热心网友喷了. 说我的文章没啥营养,所以今天来一篇烧脑的. 哈哈,开个玩笑,不要脸就没人能把我绑架. 主要是最近研发第二代 ...

  10. 单片机裸机实用组件--LED

    easy_led 介绍 单片机常用led驱动,可以十分方便的控制led闪烁频率和闪烁持续时间 移植教程 将 easy_led.c easy_led.h easy_led_port.c 添加到工程中 打 ...

最新文章

  1. 连接web端,mysql,返回乱码解决
  2. Scala概述及学习Scala的优势
  3. 03-对图像进行数值计算和加权融合
  4. python对文件操作的相关函数_python文件操作的相关函数深入理解Django中内置的用户认证...
  5. java synchronizer_Java同步框架AbstractQueuedSynchronizer详解
  6. mysql查看所有触发器以及存储过程等操作集合
  7. python request保持连接_python接口自动化 - Requests-3 高级用法
  8. python约瑟夫环单向循环链表_用单向循环链表解决约瑟夫环(Joseph)问题
  9. .Net·使用ILSpy反编译exe或dll文件保存为项目结构
  10. Chrome插件--IDM
  11. 并联机构逆运动学用MapleSim符号来解决
  12. delphi技巧--分离汉字和英文字母
  13. raw格式转换成qcow2格式
  14. ETCD 源码学习--Watch(client)
  15. html页面怎样打印二分之一,打印二分之一a4纸 大小的纸张 Word该如何设置?
  16. SEO外链收录:锚文本外链代发排名
  17. 最全Hadoop视频教程(从入门到精通 视频教程下载)Hadoop八天完全攻克Hadoop视频教程 Hadoop开发新版Hadoop视频教程
  18. 《Spring》第二十一篇 事务底层源码解析
  19. kafka send failed: dial tcp: lookup hostname: no such host
  20. php+撮合引擎,撮合引擎开发:数据结构设计

热门文章

  1. JAVA UTC时区时间相互转换
  2. win10删除账户文件夹(C:\Users\***)后,无法登录账户的解决方法
  3. 【共词聚类分析】基于CNKI和WOS的小样本稳健性检验
  4. Unity-TextMeshPro如何扩展材质实现字体Face+Outline流光效果
  5. Linux基础命令(2)
  6. D. Drunk Passenger(数学概率)
  7. java 读取xls、xlsx文件
  8. Arduino驱动HDC1080测量温湿度
  9. 服务器如果清理垃圾文件,为citrix服务器清理垃圾文件事件
  10. python 实验七 字典与集合 (上)