【韦东山】嵌入式全系统:单片机-linux-Android对硬件
我是韦东山,一直从事嵌入式Linux培训,最近打算连载一系列文章。 正在录制全新的嵌入式Linux视频,使用新路线,不再从裸机/uboot开始,效率更高。 对应文档也会写成书<<嵌入式Linux应用开发完全手册>>第二版, 视频文档、书的样稿可以直接下载:https://vdisk.weibo.com/s/t6HbuIpx6zoa1
1.概念
只要涉及编程,并且所用硬件不是电脑的话,都可以认为是嵌入式软件开发。所谓“嵌入”,就是把处理器嵌入某个物体中,让它具备计算能力。比如手表中有单片机,那么手表就是一个嵌入式设备,在上面开发的单片机程序就是嵌入式软件;手机中有性能强大的处理器,它也是一个嵌入式设备,手机中运行Linux系统,在Linux系统上运行Android系统,这些Linux、Android都属于嵌入式软件。
嵌入式设备上运行的软件或系统可以分为三类:单片机、Linux/WinCE等大型操作系统、Android/IOS/QT等GUI系统。
做产品时我们考虑的是性价比,什么合适就用什么,这需要我们具备多方面的开发能力。本文将介绍单片机、Linux、Android系统的侧重点。
2. 有哪些产品使用这3类技术?




没有一样技术可以适用于所有设备,很多时候需要组合起来。比如无人机,使用单片机才能更快处理各种控制事件,使用Linux才能更好进行图像处理、传输,在手机端还得给你开发一个安卓APP让你更容易操控。
3. 谁的工作机会更多?
我们要用数据说话,看下图:

让人意外,Linux的职位竟然是最多的。可能因为很多互联网产品也使用Linux,比如虚拟化、云计算、云存储领域。这些互联网公司、云产品公司对Linux开发人员也有大量的需求,把这些公司的职位来跟单片机职位进行对比,很不公平。
所以我再细分一下,把涉及硬件操作的Linux职位单独抽出来,如下:

这些数据统计稍显粗略,但是也能说明一些问题,我先做个柱形图:

也许,我们可以得出这么个结论:跟硬件打交道的职位里单片机最多,嵌入式Linux的数量是单片机的三分之二。 如果把Linux APP的职位算上,那是最多的,这似乎有些不公平,Linux APP应该去跟JAVA等相比。 这些职位需求也是吻合现实的,一个公司里硬件职位最少,驱动稍多点,APP最多。很多时候APP职位里几个老员工把驱动的活也全包了。
3.1 单片机工作机会门槛最低
身边触手可及的电灯开关、洗衣机、冰箱、微波炉等小家电,使用的都是单片机技术;家里的无线路由器、智能电视,用的是Linux;你天天用的手机要么是安卓要么是苹果。
可以大概猜得出来,单片机的工作机会更多地集中在小家电领域,门槛比较低,单纯的技术上升空间也有限。注意,我说的是“技术上升空间”。我几年前发表过一个观点“学习单片机没有前途”,这过于激烈,被很多人骂。我今天把它改为“只学习单片机没有前途”。
最近有一个高手在教我CAN的知识,CAN编程基本只用在单片机上,但是华为年薪80万挖不走他;并且他才刚开始学习Linux。他给我发过两张图:

