精华内容
下载资源
问答
  • 郭天祥《新概念51单片机C语言教程》序言
    千次阅读
    2019-01-29 12:13:07

           记得转专业后的半年进入大三开始接触了单片机,那时候大家学习都知道郭天祥的名声,被很多人称为嵌入式硬件的入门老师,很遗憾我的入门老师却是我的单片机课任老师(笑),虽然郭天祥的十天学会单片机的视频我没有看过,但也还是当初翻阅过他那本《新概念51单片机C语言教程》,其它知识内容现在我也记不太多了,但我依然记得那天下午翻阅第一页书的序言深深感动,如果让我说,我相信这是最为让我感到诚挚情感的序言,我也觉得那篇序言后的我至少有了一些不一样,也许是热血吧(苦笑)……


    致读者


    致阅读本书的大学生朋友

           在哈尔滨工程大学六年,我在学校国家电工电子教学基地的电子创新实验室呆了四年,这四年里创新实验室给我提供了良好的学习环境和完善的实验设备;在与众多电子爱好者的交流中,使我学到了更多的专业知识;在学校老师的教导下,让我学会了如何做一名合格的大学生。因此,在这里我要感谢哈尔滨工程大学的历任领导,我今天成绩的取得得益于他们不断完善的教育体制;衷心地感谢曾经教导过我的刁鸣教授、付永庆教授、王松武教授,没有他们对我的培养,也就没有我的今天。同时我也希望能有更多的电子爱好者加入创新实验室,在完善自我的同时,在电子行业做出更突出的业绩。
           2007年,我以全新的教学方式推出了一套讲述51单片机的教学视频课程——“十天学会单片机”,该视频自从网上发布后,得到了电子爱好者的一致好评,诸多的单片机初学者通过这套视频走上了单片机开发之路。有很多学员来信或打电话希望我能够将视频中的内容著书出版,让更多的人受益。为此,从2007年9月至2008年7月,我用了近十个月的时间将本书写完。本书的写作风格与我在教学视频中的讲课风格相似,它与传统讲授单片机的书籍完全不同,我以学单片机“过来人”的思路,抱着如何才能更容易掌握单片机的态度,理论与实践完全结合的方式清晰地讲解了单片机部分。其余大部分内容为我多年做项目的经验积累,也有部分内容来自于网络电子高手们的精华总结,应当说,在本书中有太多的知识是大家平时在书本上学不到的。在这里,先将我在大学期间的学习和生活经历与大家分享,借此鼓舞大家珍惜大学时光,多学习文化知识,开创更加美好的明天。

    我的大学

           写这篇文章的时候,我正处于硕士研究生毕业论文的准备阶段,眼睁睁看着我的大学生活即将画上句号,再看看身边有很多低年级的学生们一天天把时间白白荒废掉,我在心里替他们惋惜,在即将结束我的大学生活之际,我将我的大学几年的有意义的生活与大家分享,看过这篇文章后也许能让那些有梦想的同学为了实现自己的人生目标少走些弯路,大家要相信,大学校园——将为你提供一生最好的学习环境。
           我高中毕业于新疆伊宁市三中,2002年考入哈尔滨工程大学信息与通信工程学院电子信息工程专业,2006年以创新人才免试保送哈尔滨工程大学硕士研究生,现在已经是我在学校的最后一个学期了。记得我刚入校的时候对电子知识一点也不懂,之前我比较喜欢经商,想着好好努力,将来开个公司,做做生意,所以第一志愿报了经济管理学院,结果没被经管学院录取,而被调剂到信通学院,现在想来也算是走对了。在上大学之前,我的梦想是上大学后,一定要当班长,一定要当学生会的干部。所以我从上大一就开始加入学校的学生会,非常积极地竞选班干部,后来也如了我的愿,班长也当了,学生会干部也做了不少。因为刚上大一的时候根本不知道大学里具体要学什么知识,每天就是上课,那时一节课也不敢逃,每天的生活就是去上课、吃饭、打球和踢球,然后回宿舍瞎侃,上床睡觉。周末时,找几个同学逛逛街什么的,每周都重复着同样的生活,日子过得平平谈谈,但那时也不觉得在虚度,可能还带着刚离开高中校园的那种兴奋,认为理想中的大学生活就是如此吧。
           大一的一年就这样糊里糊涂过去了,接着就大二了。大二上学期除了在学生会的职位高了点外,其余和大一时也没什么区别,没有特别的事情发生过,偶尔逃逃不点名的公共课,天天照旧打篮球、踢足球。在大二下学期开学不久的某一天,我静静地思考了很久,我想起了我曾经有过的梦想、我追求的人生、我向往的生活,想想如果再这样过完两年,我的将来会是什么样子?那天我觉悟了。我的专业是电子信息工程,那我必须在这方面学有所成,两年都快过去了,天天抱着课本啃,现在想想我的水平和高中时一样,我学的是电子专业,从初中就开始学电阻了,到现在都六七年了,至今我连电阻长什么样都没见过,这样下去学的算是什么电子专业?我想我不能再这样下去了,于是找了同宿舍的另一位同学赖世雄,我对他说:“我们一起参加学校的“五四杯”电子设计竞赛吧!”他欣然同意了,当时我俩真是对电子知识一无所知,根本不知道从哪里开始,于是我们就从电子杂志上随便找了个类似电话控制器的小作品,把杂志上原理图中所有的元件型号抄下来,然后我俩就去电子市场上买元件。第一次买电子元件,一点专业知识也没有,我们讲的好多东西卖元件的人都听不懂,闹了不少笑话,一个电阻被人家要了一毛钱,还说这东西真便宜啊!(实际上一个电阻还不到一分钱),最后买了一堆电阻、电容和三极管,加起来一共六七十元,回来就准备照着别人的原理图焊接,很显然,这种做法从一开始就已经注定结果必然是失败的。无奈之下,我们跑去找当时教我们电路基础课的付永庆教授,我对付老师说我们想学点真正的东西,但根本无从下手,能不能请付老师帮我们想想看做个什么东西?付老师当时正在构想从学校低年级学生中选出一部分爱动手、有上进心的学生作为创新型人才来培养,他看我俩有想法,就直接对我俩说:“你们俩可以到我的实验室里来,现在我正好带几个大四的学生做毕业设计,你俩先跟着他们学习学习吧!”。当时因为是付老师个人的实验室,所以电脑不够用,于是我俩就把自己的电脑搬进了实验室,从那天起,我真正踏上了电子设计这条路。付老师又给我俩介绍了一位正在做毕业设计的大四女同学,她叫黄光亚,她正在做一个两台计算机之间用激光通信的题目,我和赖世雄每天都去实验室看着黄光亚焊电路、写程序,那时看着真是一头雾水,感觉那些东西好神奇,在计算机上写上几句程序,按完回车,看见一道激光穿过眼前,然后在另一台电脑上就能看到整屏滚动的数据。大概跟着黄光亚前后忙了一个月,对黄光亚正在做的作品的硬件部分算是有了基本的了解,但计算机部分具体怎么实现的还是不明白。那时正好赶上2004年学校的“五四杯”电子设计竞赛,我们借黄光亚的作品申报了参赛资格。在比赛那天,我们就用仅懂些基本原理的一堆元件加两台电脑等待比赛评委的到来,当时评委们问了我们这是什么原理、信号怎么调制、传输波特率多少等很多很多简单的专业问题。说实话,我们哪里知道啊!我那时连RS232电平是什么概念都不明白,评委们提的专业名词我根本就没听说过,当时也就把我们懂的东西全说了,也不知道对应评委的哪个问题。那时学校“五四杯”电子竞赛的参赛作品比较少,评委看我们才大二,而且我们的作品又是一个较完整的系统,基本没什么工作上的漏洞,为了鼓励我们,最后还是给我们发了个小奖项。
           “五四杯”结束后,赖世雄就从实验室把他的电脑搬回宿舍了,很可惜,他放弃了继续走这条路,我的电脑一直放在付老师的实验室。说到这里还要讲一点儿关于我买电脑的小插曲。大二上学期时,我的很多同学们都买了电脑,于是我也跟着买了,当时不知道买来电脑后具体要学什么东西,我的同学们买来电脑后,大部分时间在玩游戏、QQ聊天,有的同学可以从早上一直聊到晚上,玩游戏的同学可以从早玩到晚,我同学建议我玩“传奇”游戏,说很有意思,他帮我注册了账号,游戏里一个动画人物拿着一把大刀不停地砍野猪、野鹿什么乱七八糟的所谓怪物,他砍了几刀就把一头野猪砍死了,然后他说:“你看长经验了吧,多有意思,你来玩!”,我接过鼠标砍了三刀,我想破脑子也想不出他说的有意思是指什么,然后我说:“实在是无聊!”,那天起开始了我的游戏生涯,三刀后也结束了我的游戏生涯,我觉得网络游戏实在是没有意思。我更不喜欢聊QQ,可是这电脑都买了,不能一点用处都没有吧,当时那个时候,真的不知道电脑能“玩”什么和我们专业有关的东西,那些天我每天用电脑做的最多的工作就是把文件从一个分区拷到另一个分区,把一些不用的文件删除,甚至把C盘下能删的文件都删了,最后导致系统无法启动还问为什么?过了几个月我发现除了复制和粘贴功能我用得非常熟练外,其他我好像还是什么也没学会。再后来就去书店买了些制作Flash动画和制作照片的Photoshop之类的书,回来后天天学那些没用的东西。现在想来真的是太可惜了,那时真是浪费了大把大把的时间。电脑真的是可以学很多很多东西的,对于我们专业来讲,学单片机需要学C语言,学Keil、WAVE、IAR、ICC、MPLAB软件的使用,学汇编语言;在用到上位机界面编程时,需要学C++、VC++、VB语言等;用CPLD/FPGA/SOPC 时,需要学VHDL和Verlog语言,学这些语言时,可以学Maxplus、Quartus软件的使用;当用到仿真时,可以学Protues、Multisim软件的使用;设计电路板时,可以学Protell、Altium Designer、Power PCB软件的使用等;还可以学DSP 用的CCS软件、ARM用的ADS、STD软件等,所有上面我提到的这些,全都依赖于计算机系统。在今天看来,我是全部掌握了,然而这是后来我付出巨大的代价才换来的,如果我能利用好大一大二那些大好时光的话,我相信今天的我又会是另一番模样。
           接上面话题,赖世雄搬走后,付老师给了我实验室的钥匙,从那天起,实验室便成了我的另一个家。当时那个实验室只有我一个人学硬件,也只有我一个本科生,其他的硕士、博士研究生主要研究理论,所以很少有做硬件的,那时我分不清电解电容的正负极性,我拿着一个电解电容问了实验室的好几个人,结果他们也不知道,更有人说这是什么东西,我从来没见过。这件事很令我震惊,难道这就是电子专业读了四年本科,又读了几年硕士研究生的高水平大学生吗?现在大学毕业生的工作确实不好找,那不能怪别人,只是因为你确实没有别人需要你的理由。偶尔听前届的学长们说到,作为信通学院的学生,如果学会了单片机、C语言、DSP那你的前途必定是一片光明。于是我开始学习单片机,当时苦于没有硬件实验环境,身边又没有会的人请教,于是我就上网找资料,看见网上有卖单片机学习板的,那时价格都挺贵的,但我还是狠下心买了一块三百多块钱的单片机学习板,寄回来后我就开始做练习,之前也看过几遍书,可发现光看书没有任何效果,看上十遍、二十遍,感觉是学会单片机了,可当要应用到硬件系统中时,发现其实我什么也不会。后来我就边做实验边查书,这样就理解得很透彻了,就是从那时起我每天早上八点之前就到实验室了,除了选上部分课外,其他时间都泡在实验室里,一直到晚上十点多看楼的大爷用脚踹着实验室的门叫我走我才离开实验室。那时每天就摆弄单片机,没有人教我,全是我自己一个人摸索,而且当时学的是非常难懂的汇编语言。记得大一时也学过C语言,可我发现等要用的时候我什么也不会,根本和单片机联系不起来,就和没学一样,我只好选择汇编语言,大概一个月后,也就是快放暑假时,我做出来了自己的第一个单片机作品,一个电子钟。有人说你要是用单片机做出一个电子钟,那你基本上已经掌握单片机的80%了。这句话有道理,电子钟对编程的综合性要求还是相当高的。
           那时,我对单片机已经有了初步的掌握,假期的时候我报名参加了2004年黑龙江省大学生电子设计大赛,那天起我搬进了学校的电子创新实验室,我们选的题目是无线数据通信,当时指导老师让我们用FPGA做,其中还要用到VC编程及C++语言,我那时还不懂什么是FPGA,于是我开始拼命地学这些知识,每天吃饭都在实验室。省赛不同国赛,省赛是把题目先发下来,两个月后交作品就行,其实学FPGA/CPLD也和学单片机一样,关键是自己动手写程序实践,不停地写程序,然后看程序运行的效果,这两个月里我把VHDL语言搞得很熟练,但是VC还差一点。我们队一共三个人,除我之外还有路智超(做模拟电路部分)和魏旭东(上位机VC程序),魏旭东是我校理学院的,VC学得相当好,他的VC编程也全是自已业余学的。魏旭东编程时,我就在旁边看,他耐心地给我解释每一行每一句,等空闲时我自己再练,那段时间我对VC有了初步的了解。比赛结果很好,我们获得了黑龙江省一等奖,这也是我的第二次获奖,这次获奖给了我很大的鼓舞,接下来我发现必须要学单片机C语言编程了,汇编编程非常烦琐,一个全面的人才不能只将知识局限于某一方面。
           从大三开始学校里有各种电子设计竞赛,我总是积极报名参加,为自己寻找锻炼的机会,我为此放弃了我最喜欢的篮球、足球运动,再没有逛过一次街,每天早上起床、洗脸、刷牙,然后就拿着书去实验室,白天在实验室写程序、调电路,做各种硬件练习,晚上回来补充理论知识,模电、数电、高频一遍一遍地重复看,每晚差不多两点睡觉,充分地把实践与理论结合在了一起,那时我才发现大学里的理论知识同样是那么重要,而原来根本没有意识到。孤立地学习理论,不把它们与要应用的领域结合在一起,就失去了学习它的真正意义;如果只为了参加期末考试,等考完试的第二周也许就已经忘得干干净净了,如果这样学习,那只能说我们学错了方向。如果一个人的模拟电路、数字电路和高频电子线路的基础不好,那么他可能设计不出什么好的电路,我们在做硬件实践的同时再来看书中的理论知识,这样的结合是最好的。这种单调的生活我天天重复着大概过了一年,无数次实验失败时内心涌起的烦燥被我执着追求知识的欲望一次次抑制住;无数次胜利的经验告诉我,唯有坚持不懈、永不放弃才会取得最终的胜利。在这一年期间,我陆续参加了一些国家级及校里的竞赛,同时也获得了不少奖项。
           大三下学期,我基本上在学习单片机C语言编程,进一步熟练VC、C++语言。等真正学会用C语言给单片机编程时,那时才将单片机用到得心应手的程度。回想过去,学汇编语言花费了我大量的时间,假如当初有人指点我学单片机的C语言编程那该有多好,至少可以少走很多弯路。很多人说,学单片机最好先学汇编语言,以我的经验告诉大家,绝对没有这个必要,初学者一开始就直接用C语言为单片机编程,既省时间,学起来又容易,进步速度会很快。在刚开始学单片机的时候,千万不要为了解单片机内部结构而浪费时间,这样只能打击你的信心,当你学会编程后,自然一步步就掌握其内部结构了。大三暑期时,我为每两年一届的“索尼杯”全国大学生电子设计竞赛做准备,大赛时我们选择的题目是“集成运放参数测量仪”,题目是自己队员商量后选择的,我们代表队有三名成员,说实话,对于这个题目我当时心里还真没底,大家研究了两个小时,感觉不应该选这个题目,可惜题目已定,不能更换,大赛只有四天三夜的时间,第一天的早上八点知道题目,要求第四天的晚上八点交作品,所以每一分钟都是非常宝贵的,既然题目都选了不管有多大的难度都要坚持到底。计算机系的于振南主要负责写软件,他对硬件也很熟悉,完全是凭兴趣自学的,他的工作态度和吃苦精神当时给我留下了很深的印象。那四天三夜里我们没有睡过觉,尤其是于振南,他几乎是一直坐在电脑前写软件,差不多有几十个小时没有睡一分钟,他什么时候吃的饭我都没看见,最后我看他眼睛一直在流眼泪,当然不是哭了,那是看电脑屏幕看的。因为工作量非常大,要做硬件,写软件,绘制整个系统的电路图,还要写几万字的论文,都要在这四天三夜里完成。当时我们队三个人的个人能力都比较强,可能是以前大家没在一起合作过,所以到真正合作设计作品的时候还不是很默契。电路焊了一套又一套,结果都不理想。我们的作品最终在联调时失败了,每个人负责的功能能够独立实现,可联在一起就不能工作了,而评委要看的就是你的整体功能实现,不会看部分的。这次比赛我们以失败告终。以后大家如果有机会组队参加比赛要注意如下三点:①选题最关键,一定要选你们比较熟的,队里有一两个比较熟也行,但如果三个人都不会那一定要换题。②题目选定后,首先以实现基本功能为主开始做题,如果基本功能你都能做成功了,那你应该能得全国二等奖了,因为在这么短的时间里大部分队根本是什么也做不出来的,如果发挥部分再能做出一部分就可以向全国一等奖进军了,我们队失败的另一个原因就是我们直接开始做发挥部分的题目,而忽略了基本部分。③组队的安排,一定要找大家熟悉的人,最好在一起合作过,分工要明确,不要无头绪地各干各的,最后要做什么大家都不明白。
           参加完这次比赛后,我承接了一个开发项目,我找了于振南合作,我设计硬件,于振南写软件,我俩很快就把项目做完了,这也算是我们用所学的专业知识淘的第一桶金吧,获得的报酬足够支付我俩两年的学费了。在学习更多电子技术知识的同时,我和于振南共同合作开发了几个项目,一点点积累着经验。
           大四了,已经习惯了的生活和大三没有多大的变化,和我第一次参加“五四杯”的赖世雄同学每天都在忙着复习考研,最终也考上了他理想的学校。我不想再读书了,想着早点毕业出去工作。快十月份时,我们学院国家电工电子基地的王松武老师告诉我,北京某个电子公司每年在我们学校招两三个学生,要求动手能力较强的,最好参加过一些国家级的竞赛获过奖的同学,那边公司待遇很不错,王老师推荐了我,我谢过王老师准备参加该单位十月三号来学校进行的面试。我正准备面试呢,十月二号学校贴出通告,我被免试保送我校的研究生了,当时很高兴。学校有制度,学生有某方面的特长,多次获级别较高国家奖项的可以推荐免试读研究生,保送读研究生不交学费,不用考试,而且享有硕博连读的优先资格。当时值得庆幸的是,我的综合成绩平均分70多分,也就是刚够分数线,若再低一点点恐怕我也无缘这等好事了。我从内心感谢哈尔滨工程大学的领导、感谢哈尔滨工程大学的教育体制。
           大四上学期一学期我基本上都在为2005年的“枭龙杯”中国空中机器人大赛备赛,这次于振南也参加了,我主要负责飞机的自动驾驶仪,另外协助于振南一起写地面站操作平台。这次比赛涉及的知识领域非常广泛,主要包括同时刻四通道无线通信(遥控器、远程无线数据传输、远程微波图像传输、GPS信号传输)、单片机技术、计算机控制、应用软件、图像捕捉、图像识别、惯性导航、飞行器制造等技术。这次比赛我全身心投入,在调试飞机的近六个月的时间里,差不多天天早出晚归。功夫不负有心人,我校设计的无人机实现了全程无人控制全自主的自动起飞、自动巡航、自动识别静态/动态目标、自动着陆动作,开辟了我国无人机全自主飞行的先河。最终我校代表队战胜清华等多所名校,获得了全国亚军。
           大四的寒假,那时我对单片机的掌握已经很熟练了,想着应该用学会的知识来开发些产品了,一来可以解决生活费用上的开销,二来正好也可以圆我经商做生意的梦。想着很多曾经和我一样的单片机初学者可能会购买学习板,于是决定开发单片机学习板,2月份做出第一个样板,3月份做出第2版,4月底建立个人网站“天祥电子”:h t t p : / / w w w . t x m c u . c o m / ,在经过3个月共改进了7版后,最终定型TX-1C单片机学习板为最终产品。4月份中央电视台“我的太阳”摄制组来到我校特别为我拍摄了专题片“我的太阳——创新360之郭天祥”,该片以我参加2005“枭龙杯”中国空中机器人大赛为背景,讲述了我在哈尔滨工程大学几年的创新学习生活,5月7日在中央电视台教育一台播出,同时我远在新疆的家人在电视里看见了已经离开家乡几年的我,这也是我生平第一次上中央电视台的专题节目。
           从大四下学期开始,我一边管理自己的网站,一边学习DSP(数字信号处理器),因为我清楚,在科技日新月异的今天,仅靠会一点单片机而在社会上立足是万万不行的,我必须充分利用在大学校园里的这几年时间,以最快的速度尽可能多地掌握各种电子技术知识,一旦出了校园,恐怕再也不会有太多的学习时间了。由于学校实验室里有DSP实验箱,这样学习起来就方便多了,一台DSP实验箱的价格都在七、八千甚至上万元,以个人能力购买还是很费劲的。学硬件主要就是做实验,写程序、下载程序、观察现象、认真思考、修改程序、再下载程序、再观察现象……如此重复,直到得到满意的现象结果,只要抓住这条思路,任何硬件都会在很短的时间内掌握。大四下学期,我的同学们都在为各自的本科毕业设计而忙碌,而我却在设计自己的DSP实验板,由于DSP实验板上使用的芯片大多为多引脚贴片封装的,所以至少要设计成4层的PCB板,那是我第一次画4层PCB板,用了近一个月才绘制完成,值得庆幸的是,板子做出来后完全正常,我又用了一个月将其调试完成。差不多在4个月的时间里,我完成了对DSP从认识到制板再到最后调试实验板通过的全过程。因为之前有单片机的基础,本科毕业设计对我来讲是非常容易的,在大多数同学花半年的时间去研究的时候,我从设计到完成用了不到10天的时间,而且在这10天里还帮了很多同学的忙。
           转眼就到了本科毕业聚会了,大部分同学的大学生活就此画上了句号。我亲眼看着他们如何一步步地成就了自己的梦想,也亲眼看着他们如何一次次地重复着自己的生活,同时也亲眼看着他们如何一天天地堕落下去。从那天起,大家又将迎来各自的全新环境,在那里,也许有人庆幸,也许有人后悔,但无论怎样,自己的路自己选择,当然要自己走下去。
           知识的海洋永无尽头,在路上的我不能停止,还没等到研究生开学,我已经为这两年半的时间制定了全面的计划。从假期开始,我就开始接触ARM(嵌入式系统)了,在我看来,如果不涉及ARM的操作系统,那么它的学习方法还是和单片机一样,在开始阶段,我就把它当成一块单片机来用,当然它的功能要比单片机强大得多。半年后,我和同学宋宝森还有于振南三人共同承接了一个用三星ARM7做主控制器的工程项目,该项目所涉及的知识也非常之广,内容涵盖单片机系统、嵌入式ARM7、GPRS网络、Internet应用、图像采集、图像处理及远程传输、TCP/IP协议、移动通信技术、码分多址技术、网络数据解析、模拟电路、数字电路、高频电路、射频无线数据传输、工业传感器等技术。在这个项目设计中,我发现,上面我提到的这些知识领域,没有几个是我大学专业所学到的,就算是学到了也没有几个是真正能应用到实际当中的,在高科技主导社会进步的今天,单纯掌握某一狭窄领域的知识是远远不够的,我们只有不断地学习,不断地应用,再学习,抱着这种态度才能让知识得到最大的发挥,让科技不断地进步。
           2007年初,通过学校的科技创新立项,我申报了“远程无线可控潜水器”项目,最后以全校唯一特大重点项目获得批准,学校和院里都给予了全额资金的支持,在经过我和团队成员5个月的努力后,我们的作品终于试水成功。该作品获2007年学校“五四杯”一等奖,同年获得黑龙江省“挑战杯”大学生电子设计竞赛一等奖。至我离开学校时,该项目还在由团队其他成员进一步改进完善中。
           在研一阶段,我利用两个寒暑期在学校举办了为期十天的单片机培训班,我以全新的授课方式,以初学者最容易快速入门的方法为学员讲解了51单片机的用法,我在课堂现场带领学员做实验,每天课后学员们自己再练习写程序,经过十天的强化训练,课程结束时,几乎所有的学员都能够独立编程操作51单片机的各个功能了。在同年的“索尼杯”全国大学生电子设计大赛中,我担任学校指导教师,在大赛现场我看到了许多曾经在我的课堂上听课的学员的身影,而且他们最终都取得了喜人的成绩,我由衷地感到欣慰。为了让更多的单片机初学者受益,我将授课过程全程录像,然后将其免费发布到网上,自该录像在网上发布后,得到了很多学员的高度赞扬,甚至有许多国外的留学生打来电话向我致谢。
           2007年9月,我以实习生的身份到某能源股份有限公司做硕士课题,当时与我同去的还有很多其他院校的本科毕业生,他们有与我同专业的,也有自动化专业的。我与几个老员工是公司仅有的能够独立开发项目并且真正懂硬件编程的人,我们拿着高薪,而且公司还把我们当成宝贝,其他新来的大学生们在夸奖我们能力的同时也叹息自己大学里到底学了什么,从无奈的语气中我看出了他们的悔恨,然而今天的他们在现实中又有什么办法呢?每周6个工作日、每天8小时、迟到扣工资、早退扣工资、请假扣工资……这就是摆在他们面前不可改变的现实,每月等待那么一天的到来,而薄薄的信封里也仅仅够每个月的基本生活费。年轻的朋友们啊!同是从大学校园里走出的大学生,这就是差距,而且这只是差距的开始。实习期间,在与公司技术人员的交流中,在产品一步步地改进完善中,我的专业知识得到进一步的升华,我深刻地认识到,仅仅死学书本上的理论而不与实际硬件结合进行实践,这样的理论没有用;仅仅在校园里做的简单硬件实践如果不与工业现场应用结合,这样的实践是不成熟的。至2008年6月我离开公司,我为公司研发了一系列的太阳能充/放电控制器、太阳能路灯控制器和联通移动基站的太阳能电站充/放电控制器,并且得到了批量生产和应用。
           大学生活是我们人生中最宝贵的经历,我们付出了四年光阴的代价,我们应该也必须为此有所收获。很多同学在大学校园里迷失了方向,不知道自己来到这里究竟是为了什么,单纯的认为毕业后找个好工作就万事大吉了,可你们是否想过,没有真正的本领如何能找到好工作?如何能为这个社会做出贡献?更现实一些,没有一份好工作如何买房成家,建立起属于你自己的幸福快乐的家呢?真本事不是靠混日子混出来的,我们身边有很多机会可以发挥自己的能力,实现自己的理想,即使这些机会不是很明显地让我们看见,我们也应该努力地去争取。偶尔的娱乐是可以的,可是成宿在网络游戏中挥舞大刀的同学们,那里可以砍出你的未来吗?适当的运动也是应该的,可整天都泡在篮球场上的同学们,你觉得你还有希望成为第二个乔丹吗?哥们义气固然重要,可三天两头为朋友两肋插刀,你的肋骨够用吗?年轻人应该有更高的追求,你要为你的将来做好准备,外面的世界很精彩,外面的世界也很残酷,你活着的每一天都应该好好珍惜!
           我的大学生活即将结束,这就是我大学的六年生活,有人认为我可能失去了很多东西,但我得到的却是无价的,这样的人生经历可能有很多人惋惜,然而这样的结果必然有很多人羡慕。为了追求我的梦想,我充分利用每一天每一秒,为了实现我的目标,我在知识的海洋里吸取每一点每一滴,我感觉到的是充实。只要你有技高别人的想法,你有出人头地的愿望,你能下得了做一件事情的决心,你有能坚持下去的毅力,只要你天天都在进步,用不了多久,你会发现一个全新的你将重新站立在大家面前。希望各位学弟学妹们珍惜你们拥有的,在大学里好好努力,四年时间过得飞快,当瞬间过后发现自己和刚入校时并没有太大的变化时,那时后悔恐怕真的晚了!

    郭天祥

    2008年11月

    更多相关内容
  • 郭天祥51单片机开发板原理图pdf,
  • 51单片机 开发板原理图郭天祥),不用于商业用途,只用来学习参考使用
  • 郭天祥10天学会51单片机
  • 郭天祥51单片机开发板原理图,可初学作为硬件设计参考
  • 郭天祥十天征服单片机 模拟板,好用,对于不没有硬件资源的童鞋来说,这东西太好用了,本人就是用模拟版学完了他的51教程。
  • 郭天祥51单片机学习板原理图:KP-1C单片机实验板原理图
  • 郭天祥51单片机教程原理图,有需要的下.
  • 这个是郭天祥51单片机开发板原理图1的附属部分建议下载一的话就同时下载二
  • 结合TX-1C原理图看,赋给相应管脚低电平或高电平,结合DA接口.bmp看,DI0到DI7是数据口连接单片机的P0口,其它的为控制口或电源口,CSDA连接单片机的P3.2口(使用时要给低电平),WR连接单片机的P3.6口(使用时要给...

    全局变量:该变量在主函数外面定义

    局部变量:在函数体内部定义

    当子函数内部定义的变量,该变量的变量名和全局变量名相同并且类型相同时,在主函数调用该子函数时,该子函数的该变量有效,将全局变量屏蔽掉

    D/A,数字量(Digital):例如直接从5V跳到0V;模拟量(Anolog):例如从5V缓慢变化到0V,有个变化的过程。

    例子:1111 1111    对应    5v(或50mA)

    1000 0000    对应    2.5v(或25mA)

    0000 0000    对应    0v(或0mA)

    当都接0时,从最右边的电阻依次并联算起,到最左边的2R电阻处再和右边全部的电阻(并联后也为2R)为R,所以Vref/R= I, Io2=1/2 I,Io1=0

    当I7接0,其它接1时,I7处的电流为I7,I7右边的电流也为I7,所以Io2=1/2 I

    当I7接1,当I6接1,先不看其它支路,Io1=(1/2 )*Vref/R+(1/2 *1/2 ) *Vref/R

    以此类推,到最后全接1时Io1=Vref/R(1/2+1/2*1/2+……+1/2的八次方)

    DAC0832,这里用直通方式,一种简单的方式会了其它方式照猫画虎就行

     Vref为输入参考电压,这里IOUT2接地,IOUT1作为输出,当需要模拟电压时IOUT1接运算放大器并且连接Rfb(反馈电阻)

    类似这样上面有横杠的表示低电平有效;上图中连线上连接与门的圆圈表示取反 

    CS表示片选信号,Chip Select

    下载数据文档:Datasheet即数据文档网站:www.21ic.com-->左边的IC处填写”DAC0832”,“资料”-->下载Datasheet。www.alldatasheet.com

    看资料芯片看串并行方式,接口说明,转换位数和转换速率,操作时序

    www.maxim-ic.com,如果是并行的一次把数据都读走,但浪费I/O口

    见dac0832资料,P5图,ts指不稳定的输出范围,之后稳定

    选取DA时,要先知道设计的产品的运行速度,然后选取DA的转换速率,根据产品的精度选取DA的精度即位

    串行MAX531的资料:DIN是数据输入端,SCLK是数据时钟,DOUT是输入电压,VDD是电源,VOUT是输出电压,REFIN是参考电压,AGND是接地

    时序图中,网格表示无所谓高低电平,两个箭头包起来的数据表示有效数据,MAX531的资料P8中图Figure1:SCLK上升沿读走位(DIN)的数据,八个上升沿就读走八个位数据。

    看这种资料主要看各个管脚怎么使用以及时序图

    时序图中,阴影表示高低电平都可以;两个箭头包起来的数据表示有效数据,例如DIN

    SCLK上升沿读走位(DIN)的数据,八个上升沿就读走八个位数据

    DA资料中,看多少位,速度,管脚,时序图,有的接法不同,时序图就不同

    找资料,根据资料设计电路,按资料上的器件接法连接,把资料上的电器件(如电阻的阻值,电容的法拉)都表示清楚,然后画Protel图,再做出PCB板子,拿到车间生产焊接再连接单片机就制作出来了。

    dac0832PDFP5,图中表示CSILE要先给低电平,然后WR给低电平,随后有效数据就传送过去,经过一小段时间稳定一下,IOUT1IOUT2再进行有效输出

    直通连接方式:直接送数据,IOUT1口就输出;结合TX-1C原理图看,赋给相应管脚低电平或高电平,结合DA接口.bmp看,DI0DI7是数据口连接单片机的P0口,其它的为控制口或电源口,CSDA连接单片机的P3.2口(使用时要给低电平),WR连接单片机的P3.6口(使用时要给低电平);IOUT1口输出的P523用跳线帽(又叫短路子)短路,IOUT1输出的电流直接穿过发光二极管到地上,输出的数字量变化,那么输出的模拟量就变化,模拟量的变化体现在流过发光二极管上的电流,发光二极管就有明暗的变化可以判断有没有把DA操作起来,1口可以外接运算放大器;DA输出口的器件,当23短路后直接通过发光二极管接地

    赋给低电平

    输出最高电压,点亮DA的灯,一上电P0口到P3口就输出最大值,所以开始DA的灯就亮:

    #include<reg52.h>

    sbit csda=P3^2;//注意csda(数模)和csad(模数)相区别

    sbit wr=P3^6;

    void main()

    {

           csda=0;

           wr=0;

           P0=0xff;//输出最高电压,P0=0时,关闭DA

           while(1);

    }

    我的随笔程序:证明按照AD的时序图来操作是可以的,可以让片选CSDA高低电平变化,并且WR高低电平的变化:

    #include<reg52.h>

    #define uint unsigned int

    #define uchar unsigned char

    sbit csda=P3^2;//注意csda(数模)和csad(模数)相区别

    sbit wr=P3^6;

    sbit dula=P2^6;

    sbit wela=P2^7;

    uchar aa;

    void delay(uint z)

    {

           uint x,y;

           for(x=z;x>0;x--)

                  for(y=110;y>0;y--);

    }

    void main()

    {

           while(1)

           {

                  dula=0;

                  wela=0;

                  aa++;

                  if(aa==256)

                         aa=0;

                  csda=0;

                  wr=0;

                  P0=aa;//输出最高电压,P0=0时,关闭DA

                  delay(5);

                  wr=1;

                  csda=1;

                  delay(5);

           }

    }

    DA灯由灭到逐渐变到最亮,时间2s,由最亮到逐渐变暗到灭,时间2s

    我的程序:

    #include<reg52.h>

    #define uint unsigned int

    #define uchar unsigned char

    sbit csda=P3^2;

    sbit wr=P3^6;

    sbit wela=P2^7;

    uchar flag;

    int aa,bb,cc;

    void init()

    {

           csda=0;

           wr=0;

           P0=0;

           TMOD=0x01;

           TH0=(65536-7812)/256;

           TL0=(65536-7812)%256;

           EA=1;

           ET0=1;

           TR0=1;

           wela=1;

           P0=0xff;

           wela=0;

           bb=255;

    }

    void main()

    {

           init();

           while(1)

           {

                  P0=cc;

           }

    }

    void timer0() interrupt 1

    {

           if(flag==0)

           {

                  TH0=(65536-7812)/256;

                  TL0=(65536-7812)%256;

                  aa++;

                  if(aa==256)

                  {

                         aa=0;

                         flag=1;

                  }

                  cc=aa;

           }

           if(flag==1)

           {

                  TH0=(65536-7812)/256;

                  TL0=(65536-7812)%256;

                  bb--;

                  if(bb==-1)

                  {

                         bb=255;

                         flag=0;

                  }

                  cc=bb;

           }

    }

    DA灯亮灭变化的同时发光二极管做加法变化:

    #include<reg51.h>

    sbit wela=P2^7;

    sbit dula=P2^6;

    sbit dawr=P3^6;

    sbit csda=P3^2;

    unsigned char a,j,k;

    void delay(unsigned char i)

    {

      for(j=i;j>0;j--)

        for(k=125;k>0;k--);

    }

    void main()

    {

      wela=0;

      dula=0;//因为下面控制P1口,段选和位选给零,不让数码管干扰

      csda=0;

      a=0;

      dawr=0;

      while(1)

          {

             P0=a;

             P1=~a;

             delay(50);

             a++;

    }

    }

    A/D例如把08V电压分成百位就是全部量化分配到0255

    用的最多的是逐次逼近式和双积分式

    PPTP16VIN模拟量的输入端,EOCEnd Of Convert)转换结束(输出一个信号,告诉转换结束,可以把数据读走),倒三角是比较器,OEOutput Enable)是使能端,D/A转换器有A/D转换的功能

    倒三角是比较器,倒三角上面的线(带圆圈的是上面)输出比下面高输出就是1,上面的线输出比下面低输出就是0;图中最右边,从右向左看,先将作为参考电压,这里将八位D/A转换器的最高位先置1,通过D/A转换器后的对应电压是 = /2,输出电压为 = /2,与 比较,如果大,则置1到N位寄存器最高位并传给D/A转换器,如果小,则置0到N位寄存器最高位并传给D/A转换器和锁存缓存器,再在D/A转换器的第二位置1,进行判断,如此类推,进行八次后,EOC口输出一个信号给单片机,告诉转换结束,单片机收到EOC信号后给OE一个低电平再将数据读走

    见dac0832资料P1的典型管脚连线图,11到18管脚是数据口(TX-1C型单片机实验板原理图中的DB1到DB8),用来送数据,接单片机的P1口;INTR是中断口,当芯片转换完给单片机一个中断,要接单片机的外部中断(P3.2口或P3.3口),开发板中AD转换器没;使用中断,就是过段时间去读,肯定能转换完;RD和WR接单片机的RD和WR,即单片机的P3.6口和P3.7口;CS即片选,接锁存器(控制数码管位选的那个锁存器)的CSAD;VCC接5V电压;CLK R和CLK IN接管脚19和4是一个RC振荡电路,作用是提供频率让A/D转换;VIN(+)和VIN(-)采集电压,组成差分电路,输出差分信号,两条电路用来比较,可以采集桥式电路(见下图,可以做电子秤,上面的支路的第一个电阻是滑动电阻,两条并联的支路的两个电阻之间的导线连在VIN(+)和VIN(-)上,得到的压差来得出压力值);A GND表示模拟电压地端,D GND表示数字电压地端,之所以分开是防止它俩有干扰;Processor是处理器,即单片机(51,arm等);AD转换器在开发板中的电源灯下面,ADIN在AD转换器的左侧,即有跳线帽的,为了扩展,可能接模拟输入端,开发板中将其1和2短路,上面的滑动变阻器对应开发板中AD转换器的右边,可以调节上面的旋钮,ADIN的1连接着AD转换器的6管脚,6管脚下面的7管脚接地,所以6管脚就能检测到0到5伏之间的变化,ADIN的1管脚和AD转换器的6管脚之间的10k电阻是限流电阻,保护不被击穿,但电压是不会变的;AD转换器的9管脚是 ,开发板上用两个1K电阻分成2.5V

     P5的时序图,第一个图是开始转换,CS给低电平,WRCS低电平期间给个低脉冲,即在CS给低电平之后稍过一段时间WR给个低脉冲,实际内部转换状态(Actual Internal Status Of The Converter)的BUSY表示AD转换过程,转换完INTR给个低电平通知中断,实际内部转换状态和INTR可以不用程序实现,只是表示转换过程;第二个图是读取数据,如果要AD转换器一直工作就让CS一直置0;中断INTR通知后,给RD一个低电平,在RD低电平到高电平变化的瞬间把数据读走,开发板上不用中断,所以不用考虑中断;程序中就让RD为高,变低,再为高,读走数据,即送到P1口;AD转换器的CSAD连接着锁存器,程序中直接控制锁存器就行

    开发板中的AD转换器的数据口也连接着发光二极管,设计一个程序,就不停的启动读,数字量变化八个发光二极管就亮灭变化

     

    见ad0804的PDF的P18,是内部工作频率,八个数据全转换完需要八个,R=10K,C=145PF,由公式可得,开发板上的C很大,所以程序启动后要等一会再读数字

    利用AD转换器动态显示发光二极管:

    #include<reg52.h>

    #define uchar unsigned char

    #define uint unsigned int

    sbit wr=P3^6;

    sbit rd=P3^7;

    void delay(uint z)

    {

           uint x,y;

           for(x=z;x>0;x--)

                  for(y=110;y>0;y--);

    }

    void init();

    void start();

    void main()

    {

           init();

           while(1)

           {

                  start();

                  delay(20);

                  rd=0;//rd低电平才能读数据,见时序图

            delay(10);//一定要延时一会将数据读走再将rd变高电平,见上面的总结

                  rd=1; //rd高电平为了下次变低电平后读数据

                  delay(10);

           }    

    }

    void init()

    {

           P0=0;//即将csad赋给0,A/D转换器被选用

    }

    void start()

    {

           wr=1;//0804的资料上的时序图,启动AD转换

           wr=0;

           wr=1;     

    }

    A/D转换器的数据口接在DB1DB8上,DB1DB8连在发光二极管上,所以A/D转换器的数据口有数据输出,发光二极管也会亮

    旋转AD转换器右边的电位器的旋钮,发光二极管的亮度会变化。

    TX-1C型单片机实验板原理图中单片机和数码管中间的是USB设备开发芯片,右边是USB下载接口,晶振下面是复位电路,复位电路下面是DS18B20是数字温度传感器,DS18B20下面是串口,串口那,电容处的104表示10* PF(皮法),103是10*PF,180是18*;电阻4K7是4.7K5R85.8欧姆;封装(电阻,电容封装方式):0805,还有1206封装,3216封装,0604封装,0302封装(数字越小封装越小);键盘下面的P6P9是扩展口(下面标明了对应的P0P1P2P3),即开发板上单片机左右的两排针;扩展口的右边是EEPROM,再右边是1602液晶接口,再右边是1280液晶接口;晶振右边是下载程序的指示灯,键盘上面是AD转换器

    开发板上,黄色的是电容,黑色的是电阻

    课件练习:

    AD模拟数字的模拟量读回来,转换成十进制数显示在数码管的前三位上,0255

    我的程序:

    #include<reg52.h>

    #define uint unsigned int

    #define uchar unsigned char

    uchar bai,shi,ge,temp;

    sbit dula=P2^6;

    sbit wela=P2^7;

    sbit wr=P3^6;

    sbit rd=P3^7;

    uchar code table[]={

    0x3f,0x06,0x5b,0x4f,

    0x66,0x6d,0x7d,0x07,

    0x7f,0x6f,0x77,0x7c,

    0x39,0x5e,0x79,0x71,

    0x76,0x79,0x38,0x3f,0

    };

    void delay(uint z)

    {

           uint x,y;

           for(x=z;x>0;x--)

                  for(y=110;y>0;y--);

    }

    void start()

    {

           wela=1;

           P0=0;

           wr=0;//下面不能加延时程序delay(10),一旦加入延时,wela=1;P0=0;这两句就把数码管//打开,让八个数码管一起显示,而没有延时,刚打开数码管就wela=0关闭就不会出现八个//数码管一起显示

           wr=1;

           P0=0xff;

           delay(10);

           wela=0;

    }

    void display(uchar aa,uchar bb,uchar cc)

    {

           dula=1;

           P0=table[aa];

           dula=0;

           P0=0xff;

           wela=1;

           P0=0xfe;

           wela=0;

           delay(10);

           dula=1;

           P0=table[bb];

           dula=0;

           P0=0xff;

           wela=1;

           P0=0xfd;

           wela=0;

           delay(10);

           dula=1;

           P0=table[cc];

           dula=0;

           P0=0xff;

           wela=1;

           P0=0xfb;

           wela=0;

           delay(10);

    }

    void init()

    {

           P0=0;

    }

    void main()

    {    

           init();

           while(1)

           {

                  start();

                  delay(20);

                  wela=1;//必须有这句,否则会出错,现象是只显示255,因为上次存储器锁存的是//P0=0xff,如果不打开wela,锁存器仍然锁存0xff,而不会把新的P0值存入并显示

                  P1=0xff;

                  P0=0;

                  rd=0;

                  temp=P1;

                  rd=1;     

                  P0=0xff;

                  P1=temp;

                  delay(20);

                  display(temp/100,temp%100/10,temp%10);       

           }

    }    

    课件的程序:

    #include<reg51.h>

    #include <intrins.h>

    #define uint unsigned int

    #define uchar unsigned char

    sbit adrd=P3^7;                          //IO口定义

    sbit adwr=P3^6;

    sbit diola=P2^5;

    sbit dula=P2^6;

    sbit wela=P2^7;

    unsigned char j,k,adval;

    void delay(unsigned char i)          //延时程序

    {

      for(j=i;j>0;j--)

        for(k=125;k>0;k--);

    }

    uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,                            //数码管编码

                            0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

    void display(uchar bai_c,uchar sh_c,uchar g_c)                 //显示程序

       P0=table[bai_c];             //显示百位

       dula=1;

       dula=0;

       P0=0xfe;

       wela=1;

       wela=0;

       delay(5);

       dula=0;

       P0=table[sh_c];        //显示十位

       dula=1;

       dula=0;

       wela=0;

       P0=0xfd;

       wela=1;

       wela=0;

       delay(5);

       P0=table[g_c];         //显示个位

       dula=1;

       dula=0;

       P0=0xfb;

       wela=1;

       wela=0;

       delay(5);

    }

    void main()           //     主程序

    {

      uchar a,A1,A2,A2t,A3;

        while(1)

          {

        wela=1;

        P0=0;                       //选通ADCS

        adwr=0;                //AD写入(随便写个什么都行,主要是为了启动AD转换)

        _nop_();

        adwr=1;

        P0=0xff;                    //关闭ADCS

        delay(10);

    wela=0;                     //关闭有AD片选信号锁存器的锁存端以防止在操作数

    //码管时使AD的片选发生变化

           for(a=20;a>0;a--)        //需要注意的是ADC0804在写和读之间的时间间隔要足够//长否则无法读出数据

        {                           //这里把显示部分放这里的原因也是为了增加写读之间//的时间间隔                                                                                                                                                                                                                           

            display(A1,A2,A3);

         }    //送去显示各位。

         wela=1;                   //重新打开有AD片选信号锁存器的锁存端

         P1=0xff;                    //读取P1口之前先给其写全1

         P0=0;                       //选通ADCS

         adrd=0;                     //AD读使能

         adval=P1;                   //AD数据读取赋给P1

         adrd=1;

         P0=0xff;                     //关闭ADCS

         adwr=0;

         P1=adval;                    //同时把AD的值送八个发光二极显示

         A1=adval/100;            //分出百,十,和个位

         A2t=adval%100;

         A2=A2t/10;

         A3=A2t%10;

       };

    }    

    AD的值读回来,赋给DA,即调节AD的电位器时,DA对应的发光二极管也会发生变化:

    我的程序:

    #include<reg52.h>

    #define uint unsigned int

    #define uchar unsigned char

    sbit adwr=P3^6;

    sbit adrd=P3^7;

    sbit dula=P2^6;

    sbit wela=P2^7;

    sbit csda=P3^2;

    uchar temp;

    void delay(uchar z)

    {

           uchar x,y;

           for(x=z;x>0;x--)

                  for(y=110;y>0;y--);

    }

    void init()

    {

           temp=0;

           P0=0;

    }

    void start()

    {

           P0=0;

           adwr=0;

           adwr=1;

           P0=0xff;

    }

    void admode()

    {

           csda=0;  

           adwr=0;

           //temp=P1;

           delay(1);//调试的时候,由于我不能确定P0是否被赋值为temp,这里可以添加一句//temp=0xfd,再调试中下面的语句csda=1加断点,看看P0是否等于temp,如果是说明AD

    //转换器的输出值temp确实被DA转换器读入,并将此值送给P0来控制DA转换器的发光//二极管

           P0=temp;

           csda=1;

           delay(10);

    }

    void main()

    {

           init();

           while(1)

           {

                  start();

                  delay(10);

                  P1=0xff;

                  P0=0;

                  adrd=0;

                  temp=P1;

                  adrd=1;

                  P0=0xff;

                  delay(20);

                  P1=temp;//发光二极管亮,可以判断AD转换器是否起作用

                  admode();             

           }

    }

    展开全文
  • 郭天祥10天学会51单片机 原理图 郭天祥10天学会51单片机 原理图
  • 郭天祥10天学会51单片机全套资料,包括 所有程序 所有课后作业+答案 ppt课件 (以上分为总结到一个文件的、和分课程按目录放的,两套) 郭天祥TX-1C单片机STC89C52仿真版 TX-1C型单片机开发板原理图
  • 郭天祥51单片机_TX1C_原理图_cadence_orcad层次划分图_自学用的仅供参考pdf,
  • 郭天祥开设计的51单片机开发电路板1 建议下载后打印出来看
  • 郭天祥51和PIC单片机原理图,跟天祥电子的开发板配套。
  • 此开发板原理图郭天祥 TX-1C型单片机开发板原理图,本图详细的介绍了开发板中的电路原理与相关芯片的连接使用方式。
  • VPD备用电源的输入端,当主电源VCC发生故障降低到某一规定的低电平时,将+5V电源自动接入RST端,为内部RAM提供备用电源,以保证片内RAM信息不丢失,从而保证单片机在复位后能继续正常运行(第二功能暂时不用) ...

    学习引脚的功能

    9引脚

    • 复位管脚,当给2个机器周期(24个时钟振荡周期)的高电平时会复位,单片机正常工作时会给0.5v的低电平
    • VPD备用电源的输入端,当主电源VCC发生故障降低到某一规定的低电平时,将+5V电源自动接入RST端,为内部RAM提供备用电源,以保证片内RAM信息不丢失,从而保证单片机在复位后能继续正常运行(第二功能暂时不用)

    RXD:串行输入口

    TXD:串行输出口

    单片机通过电脑下载程序就是通过这两个IO口,单片机内部有固件程序,上电后先和计算机通信一次,确定计算机是否有发送下载命令,如果没有,就执行内部程序,如果有,就进行交互,把要下载的程序下载进去。所以需要冷启动,单片机只有启动的时候才会检测是否下载。

    INT0、INT1:外部中断0、外部中断1

    T0、T1:定时器0外部计数输入,定时器1外部计数输入(有定时器和计数器功能),定时时内部自动定时间,与管脚无关。外部计数器的输入端:给端口加一个方波(高低电平变化的波形)设置内部寄存器设置为计数器后,它就可以数数,数你输入了多少方波,即一共有多少次高低电平变化。做频率计,测一个信号源频率为多少,若为正弦波,通过比较器变为方波,然后输入到这个端口,写程序控制单片机进行计数,就可以做出计数器。三角波通过积分也可以变成方波。方波就可以直接读取频率了。

    WR、RD:外部数据存储器的写选通、外部数据存储器的读选通(暂时不用,用的是片内存储器,等对单片机了解加深后,自己就会明白)

    P3.0~P3.7每一个都有相应的寄存器设置,并不是一个寄存器设置了7个。

    XTAL1、2:晶振输入端,外部加晶振时用


     复位电路

      

    开关按下后,VCC将于1K电阻这里接通,电容隔直通交,根据分压(1/(10+1)  *5),RST这里电压接近5V,按下去的时候肯定大于24个时钟周期(24个时钟周期很短)将复位。上电时也是自动复位,上电时电容充电,两个极板就会有电压,然后会复位,充完点后会慢慢放电,通过10K电阻流到地。放电时间:τ(tao)=根号下(RC)


     晶振电路

      

    两个电容的作用是上电时帮助晶振Y1起振,晶振正常工作时是输出正弦波,有时不加电容可能起不来,上电后给电容充电,电容放电帮助起振。一般12MHz左右用30P电容,6MHz一般用20P。


     29引脚(PSEN):一般不用,空着就可以

    29-31,9一般都是用于编程的,at公司的的89c51必须要专门的编程器编程,编程时VPP要加12V电压才能把程序写进去,PROG(program),ALE:单片机正常工作时,可以输出1/6个时钟周期的脉冲(方波),若想检测单片机是否正常工作,这里放一个示波器,检测是否是晶振的1/6频率输出方波。

    EA:内部程序存储器选择控制端,高电平时访问内部存储器,但在程序计数器值超过0xff时,即51单片机4KB,记值范围0~0xfffh,将自动转为执行外部程序,即超过内部程序时会自动转为执行外部存储器的程序。低电平时只访问外部存储器的程序,不论是否有内部程序存储器,对于8031来说,因为没有内部存储器,该脚必须接地,只能选择外部存储器。现在很少用外接的程序存储器,科技发展快,单片机内的存储空间越来越大。所以一般EA接高即可。

    单片机这里EA直接高电平,内部执行程序。

    P0是双向8位三态(高电平,低电平,高阻态)IO口,与P1~P3不同,他们是8位准双向。P1~3线内均有固定的上拉电阻,P0没有,当P1~3做输入使用时,要向该口先写1,准双向,即要准备一下才能成为双向口,输出时可以直接用,准双向IO口没有高阻的浮空状态,即无高阻状态,P0线内无固定上拉电阻,由两个MOS管串接,既可开路输出,又可以处于高阻的浮空状态,故称之为双向三态IO口。

    至此管脚介绍完毕,29PSEN不用记,30ALE正常工作时1/6晶振频率的方波,31EA程序从哪里执行的标志,30、31的第二功能VPP、PROG编程用的,10~17第二功能边学边记,没必要一次记住。学单片机就是通过学程序把这32个IO随意控制,设计电路要不断的积累经验(网上查资料,找书看),调试。


    特殊功能寄存器有P0~P3,PSW、IP、IE,实际上对单片机本身来说开放的IO口,P0~P3就是4个寄存器,对他们操作能直接体现出高低电平变化,每个寄存器都占有一个地址。  (之前已经分散的说过)


     

    点阵型发光二极管,其中一个管有的是能发三种颜色(三原色)可以控制其中的一个两个或者三个发出不同的颜色。这种不同的颜色变化是一个点一个点构成的,会形成真彩,所有颜色都出现了,电视信号接收到后经过信号分析,送到屏幕就成了电视。所有的电子设备都可以做,空调也可用单片机做出,内部有变频器,单片机控制它的频率变化,然后运行空气压缩器,空气压缩器运行压缩空气产生空气变化,这是制冷,加热,内部有温度传感器,有加热管,温度到某一个温度自动把它停掉,用继电器切换加热管是否加热。功能强的单片机也可以直接控制CRT显示器,也是三原色的三根线控制,不过是输出的模拟信号,模拟量不同,输出的亮度不同,还有两根数据线X场、Y场,控制在屏幕显示的位置,再三根线控制颜色,不停地扫描就出现图形。(..基本废话,就当了解吧)

    数码管是使用7段或者8段LED发光二极管显示的,七段就是不带“点”(dp)

     共阴极就是发光二极管阴极接在一起,共阳极就是发光二极管阳极接在一起。接在一起的地方叫做公共端,公共端是接地还是接电源就是高低电平,是由单片机IO口决定的。

    举例,若显示1,就是数码管bc两个led亮

    • 共阴极:bc两个为1,其它为0
    • 共阳极:bc两个为0,其它为1

    然后高低位从高位dp到单位a,共阴极就是0x06,共阳极为0xf9

    什么是段选,什么是位选?

    • 位选:构成一个数字+一个点的8个led灯是一位,即一个数码管,当许多位连在一起,就需要选择亮哪一位,而起选择作用的就是位选,就是那个公共端。
    • 段选:构成一个数字+一个点的8个led灯的每一个是一段,控制哪一段亮的就是段选,即a~dp。

     

    总线形式画出来的,P20~P23位选,P00~P07段选,段选加上拉电阻,单片机IO口输出的电流很小,可能不到1mA,发光二极管点亮需要5~10mA电流,所以需要上拉电阻。当P00位高,P20位低时,电流会从IO口和VCC一起流经a然后到P20,这种是最简单的接法,我们电路板不同,但原理类似。疑问:如果P00位低,P20位低,那么电压不就直接从VCC进入IO口和LED了吗?

    郭天祥教学实验板,图中有错误,红线划掉了,每个管脚控制一个段,WE是公共端阴极,所有段选全部连在一起,图中看到每个数码管的e都是1,位选独立的。

    此处位选寄存器的12是AD芯片的片选chip select,低电平有效,模数转换时才用,这里一直给高电平

    段选和位分别由锁存器控制。第一个控制段选,第二个位选,锁存器的输入都接在了D0~D7,即接在了P0,都有10K上拉电阻,P0位三态状态,无上拉电阻,所以无法给高低电平操作,加上拉电阻后,一上电就是高电平,此为原因,记得以后设计电路时单片机P0要加上拉电阻,大小10K,接法如此。看到这里为什么两个锁存器都接在了P0?原因锁存器可以利用11引脚来控制是否使用,高电平,输入输出直通,低电平,输入输出断开,输出保持原来的值(其实就是高电平变低电平的这个下降沿使其锁存的)。忘接了就回去看。例如,先让第二个锁存器11为高,控制位选选择控制某一个数码管,然后11位低,保持输出不变,然后打开段选的锁存器即可,最后再锁住。

    这就是用一组IO口控制6个数码管,最多可以八个,位选(12、13还没放数码管)那里可以放8个,而之前那种是用了12个IO口控制4个数码管,浪费IO口,占用资源。


    编程开始

    如何让第一个数码管亮1,其它不亮?思考下

    首先其它不数码管不亮,单片机上电后IO口为高电平,那么所有的位选和段选都是高电平,所以所有的LED都是不亮的,不亮的原因当然就是数码管的LED阳极和阴极都是高电平喽。接下来我们要让第一个数码管亮,那么首先要打开位选锁存器来选择某一个数码管,先让位选锁存器11引脚为1(P2^7=1,当然肯定不能这样用,毕竟要先定义),这样就能控制位选锁存器了,然后是让第一个亮,其他的不用管,那么第一个数码管的位选为0(位选是数码管LED的阴极嘛,忘了就会取看看),其它的位选为1,那么就是0xfe,这样数码管就选择完了,那么就要关闭这个锁存器,11阴极为低。接下来是控制段选了,来让数码管亮1,首先要打开段选锁存器,让他的11引脚为1(P2^6=1),这样就打开了,亮1,那么就是bc为1,其它为0,那么就是0x06,控制完段选后就关掉锁存器,11位低,这样就全都操作完了。

    这里我是用我单片机的电路图

     

     1 #include<reg51.h>
     2 
     3 sbit DUAN=P2^6;
     4 sbit WEI=P2^7;
     5 
     6 void main()
     7 {
     8     while(1)
     9     {
    10         //控制位选
    11         WEI=1;
    12         P0=0xfe;
    13         WEI=0;
    14         
    15         //控制段选
    16         DUAN=1;
    17         P0=0x06;
    18         DUAN=0;
    19     }
    20 }
    

     1 #include<reg51.h>
     2 
     3 sbit DUAN=P2^6;
     4 sbit WEI=P2^7;
     5 
     6 void main()
     7 {
     8     while(1)
     9     {
    10         //控制位选
    11         WEI=1;
    12         P0=0xf0;
    13         WEI=0;
    14         
    15         //控制段选
    16         DUAN=1;
    17         P0=0x06;
    18         DUAN=0;
    19         while(1);
    20     }
    21 }
    

    这样呢就显示了4个1,先看下我代码里最后多了一个while(1),如果没有这条语句,在最外面的while(1)循环中,执行到WEI=0后,P0一开始是有值的,那么在DUAN=1时,P0此时还是0xfe,然后才会变成0x06,同样的在DUAN=0结束后P0=0x06,然后再一次循环开始,WEI=1,这时候P0也是有值的,是0x06,也就是出了第二三两个数码管都亮。这样在这种一直闪烁的情况下,由于执行的很快,会有一些错误,如下:

    因此要加上while(1),不知道实体单片机会不会这样。


     接下来让8个数码管从0计数到F

     1 #include<reg51.h>
     2 #define uchar unsigned char
     3 #define uint unsigned int
     4 
     5 sbit WEI=P2^7;
     6 sbit DUAN=P2^6;
     7 
     8 void Delay1ms();
     9 void delay(int n);
    10 
    11 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
    12 //                    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   无显示
    13 //[]括号内可以不写,编译时会自动数元素数然后分配内存
    14 
    15 uchar num;
    16 void main()
    17 {
    18     while(1)
    19     {
    20         WEI=1;
    21         P0=0x00;
    22         WEI=0;
    23         
    24 //        DUAN=1;
    25         for(num=0;num<15;num++)
    26         {
    27             DUAN=1;
    28             P0=Table[num];
    29             delay(1000);
    30             DUAN=0;
    31         }
    32 //        DUAN=0;
    33     }
    34 }
    35 
    36 void delay(int n)
    37 {
    38     while(n--)
    39     {
    40         Delay1ms();
    41     }
    42 }
    43 void Delay1ms()        //@12.000MHz
    44 {
    45     unsigned char i, j;
    46 
    47     i = 2;
    48     j = 239;
    49     do
    50     {
    51         while (--j);
    52     } while (--i);
    53 }
    

    code表示编码表,写它编译完会放在程序存储器中,如果不写就放在了随机存储器,随机存储器是有限的,也就是数据存储器,51单片机是128字节,每定义一个char变量,例如char num;,这将占用一个字节,如果没用code那么这个char数组里面有多少个数就占用多少字节,而若是int数组,那么就占用2*元素数的字节。如果程序大了,变量多了,就不够用了,数据存储器很宝贵,要省着用,所以用多大的数据量就用多大的变量,例如能用char就不用int。


     中断系统

    所有微处理器最有用的就是中断,而且经常用到

    51单片机有5个中断源,可以嵌套,就是A发生中,B事件来了,那么去执行B,结果执行B的时候,C事件发生了,那么就去执行C,当C执行完,接着执行B,执行完B,再去执行A。这里不讲嵌套,之后慢慢就会了,当然51单片机只有两级嵌套,嵌入式系统可以嵌套4、5级。

     

    汇编中RETI是中断的返回条件,c语言没有,c语言执行完中断函数就自己回去了。

     

    计算机的键盘、鼠标等都是有中断的,键盘通过发送一段扫描码,按一下发送一段,扫描码是有两个8位的数据过去,单片机检测到扫描码再分析判断出按得哪个键。单片机可以驱动键盘,也可以驱动显示器,可以用单片机做一个电脑,当然要求单片机性能高点。

    可以看到1(中断号)是键盘,3是红外.....共23个

     

    串行输入和串行输出是一个中断源ES,所以是5个中断源(EX0,ET0,EX1,ET1,ES)。串口暂时不用,这一位先不考虑。

    下面第二个和第三张图片先不用看。

    EA总中断,要想要有中断就要打开EA,EA=0关闭,CPU屏蔽所有中断请求,也称为CPU关中断,所以如果EA=0,那么P3口只能作为普通IO口,EA=1打开总中断,启用了第二功能。

    要想启动外部中断0,那么要开启总中断(EA=1)和外部中断源(EX0=1),并且选择电平触发方式(IT0=0,IT0=1为从高到低负跳变沿触发),当P3^2有低电平输入,就去执行中断程序。

     下面第一张图是串口的,先不用看

    下面这个也看不懂,可以先不看

    嵌套时,高优先级的可以在低优先级中断中继续中断

    下面这个必须记住,记住优先级顺序就好,程序入口是汇编用的。

    例如当这五个中断同时发生,那么先发生外部中断0,然后定时计数器0,外部中断1,以此类推。

    他们的序号分别为0~4,等会写程序会用。

    中断允许控制寄存器,字节地址A8H,所有能被8整除的寄存器都可以进行位寻址,就是可以直接操作某一位,例如在操纵P2时,我们就不能P2^3=0,而这里就可以EA(IE寄存器的最高位)=1。

    打开头文件REG51.H或者52,可以看到定义了IE,然后又定义了IE的各个位

    所有寄存器上电后,默认为0,所有默认为电平触发。(IT0=0)

    下面是当P3^2变为低电平时会触发中断函数的代码。

     1 #include<reg51.h>
     2 #define uchar unsigned char
     3 #define uint unsigned int
     4 
     5 sbit WEI=P2^7;
     6 sbit DUAN=P2^6;
     7 sbit LED0=P1^0;
     8 
     9 void Delay1ms();
    10 void delay(int n);
    11 
    12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
    13 //                    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   无显示
    14 //[]括号内可以不写,编译时会自动数元素数然后分配内存
    15 
    16 uchar num;
    17 void main()
    18 {
    19     EA=1;
    20     EX0=1;
    21     while(1)
    22     {
    23         WEI=1;
    24         P0=0x00;
    25         WEI=0;
    26         
    27 //        DUAN=1;
    28         for(num=0;num<15;num++)
    29         {
    30             DUAN=1;
    31             P0=Table[num];
    32             delay(1000);
    33             DUAN=0;
    34         }
    35 //        DUAN=0;
    36     }
    37 }
    38 
    39 void exter0() interrupt 0
    40 {
    41     LED0=~LED0;
    42 }
    43 
    44 void delay(int n)
    45 {
    46     while(n--)
    47     {
    48         Delay1ms();
    49     }
    50 }
    51 void Delay1ms()        //@12.000MHz
    52 {
    53     unsigned char i, j;
    54 
    55     i = 2;
    56     j = 239;
    57     do
    58     {
    59         while (--j);
    60     } while (--i);
    61 }
    

    可以看到,中断函数不需要声明,中断函数返回值为空(void),中断函数后面有一个interrupt,表示是中断服务程序,还要有一个标号,这里我们用的是外部中断0,所以为interrupt0,上面提到过。上面代码,如果P3^2一直为低电平,将会一直在中断函数中,总程序将不执行了。

    若为电平触发方式(就是上面这种),在中断服务返回之前,外部中断请求输入必须无效,即变为高电平,否则CPU返回主程序后就会再次返回中断,就会发生上面总程序不执行的现象。所以电平触发方式适合于外部中断以低电平输入,而且中断服务程序能清除外部中断请求源,即外部中断请求输入变为高电平。

    所以我们这里我们该用跳边沿触发方式,也就是在代码EX0=1;后面加上一句IT0=1;或者TCON=0x01;这样中断程序只有在我们将电平从1变为0才会触发(负跳变沿)


     接下来讲定时计数器

    两个功能:定时,计数(就是P3^4,P3^5两个IO口,接了东西会自动计数),我们现在只讲定时。

     我们用的delay函数就是软件定时,而定时器是单片机内另一个硬件,和单片机主CPU是隔离开的,设置好自动运行,时间一到只是告诉CPU我触发中断。

     

     TMOD的高四位控制T1定时器的工作方式,第四位控制T2定时器的工作方式。

     作为计数器时,是由T0或T1引脚输入的外部脉冲源,作为定时器,是由时钟周期的输出脉冲经12分频,即12个振荡周期,每12个振荡周期,计数器加1,12个振荡周期就是一个机器周期。

     

    我们一般让GATE=0即可,工作方式我们主要讲解方式1,会了这个其它也就会了。GATE=1一般用于方波检测。

    TCON的低四位是用于控制外部中断的,忘了就回去看看,TF1一般由硬件自动置1清0,所以不需要控制。

    下面两张图是方式0的,方式0是13位计数,所以不看了。

    下面讲方式1

    一共16位,满的话就是全1,也就是2的16次方,初值可由自己设定,比如全0或其它,设为N,每一个机器周期则+1,那么计数个数就如上所示。

    如果我们定时50ms,那么就需要加50000次,那么就不能从0加到65536,初值就需要为15536(65536-50000),但是要把它分给TH0和TL0(高八位和低八位),那么TH0=(65536-50000)/256,TL0=(65536-50000)%256,2的8次方是256,/256,说明有多少个256,那么进位到高位多少,%256就是不能进位的了。

    由此可以看出最多定时65ms,要定时1s怎么办?那么可以进入20次中断,每次中断50ms,就达到了1s。每进一次中断就在中断中对一个变量+1,加到20,主程序中判断什么时候到20,到了20就是1s。

    方式2用于串口通信,现在不用

     

    方式3也不用

    1. TMOD(设置工作方式):现在用T0定时器,所以只对第四位赋值,TMOD是89H内存地址,不能进行位操作(例如GATE=0),所以要整体赋值,方式1则M1M0=01,C/T=0,GATE=0,所以TMOD=0x01,意思为设置定时器0为工作方式1。
    2. 计算初值:一次中断50ms,所以TH0=(65536-50000)/256,TL0=(65536-50000)%256,不用算出来,计算机会算的。
    3. 中断:所以总中断打开,EA=1,然后打开定时器0的中断,ET0=1。
    4. 启动定时器0:TR0=1.

    这样就开始定时了,满后就进入定时中断函数(后面是interrupt 1),这时要重新赋值,不然就从0开始定时了,就是65ms了。

    下面是用定时器完成的数码管计数。

     1 #include<reg51.h>
     2 #define uchar unsigned char
     3 #define uint unsigned int
     4     
     5 void Delay1ms();
     6 void delay(int n);
     7 
     8 sbit WEI=P2^7;
     9 sbit DUAN=P2^6;
    10 sbit LED0=P1^0;
    11 
    12 void Delay1ms();
    13 void delay(int n);
    14 
    15 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
    16 //                    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   无显示
    17 //[]括号内可以不写,编译时会自动数元素数然后分配内存
    18 
    19 uchar num,tt;
    20 void main()
    21 {
    22     tt=0,
    23     num=0;
    24     TMOD=0x01;//设置定时器0为工作方式1
    25     TH0=(65536-50000)/256;
    26     TL0=(65536-50000)%256;
    27     EA=1;//开总中断
    28     ET0=1;//开启定时器中断
    29     TR0=1;//开启定时器
    30     WEI=1;
    31     P0=0x00;
    32     WEI=0;
    33     
    34 //    DUAN=1;
    35 //    P0=Table[num];
    36 //    DUAN=0;
    37     while(1)
    38     {
    39         if(tt==20)
    40         {
    41             tt=0;
    42             num++;
    43             if(num==16)
    44             {
    45                 num=0;
    46             }
    47             DUAN=1;
    48             P0=Table[num];
    49 //            delay(1000);
    50             DUAN=0;
    51         }
    52     }
    53 }
    54 
    55 void exter0() interrupt 1
    56 {
    57     TH0=(65536-50000)/256;
    58     TL0=(65536-50000)%256;
    59     tt++;
    60 }
    61 
    62 void delay(int n)
    63 {
    64     while(n--)
    65     {
    66         Delay1ms();
    67     }
    68 }
    69 void Delay1ms()        //@12.000MHz
    70 {
    71     unsigned char i, j;
    72 
    73     i = 2;
    74     j = 239;
    75     do
    76     {
    77         while (--j);
    78     } while (--i);
    79 }
    

    会看到数码管没有从0开始或者第一秒会不是0是一个乱码,因为一开始段选的P0没给0的值,只有到了1s后才会给段选的P0显示1的值,所以需要把注释的给段选P0赋值的语句加上。还有记住绝对不能再加上那句delay,因为当程序进入if开始执行delay后,delay延时执行时,会被中断去执行定时中断程序,因此若加上delay,那么延时的时间会非常长。


     最后再总结一下中断这里

    从图中可以看到有这几个寄存器,TCON、IE、IP、SCON还有一个图中没有的IPH,这里我在把图放出来,其中SCON是串口的,这里还不学,所以先不放了。

    看出来IP、IPH是管理优先级的,你只需要知道默认的优先级顺序是:外部中断0、定时/计数器0、外部中断1、定时/计数器1、串行口、定时/计数器2   其他的就不用管了。

    接下来就是梳理中断了:

    1. 外部中断0(以0为例,1的话就是把0换成1)
      使用外部中断的步骤,首先你得写了中断函数(后面加上interrupt 0,若为外中断1就改为2,是按照优先级顺序来的),接下来就是打开中断源,所有的中断源都是由IE寄存器控制的(第三个图可以看到),在第一个图,从右往左看,上面IP不需要看了,接下来就是IE,可以看到要想实现外部中断,要开启的有两个中断源,分别是总中断EA,外部中断中断源EX0,然后就是控制它的触发方式,这样就可以使用外部中断了,这里要用到TCON寄存器,外部中断源的触发方式选择在第二张图看到用TCON的IT0控制,这样就结束了。可以看到还一个和外部中断有关的是TCON的IE0,这个是请求标志位,计算机管的,你不需要管(当然另一个控制外部中断的方式可以用到,但你现在不需要学,那个很少用)。
      最后我们再说一遍:中断函数 -> 总中断EA -> 外部中断源EX0 -> 触发方式IT0    (注意,这两个寄存器都是可位寻址的,所以直接EA=1就可以,不需要IE^7这样操作)
    2. 定时器 0 (计数器先不讲,定时器1同0)
      使用定时器的步骤,首先你得写了中断函数(后面加上interrupt1,若为定时器1就改为3),接下来就是打开中断源,总中断源EA,定时器中断源ET0,控制定时器的工作模式和工作方式,它和外部中断不同,外部中断用TCON,这个用的是TMOD,GATE是怎么开启定时器,C/T是工作模式选择,M1M0是工作方式选择,TMOD的高四位是定时器1的,第四位是定时器0的,我们一般是GATE=0,定时器模式C/T=0,工作方式1  M1M0=01,所以TMOD=0x01(注意TMOD是不可位寻址,所以不能在代码里写M1=0这样,必须是TMOD=什么。),设置定时初值,TH0=,TL0=,全部开启后接下来就是让定时器开始定时了,所以用到了TCON的TR0=1。
      最后我们再说一遍:中断函数 -> 总中断源EA -> 定时器中断源ET0 ->工作模式TMOD(常为TMOD=1) -> 定时初值TH0=,TL0=  -> 开启定时器TR0

     下一课开始是这节课的作业!!!

    动态扫描这里说一下,下节课讲

    让分别显示1234(动态扫描)

    就要用人眼的视觉暂留效应和数码管的余辉,先让第一个数码管亮,显示1,其它不亮,然后快速的让第二个显示2,其他的不亮,以此类推,这就是动态扫描。(人眼只能分别20ms以内的变化,那么让他20ms以内变化就可以了,这样人就看不出来了,就相当于四个数码管一直亮着1234)

    展开全文
  • 郭天祥10天学会51单片机全教程,按课程目录排放ppt课件、示例程序、原理图、ad封装等
  • 51单片机原理图

    2012-07-03 15:59:43
    51的最小系统,数码管,流水灯,矩阵键盘灯原理图的开发。
  • 开发板电源按钮上面的滑动变阻器(1602标号的是控制1602液晶的,12864标号的是控制12864液晶的)是控制液晶的颜色,可以把矩阵检测的程序写入单片机,然后然液晶显示,同时顺时针调节滑动变阻器,让液晶颜色变亮 ...

    开发板电源按钮上面的滑动变阻器(1602标号的是控制1602液晶的,12864标号的是控制12864液晶的)是控制液晶的颜色,可以把矩阵检测的程序写入单片机,然后然液晶显示,同时顺时针调节滑动变阻器,让液晶颜色变亮

    这里用的1602(16对应一行显示十六个字符,02对应一共两行)液晶阵脚是十六针的,一行显示十六个字符,一共两行;12864(横的128个点,竖的 64点)图像液晶,

    1602液晶说明的P1RS是数据命令选择端,高电平表示数据选择端,低电平表示命令选择端,程序中写命令,RS状态是H,程序中写数据,4号口接到单片机的P3.5

    RL高电平是读选择端状态,低电平是写选择端

    在使用一个芯片的之前要将这个芯片的资料搞明白,搞明白之后再操作该芯片

    1602液晶说明的P2的基本操作时序,高脉冲指的是一个凸型脉冲,低脉冲指的是一个凹型脉冲,这里只看写指令和写数据;见P5写操作时序中,RS先给低电平写指令再给高电平写数据,RW给低电平开始写指令或数据,tsp2为有效数据准备时间,当E高电平时,开始将有效数据送出,在tpw时间内DB0DB7的数据必须有效才能写进去,这里我们给RW始终低电平让液晶始终在写;见P2的显示模式设置,5*7点阵就是横行5个点、竖行7个点显示一个字符,指令码对应0x38;见P3的设置指针设置,80H+0对应RAM地址(见P2)上面的0080H+1对应RAM(数据存储区)地址的01,从0027,然后断开,再从4067P2RAM地址映射图是液晶数据存储区的地址映射

    开发板上液晶在蜂鸣器的下面,HEADER161管脚是地,2管脚是VCC1516管脚是背光的作用,15管脚接电阻用来限流并且不让光太亮,D0D7是数据口接单片机的P0口,6管脚是使能,对应TX-1C型单片机实验板原理图上的LCDEN接单片机的P3.4口,管脚5是读写选择端R/W,这里只写不读,给5管脚低电平,数据命令选择端RS接单片机的P3.5口,3管脚是偏压信号,液晶显示需要一个负电压,上面有个滑动变阻器,调节滑动变阻器内部显示的对比度就发生变化;程序中控制LCDEN接单片机的P3.4口和数据命令选择端RS接单片机的P3.5口即可

    液晶使用时先把光标弄出来,可以写两个函数,一个用来写指令一个用来写程序

    买完液晶就看资料,看完资料就按资料连接控制就行了

    寄存器等一些知识不用记的,我们是应用,应用时可以查书

    使用时要关掉数码管,防止和液晶一起使用时功率过大,所以用锁存器关掉数码管

    液晶显示不用大循环,显示后不给命令改变就不会变

    先让液晶有显示:

    #include<reg52.h>

    #define uchar unsigned char

    #define uint unsigned int

    sbit lcden=P3^4;

    sbit lcdrs=P3^5;

    sbit dula=P2^6;//使用时要关掉数码管,防止和液晶一起使用时功率过大,所以用锁存器关掉//数码管

    sbit wela=P2^7;

    uchar num;

    void delay(uint z)

    {

           uint x,y;

           for(x=z;x>0;x--)

                  for(y=110;y>0;y--);

    }

    void write_com(uchar com)

    {

           lcdrs=0;

           P0=com;//数据口送上数据,有效数据准备好后让使能端lcden置高

           delay(5);//1602液晶说明P2的写程序时序图

           lcden=1;

           delay(5);

           lcden=0;

    }

    void write_data(uchar date)//液晶写指数据

    {

           lcdrs=1;

           P0=date;

           delay(5);

           lcden=1;

           delay(5);

           lcden=0;

    }

    void init()

    {

           dula=0;

           wela=0;

           lcden=0;

           write_com(0x38);//1602液晶说明P2,初始化设置中第一步显示模式设置

           write_com(0x0e);//显示开关及光标设置

           write_com(0x06);//地址指针加1 ,整屏不移动

    }

    void main()

    {

           init();

           while(1);

    }

    写数字1见字符手册的PDFP16的表,当送去‘1’(‘1’实际上是ASCII码,对应一个十六进制数)时,实际上送去的是313为横坐标,1为纵坐标),程序中可以送0x31

    #include<reg52.h>

    #define uchar unsigned char

    #define uint unsigned int

    //uchar code table[]="I LIKE MCU!";//写单字符用单引号引,多字符用双引号引

    //uchar code table1[]="WWW.TXMCU.COM";

    sbit lcden=P3^4;

    sbit lcdrs=P3^5;

    sbit dula=P2^6;//使用时要关掉数码管,防止和液晶一起使用时功率过大,所以用锁存器关掉//数码管

    sbit wela=P2^7;

    uchar num;

    void delay(uint z)

    {

           uint x,y;

           for(x=z;x>0;x--)

                  for(y=110;y>0;y--);

    }

    void write_com(uchar com)

    {

           lcdrs=0;

           P0=com;//数据口送上数据

           delay(5);//见见1602液晶说明P2的写程序时序图

           lcden=1;

           delay(5);

           lcden=0;

    }

    void write_data(uchar date)//液晶写指数据

    {

           lcdrs=1;

           P0=date;

           delay(5);

           lcden=1;

           delay(5);

           lcden=0;

    }

    void init()

    {

           dula=0;

           wela=0;

           lcden=0;

           write_com(0x38);//1602液晶说明P2,初始化设置中第一步显示模式设置

           write_com(0x0e);//显示开关及光标设置

           write_com(0x06);//地址指针加1 ,整屏不移动,当write_com(0x07)时,在初始化//write_com(0x80)地址没有变化时,所有字符移动到液晶左侧的外面,

           write_com(0x01);//01为清屏指令

           write_com(0x80);//数据指针初始化,设置数据的初始位置

    }

    void main()

    {

           init();

           write_data('1');//注意要有单引号,如果没有单引号write_data(1),就会显示乱码

           while(1);//保持住

    }

    主程序中写入AB

    void main()

    {

           init();

           write_data(0x41);

           delay(10);

           write_data('B');

           while(1);

    }

    #include<reg52.h>

    #define uchar unsigned char

    #define uint unsigned int

    uchar code table[]="I LIKE MCU!";//写单字符用单引号引,多字符用双引号引

    uchar code table1[]="WWW.TXMCU.COM";//注意数组是从序号0开始的

    sbit lcden=P3^4;

    sbit lcdrs=P3^5;

    sbit dula=P2^6;//使用时要关掉数码管,防止和液晶一起使用时功率过大,所以用锁存器关掉//数码管

    sbit wela=P2^7;

    uchar num;

    void delay(uint z)

    {

           uint x,y;

           for(x=z;x>0;x--)

                  for(y=110;y>0;y--);

    }

    void write_com(uchar com)//液晶写指令,见1602液晶说明P2的写指令

    {

           lcdrs=0;//RS给低电平写指令,这里就不用把RS置为高电平

           P0=com;//数据口送上数据

           delay(5);//见见1602液晶说明P2的写程序时序图

           lcden=1;

           delay(5);

           lcden=0;

    }

    void write_data(uchar date)//液晶写指数据

    {

           lcdrs=1; //RS给高电平读指令,这里就不用把RS置为低电平

           P0=date;

           delay(5);

           lcden=1;

           delay(5);

           lcden=0;

    }

    void init()

    {

           dula=0;//关掉数码管

           wela=0;

           lcden=0;

           write_com(0x38);//1602液晶说明P2,初始化设置中第一步显示模式设置

           write_com(0x0e);//显示开关及光标设置

           write_com(0x06);//地址指针加1 ,整屏不移动

           write_com(0x01);//01为清屏指令

           write_com(0x80+0x10);//数据指针初始化

    }

    void main()

    {

           init();

           for(num=0;num<11;num++)

           {

                  write_data(table[num]);

                  delay(20);//延长的时间长可以看出动态效果,如delay(300)

           }//在该句下面添加清屏write_com(0x01)table[]的字符显示完就清屏,继续显示下面的

           write_com(0x80+0x40);//放到第二行可以write_com(0x80+0x40),见1602液晶说明

    //想空几位,可以write_com(0x80+0x40+0x03),右移三位,也可以write_com(0x80+0x40+3)//这里十进制和十六进制可以通用

           for(num=0;num<13;num++)

           {

                  write_data(table1[num]);

                  delay(20);

           }

           while(1);

    }

    字符串先显示出来,再全部左移:

    编译后错误提示:UNCALLED SEGMENT表示一个函数没有调用

    显示从右到左滚动:将数据指针指到10那,写完再用整屏移动,见EN_TC1602PDFP12Cursor or Display Shift命令,S/CR/L10时表示显示左移,光标跟随显示移动,code0x18左移一下:

    void main()

    {

           init();

           for(num=0;num<11;num++)// 这里写的数据是在液晶外面写的,初始化程序的0x10是液晶外面

           {

                  write_data(table[num]);

                  delay(200);//延长的时间长可以看出动态效果,如delay(300)

           }

           write_com(0x80+0x53);

           for(num=0;num<13;num++)// 这里写的数据是在液晶外面写的,0x53是液晶外面

           {

                  write_data(table1[num]);

                  delay(20);

           }

           for(num=0;num<16;num++)

           {

                  write_com(0x18);//写完数据就移动,整屏左移

                  delay(200);

           }

           while(1);

    }

    展开全文
  • 单片机管脚,P3口有两个功能,上电默认情况下就使用P3口的普通IO口,当对单片机内部的某些寄存器设置时...TX-1C型单片机实验板原理图中复位电路在右边晶振电路的下面,电容是通交隔直的,当S22按下,上边电路接通,10k
  • 本书从实际应用入手,以实验过程和实验现象为主导,循序渐进地讲述51单片机C语言编程方法以及51单片机的硬件结构和功能应用。 全书共分5篇,分别为入门篇、内外部资源操作篇、提高篇、实战篇和拓展篇。 本书配套光盘...
  • 参考第十节的课件DS12887 RTC就是Real Time Clock实时时钟 DS12887芯片是保持时间的,即当前设定一个时间,然后断电,而该芯片的时间还在走 DS12887-5指的是5伏,DS12887-33指的是...AD0到AD7接单片机的P0口 TX-1C
  •  } 蜂鸣器在TX-1C型单片机实验板原理图单片机右边锁存器下面,FM旁边电阻上面的18表示18欧姆,FM连接单片机的P2^3口;三极管有电流放大功能,三极管是压控流型的,电压控制电流的放大倍数,这里用的是三极管的...
  • 2.是否已连接DS1302(我的单片机板子利用的是郭天祥51单片机,因此没有DS1302,这时就可以自行淘宝购买,2块钱一个) 如果上述两个事项都没有问题,则需要检查引脚配置: 1.打开LCD1602.c,参考单片机原理图修改...
  • 郭天祥老师的51单片机开发板原理图是经典中的经典
  • //改变P1的值 8 9 } 10 } main可以直接改成这样 课后作业 补充一下蜂鸣器 蜂鸣器原理图 (我的板子是第二种)(继电器也挺重要,但暂时不说了) FM就是P2^3口,然后接一个电阻,这里用了一个三极管,用了它的开关作用(它...
  • 计算机与单片机之间通讯时需要加电平转换芯片。 C-51的基本数据类型: C-51的数据类型扩充定义: <1>str:特殊功能寄存器声明; <2>str16:str的十六位数据声明; <3>sbit:特殊功能位声明; <4&...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 334
精华内容 133
关键字:

郭天祥51单片机原理图