单片机控制led灯亮灭8个led灯,实现亮灭亮灭,这个C语言程序行吗

   电路的核心部分是AT89C2051单片机,前面提到它有Pl和P3两组I/O口,我们这里只用到Pl口,共8个引脚。图中Cl、R9组成典型的上电复位(即在加电时单片机复位)电路,XTAL、C2、C3与AT89C2051片内振荡电路组成时钟。值得注意的是,C2、C3的容量不能与图中数值偏差太大,否则可能引起不起振或振荡不稳定。XTAL的可以在4-20M之间,不过,频率的变化会导致程序运行速度的变化,这样就需要调整延时子函数的参数。事实上,不调整参数亦可,只是此时延迟时间不再是1秒,其延迟时间会随着XTAL频率的降低而增加。    二、软件部分    本程序包含两个函数,一个是主函数,另一个是延时子函数。源程序如下(为了便于讲解,我们为每行程序加上了编号):
  程序各行作用如下:    00行:把AT89C2051的头文件&AT89x051.H&包含进来。    01行:声明Delay()延时子函数,该函数有一个无符号整型参数k,同时函数前面的void表明函数不返回函数值。    02行:延时子函数的开始,同时声明两个无符号整型变量i和j。    不过请注意,这里没有象上期的程序一样,把表示函数开始的&{&单独成行,而是把下一行写在一起了。事实上,写C程序的时候,可以把多行写作一行,C编译器只要遇到分号就认为是一行语句的结束。    当然,我们不能因为C程序有这个特点,就随意把多行合作一行书写,实际书写C程序的时候,还是要养成良好的程序书写习惯,按照约定俗成的原则来书写。    03行:声明for()循环。这个循环的初始条件是i=0,终止条件是i<k,循环计数是每循环一次,用手计数的变量i加1。因此,这个循环的循环次数就是k次。这样,只要改变k的值(即改变Delay()延时子函数的参数k的值),就可以很容易地控制循环次数,从而获得不同的延时时间。    04行:声明嵌套在03循环中的一个新的for()循环,这个循环与上一个循环相似,其循环次数是120次。本循环与上一个循环嵌套后,使得总的循环次数达120&k次。    05行:第一个分号,表示L条空语句,占用一个机器时间,以实现延时的目的。后面的两个&}&中,第一个&}&是04行for()循环的结束标志,程序遇到它时,将自动返回04行,使用于循环计数的变量j加1,同时判断j是否小于120,如果否,则转入05行;第二个是03行for()循环的结束标志,程序遇到它则会返回03行。    06行:Delay()延时子函数的结束标志。    07行:声明主函数main()。这里的主函数不需要参数,也不返回函数值。    08行:主函数的开始标志&{&。    与01行的Delay()延时子函数一样,习惯上也会把下一行的语句与本行的花括号写在一起。    09行:声明一个无条件for()循环,&;;&以使单片机重复执行任务,使流水灯能不停地流动。    10行:大括号表示09行for()循环的开始,语句&Pl_0=0&是让单片机Pl口的O号引脚(即Pl.0)输出低,根据电路可知,此时LED1会被点亮。    11行:以参数值1000调用01行声明的Delay()延时子函数,使程序运行到此处时,延时1000毫秒(即1秒)。    12-41行:与10、11行的作用相同。    简而言之,10-41行的作用就是依次点亮LEDl-LED8这八个。    42行:09行结束标志,程序运行到此处时,自动返回09行,因为09行的for()循环是无条件循环,所以程序马上会转到10行继续运行。    三、软件仿    真首先按照前面的方法建立一个新的工程,并把上面的程序按照前面的方法输入并存盘。然后按照下面的方法进行仿真调试。    1.把建立好的C程序加入工程    双击左边工程窗口中的&Target1&,展开&Target1&夹,然后右击&SourceGroupl&,选择&增加文件到组&SourceGroup1&(AddFilestoSourceGroup1)&,并把刚才输入的C程序加入到工程中。    2.连编目标程序    连编之前要设置目标的输出属性,否则连编出来的目标程序中不含有用于固化到单片机中的十六进制文件。    设置目标输出属性的方法是:    先单击工程窗口中的&Target1&以选中它,然后选择&工程&菜单中的&目标&Targetl&属性(OptionsfortargetTargetl)&,系统弹出对话框,在对话框中选择&输出(Output)&选项卡,并选中&生成HEX文件(CreateHEXFile)&选项(生成十六进制文件),当然,如果你的单片机编程器不支持十六进制文件的话,就要用转换软件把生成的十六进制文件转换成了。    设置好目标属性后,按&F7&开始连编目标程序。连编的结果信息会在输出窗口中显示出来,若显示&0错误(s),0警告(s)(0Error(s),0Warning(s))&表示连编成功,否则说明连编不成功。若连编不成功,在输出窗口中会显示错误所在行及错误原因,然后根据具体的错误进行修改,修改完成后,再次连编,直到连编成功。    3.仿真调试    连编好目标程序后就可以开始仿真调试了,其步骤是:      1)选择&调试(Debug)&菜单中的&开始/停止调试(Start/StopDebugSession)&,进入仿真调试状态。    2)选择&外围设备(Peripherals)&菜单中的&I/OPorts&选项中的&Port1&,打开I/O口状态模拟器。状态模拟器中的&&&表示相应的I/O口引脚状态为&1&电平状态。    如:图中表示Pl口(Portl)的8个引脚全为&1&电平状态。    3)按&Fll&进行单步跟踪调试。每按一次&Fll&,程序会执行一步(即一条语句),若程序的执行影响了I/O口的状态,在I/O口状态模拟器上会有相应的显示。因为每按Fll一次,程序只执行一步,所以在调试循环程序时,可能会有很多的步数,如本例中每调试一次Delay()子函数中的两个循环,其步数高达六万步,因此要设法减少步数,本例中可先将Delay()子函数的参数值由1000改为1,等调试成功后再改回1000,这样就可以大大减少循环步数。    4)再次选择&调试(Debug)&菜单中的&开始/停止调试(Start/StopDebugSession)&,退出仿真调试状态。    四、程序固化    当程序通过了仿真调试,就可以利用编程器把它固化到单片机,并插入做好的线路板上,欣赏你的劳动成果了。
往下看有更多相关资料
本网站试开通微、小企业商家广告业务;维修点推荐项目。收费实惠有效果!欢迎在QQ或邮箱联系!
试试再找找您想看的资料
资料搜索:
查看相关资料 & & &
copyright & &广电电器(中国梧州) -all right reserved& 若您有什么意见或建议请mail: & &
地址: 电话:(86)774-2826670& & &&)51单片机按键控制LED灯亮灭【程序+图文】-51单片机-单片机入门教程日记
51单片机按键控制LED灯亮灭【程序+图文】
51单片机按键控制LED灯亮灭【程序+图文】
阅读:(28298)
& & & &还是先看下面的一个电路图,还是仔细看P2接口,这里我们接了一个发光二极管D1,又接了一个按键S2,我们想实现的功能是:按下按键S2,发光二极管D1改变发光状态。实际上就是模拟家庭的电灯开关。& & & &当然了,要实现这样一个功能大可不必如此兴师动众,又是单片机又是最小系统的,实际用一个简单的闭合开关、一个限流电阻、一节电池、一个灯泡就足矣啦。但是在这可不单单是为了点亮一个灯而已,通过这个小案例,我们会引出单片机开发板系统里面两个非常重要的概念,“按键去抖”和“中断”!下面的内容涉及到好多编程理念,请认真阅读。& & & &说到按键作者不禁要吐一下槽。作者曾经问(其实也被问过)这样一个问题:假设说单片机的P2.0管脚接按键,P2.4接发光二极管,怎样用按键控制灯的亮灭?& & & &有人脱口而出:按键中断!(这是后文书,现在说出来太早了,掌嘴!)& & & &还有人说:在单片机内部从P2.0直接接一条电线到P2.4……& & & &我说:……& & & &好吧,作者承认第一天学单片机的时候我也是这么认为的!& & & &为什么要说这个呢,因为正如第一节我说的,很多人初学单片机的时候会错误地认为单片机是靠纯电路实现的控制,但是事实上它是依靠单片机识别和控制管脚电平来实现各种功能的。单片机就是一个非常听你话的大脑,你让它做啥,它就做啥了。比如想要实现如图按键控制二极管的功能,就让单片机一直监测P2.0的电平状态,S2在没有按下的时候,P2.0通过R4直接连接到VCC,电平状态肯定是高电平,若S2按下,P2.0此时会接地,电平变成低电平,所以当单片机发现P2.0管脚的电平状态变成低电平的时候就知道此时有按键按下了,然后单片机再通知P2.4管脚,让D1转变发光状态,整个过程就是这样的,然后我们将它转换成一个比较专业的程序流程图,就如下图所示。然后再根据上面的流程图编写程序,代码如下所示:#include&reg52.h& &sbit S2=P2^0; &sbit D1=P2^4; &/********************************************************&**函数名:main(void)&**返回:无&**函数功能描述:按键控制灯的亮灭&**********************************************************/ &voidmain(void) & & //程序开始运行 &{ && & D1=1; & & & & &//程序初始化,令二极管不发光 && & while(1) & & & &//循环检测 && & { && & & & if(S2==0) & //如果检测到P2.0管脚为低电平,即按键按下 && & & & { && & & & & & D1=~D1; //二极管转换发光状态,返回继续循环检测 && & & & } & && & } &} && & 应该可以看出,根据流程图来编程会让思路更加清晰,以后等大家编程编的多了的时候就更能体会程序流程图的重要性。& & 好了,一个按键控制电灯的程序就编好了。& & 那么,真的编好了吗?& & 试着把程序下载到单片机里,运行一下,看看是不是您想要的效果呢?& & 好吧,告诉你,这样还不行。你可以试着按下按键,会发现电灯并不是像您想的那样那么听话,有时候确实改变了发光状态,有时候就不变,有时候还会变好几次,这是要闹哪样?& & 我们来看一下按键按下去后P2.0管脚电平的变化情况,下图是一个理想情况的示意图。& & T0时刻:按下按键,P2.0电平由高电平转换为低电平。& & T1时刻:抬起按键,P2.0电平由低电平转换为高电平。& & 当单片机P2.0管脚检测到低电平的时候,D1发生转变。你要知道,这个过程在单片机里发生的极快,大概是微秒级的数量级,而按键按下去再抬起来,这个时间段对应的是毫秒级的数量级,所以在T0到T1这个时间段里,其实D1已经发生了若干次的转换,这个不是我们想要的效果,我们想着按键按一次,D1就转换一次,那这该如何实现呢!& & 思路是这样的,当按键按下去的时候,单片机开始等待,一直等到按键抬起来的时候让D1再转变状态。代码改成下面的样子。#include&reg52.h& &sbit S2=P2^0; &sbit D1=P2^4; &/********************************************************&**函数名:main(void)&**返回:无&**函数功能描述:按键控制灯的亮灭&**********************************************************/ &voidmain(void) & & //程序开始运行 &{ && & D1=1; & & & & &//程序初始化,令二极管不发光 && & while(1) & & & &//循环检测 && & { && & & & if(S2==0) & //如果检测到P2.0管脚为低电平,即按键按下 && & & & { & && & & & & & while(S2==0); //当P2.0为低电平的时候,单片机在此等待 && & & & & & D1=~D1; //二极管转换发光状态,返回继续循环检测 && & & & } & && & } &} && & 上面加了一句“while(S2==0);”这句代码等效于“while(!S2);”,意思是当括号内的语句为真时(P2.0为低电平),单片机程序在此等待,直到括号内语句为假时(P2.0变回高电平),程序往下继续运行。好了,这下运行一下程序,看看是不是能达到您想要的效果来了。& & 。。。& & 那么,效果真的好了吗?& & 。。。& & 好吧,好像还是不行,上面的程序如果加载到类似于Proteus的仿真软件里(请参阅第五章Proteus仿真软件教程),程序运行起来一点问题也没有。但是下载到真正的单片机里运行起来虽然比不加“while(S2==0);”这句代码的时候要强一些,但时不时的还是不太听话。原因何在?& & 原因就在于一句非常有名的名言啊“现实往往比理想差好远!”,按键按下的电平变化会由于电路的稳定性和手的抖动产生一个非常不规则的波形,如下图所示,在按下和抬起的一刹那都会产生一个抖动区,不要小看这个抖动区,它足以让单片机产生误会,导致D1发生偏转。& & 所以在编写按键程序的时候往往都要加一个“去抖”过程,也就是当单片机P2.0口检测到低电平时,单片机不做任何处理,空等一段时间(10ms左右),再次检测P2.0端口,如果此时P2.0端口仍然是低电平,那就认为此次果然按下了按键,D1开始转换状态。重新编写程序,如下所示:#include&reg52.h& &#define uintunsigned int &sbit S2=P2^0; &sbit D1=P2^4; &/********************************************************&**函数名: delay(uint x)&**返回:无&**函数功能描述:延时函数,延时大概x毫秒&**********************************************************/ &voiddelay(uint x) & & & & & &//延时函数,让单片机空跑一段时间。 &{ & && & uint i,j; && & for(i=0;i&=x;i++) && & & for(j=0;j&=100;j++); &} &/********************************************************&**函数名:main(void)&**返回:无&**函数功能描述:按键控制灯的亮灭&**********************************************************/ &voidmain(void) & & //程序开始运行 &{ && & D1=1; & & & & &//程序初始化,令二极管不发光 && & while(1) & & & &//循环检测 && & { && & & & if(S2==0) & //如果检测到P2.0管脚为低电平,即按键按下 && & & & { & && & & & & &delay(10); & //延时一下 && & & & & & & & if(S2==0) && & & & & & & & { && & & & & & & & &while(S2==0); && & & & & & & & &D1=~D1; //二极管转换发光状态,返回继续循环检测 & & & & & & & &&& & & & & & & & } && & & & & & & & & & && & & & } & && & } &} && & 这下再试试,看看效果如何?& & 。。。& & 好吧& & 。。。& & 效果应该是不错了,假如还有问题的话就改改delay函数里面的参数值,多试几次肯定能调整出最好的效果。(这里如果告诉你,其实程序还是有问题的话,你会不会疯掉呢?-_-||)& & 再补充一句,有些时候我们闲编写去抖程序比较麻烦,可以在按键那里加一个滤波电容,如下图所示。按键按下后,若有抖动,电容C会起到一定的滤波作用,效果就会强很多,大家可以做实验试试看。& & 还有一个思路呢!上文咱们用到的按键都是自动弹起的,还有一种按下去就不弹起的开关呢,那种开关就简单多了,按下去就一直导通,再按一下才抬起,我用这么文艺的方式给您解释相信您一定能想的出那种开关长得什么样子吧。
还没有留言,还不快点抢沙发?

我要回帖

更多关于 单片机控制led灯亮灭 的文章

 

随机推荐