对,就是他,于振南老师,十年后,与郭天祥老师再度联手打造全新课程。
现在网络上,基本的C语言课程满天飞,我们现在差不多都在半山腰,歇够了没,于老师在嵌C之巅等我们!接下来我们将连载课程,介绍那些大佬背后不为人知的故事!
于老师跟郭老师合照
(资料图片仅供参考)
致广大单片机学习者和工程师:
你们所经历的,振南也一样不落的都经历过。起初对于C语言和单片机学习上的迷茫困惑可能比你们更甚,但是一切都过来了,没什么能够真正难倒我们,相信自己!
谨以此文,向大家讲述我十多年前入门阶段的往事和感悟,以及告诉大家:单片机到底是什么?
为什么很多初学者都被困在C语言与单片机入门基础的山脚下止步不前,彷徨徘徊?为什么大家在学习上花费了如此大的精力,却仍然是收效甚微?为什么C语言中的指针就那么难于理解,始终让人们摸不着头脑?又为什么看似毫无问题的代码,烧录到单片机中运行就是不对?这一切的一切都归结于一个根源:对C语言的本质和单片机的体系结构与运作机制认识不清!
通过本章,我希望能让你看穿一切,升华你的整体认知。
此时,你会发现做单片机和嵌入式开发是如此简单,单片机也变得“乖巧”了很多,仿佛一切都变得顺畅了,和谐了!
引用我启蒙老师的一句话:“C语言,学得多精都不为过!要学单片机,先学C语言。”
1.1 懵懂好奇的我
性格决定你所能从事的事业,也决定了你的命运。
我的性格是对新鲜事物有极大的好奇,而且这种好奇会发展为兴趣,并最终狂热。当我脑子里出现一个新想法,我就会迫不及待地去实现它,而且不看到它最后的样子,不会轻易放弃,不论成败都要试试。在我记忆里,我小时候就是这样的。
有一次我看到一根铁丝,正好我衣兜里有一个皮筋,于是我就做了一个弹弓。后来一发不可收拾,我迷上了做弹弓,各种各样,大大小小。还不乏创新和发挥,我想到在电影里见过的弩(其实我当时还不知道它叫弩),于是接下来的很长时间我一直在研究如何用铁丝制造一把弩。最终,弩出现了。原来玩弹弓时的纸子弹被我换成了石子,随着扳机的扣动,我的屁股也开花了。
上初中的时候,我通过学校开设的兴趣班第一次接触到计算机,第一次知道了DOS、Windows98、WPS、输入法这些东西,迅速燃起了对计算机的好奇和兴趣。当时我渴望拥有自己的计算机。于是开始天天缠着我爸妈给我买一台计算机。碍于当时的经济条件,最后家里给我买了一台学习机。用它可以模拟DOS环境、练习指法,还有一些简单的编程,如LOGO、BASIC等。从此,我开始有了最基本的编程意识:程序就是一行行顺序执行的语句。但是对循环、条件判断等比较复杂的东西还不够熟练,只能说有一个概念。
对计算机的兴趣没有像以往一样,热乎一段时间就放下了。我发现计算机要学的东西非常多,而且它好像一直都在变化出新,这些新的东西又会再一次掀起我的兴趣。对计算机的狂热从上了高中就开始了。长期基于学习机的练习,我的指法已经足够熟练,但是用拼音输入文字速度太慢,所以我报班学了五笔,一直延用至今(现在每当有人知道我用五笔的时候都会对我投来钦佩的目光)。在一顿软磨硬泡之下,我拥有了第一台自己的奔IV电脑,从此我的“折腾”开始了。
平时一有时间就研究VB、软件加解密、网络攻防这些东西,还订阅了杂志《电脑爱好者》,期期不落。到高考前,我应该可以称得上是半个“业余电脑专家”了,也已经可以使用VB开发一些小的桌面软件,比如计算器、小游戏。计算机让我的好奇心得到了很大的满足,也使我的创造力得到了施展。
1.2 我的C语言学习经历
基于我对计算机的浓厚兴趣,高考报志愿的时候,我四个志愿全部报了计算机专业,从那时起,注定了我将以计算机为伴、为业。
原以为进了大学就能马上接受正统的计算机教育了,其实并不是。计算机专业一开始并不直接学编程,而是学数学。我当时比较迷茫,觉得学计算机不教编程,上学有什么用?其实我知道专业课程安排的用意,计算机科学的基础是数学,应该先打基础。但是又有多少学生真正去好好学习这些基础而枯燥的东西。导致很多人整个大一的宝贵时间都浪费在打游戏上,估计他们已经忘了自己为什么要学计算机了。我也怕会变成这样。
我开始自学很多计算机方面的知识,但是又漫无目的,直到我碰到一个“能人”。据说他小学开始学计算机,初中已经可以独立开发软件,高中时因为开发了一个网络软件,被某软件平台收录,并评为五星软件,而被免试特招。他智商高,但似乎情商不是太高,经常容易得罪人,有一些让别人不太舒服的做事风格。有一次我们偶然聊天,他提到国际ACM程序设计竞赛的事情,问我有没有兴趣参加,说已经集结了五六个人,组成小组参加比赛。从此我开始有了动力,开始自学C语言和算法,参加团队集训,下载往年竞赛题目模拟竞技,相互交流经验。当时专业课还没有开C语言,但是我们已经都是C语言高手了。也许,应该在这里放一道ACM竞赛的试题给大家解解闷(这是一道陈年老题,感兴趣的话可以百度)。
对!ACM试题是全英文的。
图1.1 国际ACM程序设计竞赛历届真题
大二下学期,C语言专业课开了。很多人并不知道C语言有什么用,带着迷茫上课、考试、通过,最后忘掉。我开始慢慢深刻感觉到C语言的精妙,它有自己严格的语法规则,但是又不作过多限定,这让它非常灵活而实用。同一个逻辑功能,可以有很多种C语言的表达方式,它一定程度上体现出了编程者自身的习惯和素养。代码可以写得很乱,也可以写得很优雅;可以写得冗长啰嗦,也可以写得如蜻蜓点水,几行了事。但是乱也可以错落有致,寥寥几行也可以大显功底。我意识到C语言没那么简单,不仅仅是一门语言而已,它会伴随我一生,正如后来有人所说的“程序如人生”。
我的性格仍然在发挥着巨大的作用。随着不断的学C语言,用C语言,我开始觉得C语言真的是乐趣多多,如同挖矿,永远都有那些未曾遍及的角落,永远都有没有见过的另类技巧,永远都有富含创意的智慧的流露。(关于C语言的技巧,振南专门整理成了一章《C语言的那些技巧与深层理解》,感兴趣的读者可以看一下)
1.3 C语言的顶级赛事
在C语言专业课上,老师告诫我们:“C语言,学得多精都不为过!”
很多人可能当时并没有完全理解这句话,但是我却深深的赞同。后来,我们的ACM参赛组对编程的高涨热情感染了整个计算机学院,而这位C语言老师,也成为了我们的集训老师。再后来,我们的举动,带动了更多人参加ACM程序设计竞赛,学院、学校、乃至哈尔滨市、黑龙江省、东北三省。最终,国际ACM委员会委任我们学校为国际ACM中国东北赛区承办方(南方赛区承办方是浙大)。当时,全校到处都挂满了条幅:“Program Your World!”
关于ACM程序设计竞赛,当年还有一个关于浙大的传奇故事(浙大是当年的ACM世界总冠军)。我们知道写程序要经历编程、编译、查错修改、再编译,如此往复,若干次。这个往复的次数,与程序的难度与程序员的能力有很大关系。但是要做到所有一次成功,不能说不可能,但是极难!当年浙大参加总决赛,只剩十分钟,还有最后一道试题。参赛队员,打开记事本,直接写代码,直接提交,一次通过。这件事情,在圈里流传,也许有夸张的成分。但是,也足以显示我们与顶尖编程高手之间的巨大差距。
ACM竞赛,就是一群疯狂热爱计算机和编程的人们,一起正在z做的事情。他们技术夯实,以不断猎奇、不断学习、不断完成新的目标为最大乐趣。
除了ACM,我私下还在关注另一个国际编程竞赛,IOCCC(国际混乱C代码大赛,官方网站http://www.ioccc.org/,如图1.2)。其实很多人都不知道这个比赛,我也是偶然间发现的。
图1.2 IOCCC官网历届比赛的消息公布
为什么会关注这样一个似乎不太正经的比赛?它不比算法,也不比代码的质量和风格,而是比谁的代码最乱,但是乱得要艺术,要能编译,要能实现正确的功能,如图1.3所示代码。
图1.3 第24届IOCCC(2015年)参赛代码
C语言代码还能写得如此任性?它体现了C语言在形式上的灵活性。当然,也不是单纯用代码来画画,就能被称为“乱”的,它有更多更深层的编程技巧。在这里,你可以看到C语言世界的无奇不有,各种挥挥洒洒的编程风格,以及映射出来的代码背后的那个“高手”。
我对C语言的学习热情是自始至终的,现在也还是在学习。记得大学时候我们宿舍有一个习惯,就是大考之后的晚上要倾巢出动去网吧包宿。当时流行玩CS,他们联网打得热闹。但是我对游戏毫无兴趣,就窝在一个靠边的位置上,上网看C语言代码。当时特别热衷逛编程网站,比如CSDN、PUDN等,还喜欢把代码包全下载下来,看看别人的代码是怎么写的。看了代码,就想编译试试,于是就在网吧的电脑上安装VC6.0。室友过来看我在干啥,然后就惊呆了:“都考完了,你还在看C语言?”
1.4 岔路口上选择单片机
接下来,我继续学了C++,还有后来的MATLAB、VHDL和Verlog(其实当时对硬件、数字信号处理和仿真没什么概念,所以对于后者没有多少热情)。在学C++之前,我使用VC6.0已经有一定经验了,尤其是MFC(当时有人建议我学.NET,比如C#,或者JAVA,说MFC已经过时,说MFC的意思就是Maybe Finally Canceled,即最终会被微软取消)。在系统学了C++之后,我对MFC(微软基础类库)有了深入的理解,开始阅读这方面的一些专业书籍,已经可以编写一些功能复杂的多层级的应用软件了。
到这里,我对编程的学习开始出现瓶颈,感觉到迷茫。C语言,很优雅,很强大,它的父集C++,面向对象的编程模式,可以开发专业的桌面软件。然后呢?似乎其他人用C#或者JAVA,开发软件的速度更快,做得更好。优雅不能当饭吃,在这种驱使下,我开始转入C#、JAVA、PHP、JSP、ASP这些上层应用级语言的学习,准备努力成为一个出色的软件工程师。
在这个岔路口上,我遇到了我的启蒙老师,让我再一次打开好奇之门,从而走上了单片机和嵌入式技术的道路。他就是杜撰(化名):他以年龄最小、学历最低的身份,代表黑龙江省参加全国“挑战杯”科技创新大赛,凭自己设计的“仿生蛇”获得二等奖。获奖后,他把相关技术全部无偿给了国防科大。曾作为“小崔说事”栏目的特邀嘉宾接受专访。
“你从51开始学吧,先焊个最小系统,然后点个灯!”
他给了我一个最小系统板和一些配件,还有一个叫《平凡的C51教程》的电子文档。
“你就在我这学吧,有问题问我就行。”
图1.4 我的第一个单片机实验原理图(摘自《平凡的C51教程》)
我照着图1.5依葫芦画瓢的焊完了我人生中第一个电路板。虽然惨不忍睹,但是经杜撰过目之后,评价是“还不错,能用。”然后,就让我去学C51。其实我对这个被称为“最小系统”的电路为什么要用到这些元件,为什么要焊成这样,完全没有概念。带着诸多的迷惑不解开始了我的单片机C语言学习之旅,让我开始慢慢明白了C语言课上老师说的“C语言是最贴近硬件的高级语言”这句话。
1.5 窗户纸破了
C语言,不论是变量、函数,还是分支循环,乃至于算法,哪怕是最复杂的算法,这一切的体质都是CPU内核的指令执行和访存操作(RAM和ROM)。这是起初我对C语言的理解。那如何让C语言去操控硬件产生物理效果呢?当时让我百思不得其解的是C语言是软件,发光二极管是物理上的硬件,软件是如何能够影响到物理世界的呢?小到点灯;大到“仿生蛇”产生一系列的动作;更大的比如控制火箭发动机点火。这曾经是我入门阶段无法逾越的一条思维鸿沟。
sfr P1=0x80;
void main(void){P1=0x55;While(1);}
这是我亲手写过的第一个嵌入式C语言代码。它为我第一次揭示了C语言与硬件之间的交互方式—特殊功能寄存器(Special Function Register)。
register在标准C语言中是一个修饰符。一个变量在定义的时候如何加入这个修饰符,编译器便不会把它分配在内存里,而是直接放在CPU内部寄存器里。它的目的是为了加快变量的访问速度,尤其是那些需要被频繁访问的变量。
register int i;register int sum=0;
for(i=1;i<=100;i++){sum+=i;}
上面这段代码(计算1到100的和)的执行效率就比没有register要高。
51单片机中的SFR本质上也是一些随机存储单元,它们的访问速度很快(与CPU之间采用直接寻址)。但其又有特殊之处,它们都是一些电路(片内外设)的门户出入口。向这些寄存器写入数值,会直接影响相关电路的运行和输出。
51单片机的C语言中,为这些有特殊功能的寄存器,专门增加了一个修饰符—SFR。由它定义的标识(类似变量名),是可以访问到相应的特殊功能寄存器的,即片内外设电路的出入口,从而达到控制电路的目的。诸多的电路,具有各自的功能,它们纷纷留出寄存器接口,形成一系列的SFR。通过CPU统一调配、有机控制,最终就可以完成复杂而有序的各种功能。这就是单片机,乃至于更高端的嵌入式CPU,如ARM、DSP等均采用的运作机理。而这些电路,连同CPU内核,还有存储器,当然还有连接它们之间的总线,被塑封在一起(即封装),再把电路(片内外设)的相关外部信号通过引脚引出,这就是我们所看到的单片机芯片了。其实它就是一个完整的计算机。这大大拓宽了我起初对计算机认识的范畴:凡是拥有独立计算能力,具备输入输出和存储功能的设备都可以称为计算机。从某种意义来说,算盘就是最原始的计算机,虽然它很大程度上依赖人的操作和辅助。
一直困惑我的谜雾终于变得清晰了。捅破了这层C语言软件与硬件之间的窗户纸,让我看清了硬件和嵌入式系统的本质。我觉得在硬件上,我将可以发挥更大的创造力。兴趣的泛滥再一次一发不可收拾。
基于我在C语言方面的扎实基础和深入的理解,我对单片机的学习也较为顺利。
理解了51单片机的SFR,很多东西便变得简单了。对“C语言,学得再精也不为过!”这句话有了更深的认识:C语言不光是一门语言,它影射出了整个计算机体系的运作机制,每当硬件出现进步,甚至是革命的时候,C语言必定会随之进化。(大家可以看一下GCC编译器的迭代历程,基本上就是主流编程语言衍化的写照)
我们不应再为C语言如何操控硬件而产生疑惑,因为从我们使用C语言写下第一行代码的那一刻起,其实我们就已经在操控硬件了(内存访问、数据传送、CPU执行就是硬件行为)。
下一节,看透单片机!
历时筹备一年,于振南老师结合多年实战经验,全新系统性的打造了一套课程《十天登顶嵌入式C语言之巅(高手C)》,一共100讲,总课时2000多分钟,为我们解密了很多嵌入式C语言中你所不知道、经常出错的问题。
课程7月底更新完之后恢复原价1299元,6.18日-6月20日进行三天活动,特惠499元,感兴趣的同学可以在下面海报扫码先去看看免费章节,今晚再行入手!转发下面海报到微信群或朋友圈,可以找老宇哥返现69元!
标签: