来源:电子工程专辑微信公众号

某天某日某产房,你诞生了(power up , 上电运行),结果你不哭,医生把你提起来,屁股上狠狠一巴掌,你哇哇大哭(reset, 复位成),护士给你检查,看有没有传染病(EMI测试),然后打预防针(绝缘处理),没有问题后作记录(QC pass),你的父母来接你回去(客户验收)。回家后你有了自己的新床(PCB),家里条件好,给你铺六张毛巾被(六层板),可惜上面小窟窿太多(过孔太多),父母把奶瓶给你,你终于获得了外部能量(Power
Supply ),否则你的自身能量会耗尽(Battery too Low)。

每天清晨,你尚在休眠模式(IDL)下运行时,一阵叫喊声吵醒你(wake up,激活),你感觉很饿,于是大哭(Alarm Ring),父母马上来喂你,你不哭了(discard Alarm,解除报警),但很不争气地撒尿了(current output,电流输出)。父母给你收拾完,开始教你说话,但你的大脑还很简单(initial procedure,初始化程序),后来你开始学走路,结果步调不稳(步进电机驱动错误),一跑就坐到地上了(RUN fail,运行失败)。好在你的父母很耐心地教你(调试阶段),你终于可以走了(调试通过)。

你逐渐长大,吃的也多了,给你的食物老是不够(功耗太大,power waste too heavy),你偷偷打开冰箱狂吃一顿,结果吃的太多不消化了(过载,over load),差点绷断肠子(route burn,烧断走线),还好你终于没事了,不敢吃那么多了(reduce power waste,降低功耗)。后来你上学了,接受好多新的知识(new procedure),但是没有实际经验(未调试的),结果工作时发现那些知识不能照用,还要更多地学习别人的经验(Copy procedure,拷贝程序),不过你还是不断发现臭虫(BUG),只好请教灭虫专家来解决(调试高手)。终于你的工作稳定了,你开始进入日复一日的工作状态(Endless Loop),你很烦,于是老是出错误(out of order,程序跑飞),结果老板开始盯紧你(软件陷阱),你被当场抓住修理一通,马上老老实实干活了(程序恢复)。

终于有个姑娘闯入你的生活(interrrupt,中断),使你忘记别的一切(优先级最高),你完全浸入爱河(进入中断服务子程序),大手大脚地花钱(Large 模式),很快就结婚了(双CPU运行),你马上发现你的储蓄不够用了(RAM resource too low),需要精简节约(compact模式),婚假也结束了,你又回去上班了(RETI,退出中断服务程序)。后来日子越过越枯燥,老婆批评你脑袋不够用(MIPS太低),不会算计(没有浮点运算能力),你对她的话一耳进一耳出(FIFO)。你对老婆也爱理不理了(优先级降低),这时一个小姑娘勾引你,你马上动心(抗干扰能力差),幸好你老婆及时发现,严防紧守,你放弃了企图(丢弃乱码)。

日子恢复平静,一晃几十年过去,你发现你身边的年轻人都用全新的知识装备着,他们都是在ARM大学毕业的,开着Linux的车子,大把花着票子(海量存储)。你低头看自己,发现自己只是在51大学毕业,开着汇编的破车,手里钱少的可怜(256 字节内存)。你被迫到人才市场找工作,发现自己已经是多年前的旧货,降价处理了,你这样的都是一麻袋一麻袋的。

你长吁短叹,终于选择退休,靠养老金活着,开始疾病缠身,你的牙齿有了问题(IO口驱动力下降),你说话不清楚(TXD发射失败),耳朵也不灵(RXD接收不灵),你的胃也不好,存不住食物(ALE锁存失败),你终于因心肌梗死送到医院,医生手持电击手柄给你通电(高压测试),但你无法苏醒(复位失败),医生只好拔掉你的输液管(关闭电源),你看了这个乱七八糟的世界最后一眼,终于POWER DOWN了。

哈哈,是不是总结的很到位。博君一笑,下面进入正题:
经常在群、论坛里看到有人问:怎么学单片机?也常看到有人说学了好几个月可就是没有什么进展。当然,受限于每个人受到的教育水平不同和个人理解能力的差异,学习起来会有快慢之分,但我感觉最重的就是学习方法。一个好的学习方法,能让你事半功倍,这里说说我学习单片机的方法。

1、万事开头难、要勇敢迈出第一步。
开始的时候,不要老是给自己找借口,说KEIL不会建项目啦、没有实验板啦之类的。遇到困难要一件件攻克,不会建项目,就先学它,这方面网上教程很多,随便找找看一下,做几次就懂了。然后可以参考别的人程序,抄过来也无所谓,写一个最简单的,让它运行起来,先培养一下自己的感觉,知道写程序是怎么一回事,无论写大程序还是小程序,要做的工序不会差多少,总得建个项目,再配置一下项目,然后建个程序,加入项目中,再写代码、编译、生成HEX,刷进单片机中、运行。必须熟悉这一套工序。个人认为,一块学习板还是必要的,写好程序在上面运行一下看结果,学习效果会好很多,仿真器就看个人需要了。单片机是注重理论和实践的,光看书不动手,是学不会的。

2、知识点用到才学,不用的暂时丢一边。
厚厚的一本书,看着人头都晕了,学了后面的,前面的估计也快忘光了,所以,最好结合实际程序,用到的时候才去看,不必说非要把书从第一页看起,看完它才来写程序。比如你写流水灯,完全就没必要看中断的知识,专心把流水灯学好就是了,这是把整本书化整为零,一小点一小点的啃。

3、程序不要光看不写,一定要自己写一次。
最开始的时候,啥都不懂,可以抄人家的程序过来,看看每一句是干什么用的,达到什么目的,运行后有什么后果,看明白了之后,就要自己写一次,你会发现,原来看明白别人的程序很容易,但到自己写的时候却一句也写不出来,这就是差距...当你自己能写出来的时候,说明你就真的懂了。

4、必须学会掌握调试程序的方法。
不少人写程序,把代码写好了,然后一运行,不是自己想要的结果,就晕了,然后跑到论坛上发个帖子,把程序一贴,问:为什么我的程序不能正常运行?然后就等别人来给自己分析。这是一种很不好的行为,应该自己学会发现问题和学会如何解决问题。这就需要学习调试程序的方法,比如KEIL里,可以下断点啦,查看寄存器内容等等,这些都是调试程序的手段,当你发现你写的程序运行结果和你想象中不一样的时候,你可以单步,也可以下断点,然后跟踪,查看各相关寄存器内容,看看程序运行过中是不是有什么偏差,找出影响结果的地方,改正过来。这一个过程非常重要,通过程序的排错,你可以学到的知识是书上得不到的。

5、找到解决问题思路比找到代码更重要。
我们用单片机来控制周边器件,达到我们想到的目的,这是一个题目,而如何写出一个程序,来控制器件按你想要的结果去运作,这个就是解题的思路。要写程序,就得先找到解决问题的思路,你学会找出这个解题思路,比你找到代码更为重要。不少人很喜欢找人家的代码,有的人甚至有了代码就直接复制到自己的程序中,可以说,这不是一种学习的态度,无助于你编程水平的提高。我几乎不怎么看人家的代码,多数时候是看别人的思路,有方框图最好,没有的话文字说明也可以,要从代码中看出别人处理问题的思路,是相当困难的,特别是大型的程序,看起来是非常的累人,所以现在我也明白了,以前读书时说的程序流程图很重要。当你知道一个问题怎么去解决了,那么剩下的只是你安排代码去完成,这就已经不是什么问题了。

6、开动脑筋,运用多种方法,不断优化自己的程序。
想想用各种不同方法来实现同一功能。这是一个练习和提高的过程,一个问题,你解决了,那么你再想想,能不能换种写法,也可以实现同一功能,或者说,你写出来的代码,能不能再精简一点,让程序执行效率更高,这个过程,就是一个进步的过程。很多知识和经验的获得,并不是直接写在书让你看就可以得到的,需要自己去实践,开动脑筋,经验才能得到积累,编程水平才能有所提高。

7、看别人的代码,学习人家的思路。
这个在学习初期是很有用,通过看别人的代码,特别是有多年编程经验的人写出的具有一定水平的代码,可以使自己编程水平得到迅速的提高,同时,也可以结合别人的编程手法,与自己的想法融合在一起,写出更高水平的代码,从中得到进步。但要注意,切忌将学习变成抄袭,更不是抄袭完了就认为自己学会了,这样做只会使你退步。