各位看看上面的图,要想拿高薪,单片机工程师必须深入行业,掌握行业的核心技术。否则,单就单片机技术来说,10年经验跟2年经验并没有太大区别。 做单片机很容易从上到下整个程序都是你一个人掌握,所有问题你都清楚,这很安逸,也意味麻痹及危机。 现在5G、物联网时代到来,单片机也将会有新的发展,我认为重点在于各类RTOS、各类物联网规范。
3.2 Linux的职位反而是最多的
在写这篇文章之前,我也倾向于认为单片机的职位是最多的。但是在51JOB上进行粗略搜索之后,linux的职位反而是最多的,即使仅仅计算“嵌入式 linux”的职位,也达到了单片机职位的三分之二。这也许预示着中国的产业升级,大家都不再满足于使用单片机完成简单的功能,需要添加更多更炫的功能。
如果你是电子工程师,想从事“linux驱动”等跟硬件密切相关的工作,可能机会不多,因为这需要你有经验。这就是行业尴尬的地方,单片机工程师想跳槽,最适配的是嵌入式Linux中跟硬件编程相关的职位,但是这个职位又太看重经验;实际上很容易找到的是电子产品的Linux APP开发。
现在的中小公司里有这么一个趋势,扔一个项目给你,从上到下APP、驱动、硬件都要你的团队完成,很多人都是多面手。
所以,技多不压身,如果你是电子工程师话,单片机、Linux驱动、Linux APP都掌握,也许生存能力才能大辐增强。
3.3 Android
安卓的热度有点退了,一个中小公司没有一定的实力真做不来安卓系统,这个系统太庞大了,乱配个蓝牙就分分钟卡上1、2个月。 所以需要用安卓系统的公司,多是采购方案公司的板卡,方案公司帮你改好安卓系统。 买来方案后,这些公司多是做些安卓APP;要研究安卓系统的人,也许去手机厂家或是方案公司会比较好。 比如我知道的科大讯飞下某子公司,就是使用中山firefly的瑞芯微系列板卡。
4 单片机/Linux/Android工程师怎么点灯?
LED的原理图如下,只要让某个引脚输出高电平或低电平,就能让LED亮或灭。

4.1 单片机怎么点灯?

简单地说就是需要工作师去看原理图确定引脚是哪一个,输出什么电平能点亮LED。再去看芯片手册,确定怎么操作寄存器。最后写程序。
至于你写的程序,风格如何、函数名怎么取,完全由你自由发挥。以后别的同事想来重用你的代码,就得看你写的说明,或是看你的代码。
现在ARM公司在推出一些HAL规范,就是规定一些硬件操作函数接口,如果大家都遵守这些规范的话,在单片机上的APP也很容易移植到其他板子上。
4.2 Linux怎么点灯?

在Linux中,驱动程序负责操作硬件,APP调用open、write这些标准接口就可以点亮LED。APP调用open,会导致驱动程序中的led_open被调用;APP调用write,会导致驱动程序中的led_write被调用。
所以,驱动怎么写?驱动程序中要写出led_open、led_write这些函数。在写出这些函数之前,驱动工程师也要去看原理图、看芯片手册,这跟单片机工程师是一样的。然后就按照Linux的规范提供这些led_open、led_write函数。 所以,Linux驱动 = 驱动框架+硬件操作 = 驱动框架+单片机知识。 为什么要多此一举引入驱动框架?直接操作硬件多爽、多直接。
原因有2 1.术业有专攻,不要让写APP的人去看原理图、芯片手册,他们只需要调用标准的open,read,write等接口即可操作硬件 2.软件和硬件隔离,硬件再怎么变化,只需要改驱动,APP不需要改
3.3 Android怎么点灯?

Android是一套GUI系统,它是运行在Linux上面的,硬件操作由Linux完成。所以你可以认为Android就是一套APP,它也是通open、write这些接口来访问驱动,进而操作硬件的。
但是Android中程序太多数是用JAVA编写的,这些open、write是C语言函数,所以要引入一个层:JNI接口(Java Native Interface),通过这个接口Java可以调用C函数。
5. 单片机/Linux/Android工程师怎么使用LCD?
用点灯举例太简单,可以突出单片机和Linux的区别;但是Linux和Android的区别似乎不大。
下面我们用LCD为例讲解。
5.1 LCD操作原理

假设上图是一个LCD屏幕,屏幕中一个一个密密麻麻的黑点称之为像素点,每一行有若干个点,试想下有一个电子枪,电子枪位于某一个像素点的背后,然后向这个像素发射红,绿,蓝三种原色,这三种颜色按不同的比例组合成任意一种颜色。电子枪在像素点的背后,一边移动一边发出各种颜色的光,电子枪从左往右移动,到右边边缘之后就跳到下一行的行首,继续从左往右移动,如此往复,一直移动到屏幕右下角的像素点,最后就跳回原点。
问题1:电子枪如何移动?
答: 有一条像素时钟信号线(DCLK),连接屏幕,每来一个像素时钟信号(DCLK),电子枪就移动一个像素。
问题2:电子枪打出的颜色该如何确定?
答:有三组红,绿,蓝信号线(RGB),连接屏幕,由这三组信号线(RGB)传递颜色
问题3:电子枪移动到LCD屏幕右边边缘时,如何得知需要跳到下一行的行首?
答:有一条水平同步信号线(HSYNC),连接屏幕,当接收到水平同步信号(HSYNC),电子枪就跳到下一行的最左边
问题4:电子枪如何得知需要跳到原点?
答:有一条垂直同步信号线(VSYNC),连接屏幕,当接收到垂直同步信号线(VSYNC),电子枪就由屏幕右下脚跳到左上角(原点)
问题5:电子枪如何得知三组信号线(RGB)确定的颜色就是它是需要的呢?
答:有一条RGB数据使能信号线(DE),连接屏幕,当接收到数据使能信号线(DE),电子枪就知道这时由这三组信号线(RGB)确定的颜色是有效的,可以发射到该像素点。
下图是开发板,LCD控制器,LCD屏幕的框图

之前提到的像素时钟(DCLK), 三组红,绿,蓝信号线(RGB),水平同步信号线(HSYNC),垂直同步信号线(VSYNC),RGB数据使能信号线(DE)都是从LCD控制器发出的,只要开发板支持LCD显示,它肯定就会有一个LCD控制器。
问题6:RGB三组信号线上的数据从何而来?
RGB三组信号线上的数据从何而来.png
上图是RGB数据来源框图,内存中划出一部分区域,这块区域被称为Framebuffer。在Framebuffer里面我们会构造好每一个颜色所对应的像素。Framebuffer中的值会被LCD控制器读出来,通过RGB三组线传给电子枪,电子枪再把它转换成红绿蓝三种颜色打到屏幕上。在屏幕上的每一个像素,在Frambuffer里面都有一个对应存储空间,里面存有屏幕上对应像素的颜色。
LCD控制器会周而复始的从Framebuffer中取出一个个像素的颜色值,发给电子枪,同时需要和DCLK,VSYNC,HSYNC,DE这些信号配合好。
总结起来,程序需要做的就是2点:设置好LCD控制器,然后在显存中写入数据。
5.2 单片机怎么操作LCD

单片机程序员要做的事很直接: 1.设置LCD控制器,它会自动从FrameBuffer中读取每个像素的数据发送到LCD上 2.把要显示的文字、图像放入FrameBuffer中
5.3 Linux怎么操作LCD?

在Linux中,驱动程序负责操作硬件,APP调用open、ioctl这些标准接口就可以获得LCD的参数,设置LCD。然后使用mmap获得Framebuffer的地址,就可以往里面填入数据。 至于LCD控制器的设置,这由驱动来做。
所以,驱动怎么写?初始化LCD控制器,提供lcd_open、lcd_ioctl、lcd_mmap函数,让APP可以通过这些函数获得LCD参数,设置参数,获得Framebuffer地址。 所以,Linux驱动 = 驱动框架+硬件操作 = 驱动框架+单片机知识。 为什么要多此一举引入驱动框架?直接操作硬件多爽、多直接。
原因有2 1.术业有专攻,不要让写APP的人去看原理图、芯片手册,他们只需要调用标准的open,read,write,ioctl,mmap等接口即可操作硬件 2.软件和硬件隔离,硬件再怎么变化,只需要改驱动,APP不需要改
5.4 Android怎么操作LCD?

Android是一套GUI系统,跟QT是类似的。在Android/QT等GUI系统里:
- LCD会被多个APP使用,如果不统一管理必定乱套;
-
- 所以,肯定有一个管理软件,或称为服务软件:
-
2.1 APP自行构造自己的界面,提交给显示显示服务软件
-
2.2 显示服务软件:根据多个APP的前后层次,合并最终的显示图像
- 最后再调用驱动程序显示出来
所以在Android系统中,它的重心在于显示服务、在于多个窗口的层叠、管理、销毁。硬件的操作交给是Linux实现。
6 写在最后
我无意引起单片机、Linux、Android孰优孰劣的讨论,我确实不看好纯粹的单片机软件开发,但是很看好RTOS及物联网在单片机上的应用。 生活不容易,码农不容易,走上码农之路,只有不断学习了。
联系我们:加V 13923404017 进入技术交流群