8、尝试编写一下综合应用的程序。
从流水灯学起,到动态扫描,再到中断,那么,你可以试试写一下时钟这种综合性应用的程序,不要小看时钟,要写好它不是一件容易的事情,它包括了单片机大部分的知识,比如有按键(IO读取)、动态扫描(IO输出)、中断等,如何协调好各功能模块正常工作,才是编程者需要学习的地方,当你单独写一个功能的时候,比如按键读取,你可能感觉很容易,因为你的程序啥也不做,只是读按键。但把它和其它功能混合在一起,如何在整个程序运行中使每一部分都正常工作,这就不是写一个按键读取这么容易的事情,功能模块之间有可能会互相影响,比如你需要让数码管既能显示,又要去处理按键读取,怎么使这两部分都正常工作,这就是一个协调过程。当你有了这个处理协调能力,你就算是入门了。

9、着重于培养解决问题的能力,而不是具体看自己编写了多少代码或者做过什么。
“学单片机重点在于学习解决问题的思路,而不是局限于具体的芯片类型和语言”这一直是我的座右铭,是我学单片机多年来感悟出来的。经常看到有人说“你会驱动XX芯片,真牛啊”“你搞过XX项目,真厉害”之类的话,其实这是非常片面的,搞过XX芯片,搞过XX项目,只能说明你做过这一项目,它只是你的业绩,并不是代表能力就一定高。真正的能力应该是:“遇到没有解决过的问题或器件,能利用自己已学的知识,迅速找到解决问题的方法。”这个才是能力。写程序的过程就是一个创造的过程,几乎没有完全一样的项目,每次你遇上的几乎都不相同,所以你拥有的必须是你面对新项目时的创造能力,而不是标榜着你以往做过多少项目。当然,业绩也能从另一侧面反映你的经验和水平。

10、如果有可能,多学习计算机专业的知识,比如数据结构等。
这些是你解决问题的基础知识,你把这些知识应用得越好,就会发现越容易找到解决问题的方法,这就是为什么一个学计算机专业的人编的程序和一个非计算机专业的人编的程序有差异的原因。也是一个菜鸟进军到高手所要配备的知识。如果我们把编程分为宏观编程和微观编程,那么微观编程就是写具体的代码,比如控制某某器件的语句;而宏观编程就是如何对整个程序进行布局、安排,使功能模块以你想要的方式去运行,得出你想要的结果。如前所说“会控制XX器件”这些只能算是微观编程,能做到这一步还只能算是菜鸟级别,如果面对一个新的器件,你心里没底,没把握去写这个控制程序,那说明你还是一个初级的菜鸟。当你有了一定的编程经验,控制过相当数量的器件之后,你就会发现,控制器件这些工作都是相似的、重复的工作,体现不出编程的水平,最多也是写得好与不好的差别,只能算是一些小技巧的应用。而对整个程序进行布局、安排这些才是最头痛的事情,能达到宏观编程和微观编程都做好才是真正的高手。对于规模越大的程序,越能体现出这一点。

11、面对一个新项目时,多自己开动脑筋,不要急于找别人的程序。
有不少人面对一个新项目时,第一步想到的就是网上找别人写过的代码,然后抄一段,自己再写几句,凑在一起就完成任务,这虽然可能是省时间,但绝对不利你的学习。当你接到一个新项目时,应该先自己构思一下整个程序的架构,想想如何来完成,有可能的话,画一个流程图,简单的可以画在脑子里,对程序中用到的数据、变量有一个初步的安排,然后自己动手去写,遇到实在没办法解决的地方,再去请教别人,或看别人是怎么处理的,这样首先起码你自己动过脑想过,自己有自己的思路,如果你一开始就看别人的程序,你的思维就会受限在别人的思维里,自己想再创新就更难了,这样你自己永远也没办法提高,因为你是走在别人的影子里。

12、多利用网络的搜索,学会提问题。
一般来说,学习过程中,你遇上的问题,前人们多数也有遇上的,所以如果有什么不懂,在自己解决不了的时候,最好先到网上搜索一下,看能不能找到答案,找不到再到论坛里发问,发问也要有目的性,尽量简单明了的描述问题,让帮助你的人可以用最少的时间就看懂你说什么,毕竟人家帮助你是免费的,时间也是有限的。