单片机 跑马灯实验
单片机跑马灯(流水灯)控制实验报告

单片机跑马灯(流水灯)控制实验报告实验目的:本实验旨在通过使用单片机对LED灯进行控制,实现跑马灯(流水灯)的效果,同时熟悉单片机编程和IO口的使用。
实验器材:1)STC89C52单片机2)最基本的LED灯3)面包板4)若干跳线实验过程:1.硬件连接:将单片机的P2口与面包板上的相应位置连接,再将LED灯接入面包板中。
2.编写程序:按照题目要求编写所需程序。
3.单片机烧录:将程序烧录进单片机中,即可实现跑马灯效果。
程序详解:1. 由于LED灯是呈现亮灭效果,我们要编写程序来控制LED的亮灭状态。
2. 在程序中,我们通过P2口控制LED灯的亮灭状态。
例如,若要让LED1亮,我们就将P2口的第一个引脚设置为低电平(0),此时LED1就会发光。
同样地,若要LED2,LED3等依次点亮,则需要将P2口的第二个、第三个引脚设置为低电平,依此类推即可。
3. 接下来,我们要实现每个LED灯的亮灭时间间隔,并实现跑马灯的效果。
4. 在本实验中,我们采用了计时器中断的方式来实现灯光的控制,即在定时器中断函数中对P2口进行控制,这样可以方便地控制灯亮灭时间和亮度。
通过改变定时器中断的时间,可以改变LED灯的亮灭时间;通过改变P2口的控制顺序,可以实现跑马灯效果。
5. 整个程序比较简单,具体的代码实现可以参考以下程序:#include <REG52.H>#include <intrins.h>#define uint unsigned int #define uchar unsigned char void Delay1ms(uchar _ms); void InitTimer0();sbit led1=P2^0;sbit led2=P2^1;sbit led3=P2^3;sbit led4=P2^4;sbit led5=P2^5;sbit led6=P2^6;sbit led7=P2^7;void InitTimer0(){TMOD=0x01;TH0=(65536-50000)/256; TL0=(65536-50000)%256; EA=1;ET0=1;TR0=1;}void Timer0() interrupt 1 {static uint i;TH0=(65536-50000)/256; TL0=(65536-50000)%256;i++;if(i%2==0){led1=~led1;}if(i%4==0){led2=~led2;}if(i%6==0){led3=~led3;}if(i%8==0){led4=~led4;}if(i%10==0){led5=~led5;}if(i%12==0){led6=~led6;}if(i%14==0){led7=~led7;}}void Delay1ms(uchar _ms){uchar i;while(_ms--){i=130;while(i--);}}实验总结:通过本次实验,我们掌握了单片机控制跑马灯(流水灯)的方法,对单片机编程和IO 口的使用有了更深入的了解。
单片机跑马灯(流水灯)控制实验报告

单片机实验报告姓名: 学号:一、 实验实现功能:1:计数器功能2:流水灯二、 具体操作:1、计数器功能数码管的动态显示。
每按一次K2键计数器加1通过数码管显示出来,计数器可以实现从0计数到9999。
2、流水灯当在计数器模式下的时候按下K3键时程序进入跑马灯模式,8个小灯轮流点亮每次只点亮一个,间隔时间为50ms 。
三、 程序流程图开始 定时器T0 设置初值,启动定时器,打开中断复位 Key2按下 中断关闭 计数器模式 计数器加1 Key3按下 流水灯模式 数码管显示数字加1 跑马灯点亮间隔50ms Key1按下中断打开四、程序#include <reg51.h>typedef unsigned char uint8;typedef unsigned int uint16; //类型定义sbit P2_1 = P2^1;sbit P2_2 = P2^2;sbit P2_3 = P2^3;sbit P2_4 = P2^4; //位声明四个数码管开关sbit Key2 = P3^2;sbit Key3 = P3^3; //位声明2个按键K2和K3sbit Ledk = P2^0 ; //LED 开关void delay(uint16 i); //延时函数声明void refresh (); // 数码管刷新函数声明void liushuideng(); //流水灯函数声明uint8 number[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//数码管的真值表uint8 out[4] = {0}; // 数组变量uint16 counter=0; //用作计数器的变量uint16 Time_counter=0; //用作定时器的变量void main() //主函数{TMOD = 0x01; //定时器0,工作方式一TH0 = 0xFC;TL0 = 0x18; //定时器初值使每次循环为1msTR0 = 0; //定时器0开始作ET0 = 0; // 定时器中断关EA = 0; // 关中断while(1) //计数器模式{Ledk =1 ; //led开关关out[0]=number[counter%10]; //取个位out[1]=number[counter%100/10]; //十位out[2]=number[counter%1000/100]; //百位out[3]=number[counter/1000]; //千位if (!Key2) //计数器加1{++counter; //自加out[0]=number[counter%10]; //取个位out[1]=number[counter%100/10]; //十位out[2]=number[counter%1000/100]; //百位out[3]=number[counter/1000]; //千位while(!Key2) //等待键盘抬起refresh(); //刷新数码管}refresh(); //刷新数码管if (!Key3) // 进入跑马灯模式liushuideng();}} //主函数结束/*******************延时*************/void delay(uint16 i){uint8 j; // 定义局部变量for(i;i>0;i--) //循环i*240 次for(j=240;j>0;j--);}/************数码管刷新******************/void refresh (){uint8 j;for (j=0;j<4;j++) //四次循环刷新数码管{switch(j){case 0: P2_1=1;P2_2=1;P2_3=1;P2_4=0;break;case 1: P2_1=1;P2_2=1;P2_3=0;P2_4=1;break;case 2: P2_1=1;P2_2=0;P2_3=1;P2_4=1;break;case 3: P2_1=0;P2_2=1;P2_3=1;P2_4=1;break;//每次循环只选中一个数码管default:break;}P0 = out[j]; // 位选,给数码管送值delay (20); //延时消抖}}/*************定时器的中断服务函数**************/void Timer0_Overflow() interrupt 1 //定时器0溢出中断,这个语句1ms执行一次{TH0 = 0xFC;TL0 = 0x18; //每1ms重新赋定时器初值Time_counter++; //计数,看经过了几个1ms}/***********************流水灯子函数****************************/ void liushuideng(){uint8 j = 0 ; //定义局部变量P0 = 0xff; // 小灯全关TR0 = 1; //定时器1开始计时EA = 1; //中断开放ET0 = 1; //定时器0中断开while(1){Ledk = 0 ; //打开LED开关P2 = P2|0x1E; //关掉数码管if(50 == Time_counter) //50个毫秒{P0=~(1<<j++); //控制小灯Time_counter = 0; //清零开始下一次循环定时}if (8==j) //移完8次再重新移{j=0;}}}。
实验三、跑马灯的程序设计

实验三、跑马灯程序设计实验(2学时)一、实验目的1、熟悉89C51单片机系列指令系统;2、掌握软件定时程序的编写方法和子程序的调用方法;3、掌握使用汇编语言来实现跑马灯设计。
二、实验内容参照如下原理图设计一个跑马灯控制程序,让8个led按照自己的设想发光,显示的样式尽可能的丰富,灯的变化延时通过调用软件延时子程序来实现,要求延时时间为0.5S。
LED灯样式参考:1、让8个灯闪烁完后,1个灯向左(RL)或向右(RR)移动(流水灯)。
2、8个灯通过取表格“T AB:DB 81H,0C3H,0E7H,0FFH,18H,3CH,7EH,0FFH”值进行变化。
三、实验设备微机1台,单片机实验板1块四、实验报告要求1、写出实验目的、实验内容、实验设备、程序流程图和源程序清单(加注释);2、写出运行结果,并分析其是否正确;3、说明实验中遇到的问题及解决的方法;4、用实验报告纸手写实验报告。
ORG 0000HSJMP MAINORG 0030H;LCALL MAINMAIN:MOV P1,#00HMOV DPTR,#LIGHTCHU:MOV R3,#06HMOV A,#00HTURN:MOV 20H,AMOVC A,@A+DPTRMOV P1,AMOV A,20HINC ALCALL DELAYDJNZ R3,TURNSJMP CHUDELAY:MOV R0,#05HD1:MOV R1,#250D2:MOV R2,#200D3:DJNZ R2,D3D4:DJNZ R1,D2DJNZ R0,D1RETLIGHT:DB 81H,42H,24H,18H,24H,42H SJMP $END本实验,使我受益良多。
在实验未开始之前,老师给了我们讲解了什么是跑马灯,让我们知道这跑马灯是怎么一回事;后来老师还讲了一两个例子,这让我们在设计程序的时候,有了头绪。
本实验,我的程序是P1两边同时来灯,当两灯相碰撞时,就反弹;反弹到顶/底时,再向内聚;然后再反弹……这是实验最终的程序,但在程序未出炉之前,遇到了一些问题。
单片机跑马灯实验报告-叶坤

单片机实验报告—Delay函数和中断系统实现跑马灯14级通信2班叶坤学号:201400800679一、硬件组成介绍1、最小系统STC12C5A16S2单片机、开发板、12兆的晶振、电源。
2、其他共有40个引脚,两个外部中断,两个定时器,一个串行口中断。
四个独立按键,四个数码管,一个蜂鸣器,还有一块拓展区域,可作为日后拓展功能使用,开发单片机的更多功能。
二、软件开发流程1、新建工程打开Keil软件,点击“Project | New Project…”,弹出一个名为“Create New Project”的对话框。
然后选择一个合适的文件夹准备来存放工程文件。
2、选择CPUKeil提示选择CPU 器件。
选中ATMEL中的89c52即可。
接下来弹出一个对话框。
该对话框提示是否要把标准8051 的启动代码添加到工程中去,一般选择“否”。
3、新建一个.c文件点击新建文件,将文件名改为“text.c”,然后保存在合适的文件夹里。
扩展名“.c”不可省略。
4、添加源程序文件到工程中一个空的源程序文件“text.c”已经建立,但是这个文件与刚才新建的工程之间并没有什么内在联系,因此我们需要把它添加到工程中去。
单击Keil软件左边项目工作窗口“Target 1 ”上的“+”,将其展开。
然后右击“Source Group 1”文件夹,会弹出选择菜单。
单击其中的“Add Files to Group 'Source Group 1' ”项。
这时,对话框内将出现刚才保存过的“text.c”。
双击文件“text.c”,这时,源程序文件“text.c ”已经出现在项目工作窗口的“Source Group 1 ”文件夹内。
5、设计和编辑C语言程序单根据实验要求编辑C语言程序,并且通过反复的编译和调试以确保程序的正确性。
编辑“text.c ”文件,然后点击“Project”中的“compile”,根据运行结果调试程序,以达到目的。
实验一 跑马灯实验

学号***********序号34单片机原理与接口技术实验报告实验项目序号实验一实验项目名称跑马灯实验姓名王海标专业电气工程及其自动化班级电气15-2BF 完成时间2017年3月18日实验一跑马灯实验一、实验目的1、熟悉HNIST-2型单片机系统相关硬件电路,程序下载方法;2、掌握采用汇编语言与C语言开发单片机系统的程序结构;3、掌握51系列单片机通用I/O口的使用。
二、实验前准备1、完成作业3;2、根据实验内容编写好相关程序,并进行Proteus仿真。
三、实验内容1、基本的流水灯。
根据图3.1电路,编写一段程序,使8个发光二极管D1、D2、D3、D4、D5、D6、D7、D8顺序(正序)点亮:先点亮D1,再点亮D2、D3 (8)D1……,循环点亮。
每点亮一个LED,采用软件延时一段时间。
2、简单键控的流水灯。
不按键,按正序点亮流水灯;按下K1不松手,按倒序点亮流水灯,即先点亮D8,再顺序点亮D7、D6……D1、D8……。
松手后,又按正序点亮流水灯。
3、键控的流水灯。
上电,不点亮LED,按一下K1键,按正序点亮流水灯。
按一下K2键,按倒序点亮流水灯,按一下K3键,全部关闭LED。
四、软件设计思想1、基本的流水灯软件延时采用程序void delay(unsigned int c),可调整延时时间。
2、简单键控的流水灯。
由于是按下键不松手,键值一直保留,所以判断if(K1==0),即是按下K1,采用如例题所示的if(K1==0)或if(K1==1),后接while(1)循环的模式。
3、键控的流水灯由于是按一下键后马上松手,所以要设置一个变量K保留按键键值,由于单片机本身原理图所致,K17、K18、K19、K20四个键已经固定为K17=P2^0、K18=P2^1、K19=P2^2、K20=P2^3所以直接运用,利用如if(K1==0)的条件判断语句来判断是否按下K1、K2、K3按键,实现键控流水灯。
五、实验原理图如图3.1所示。
跑马灯单片机实训报告

一、前言随着科技的不断发展,单片机技术在各个领域得到了广泛的应用。
为了提高我们的实践能力,加强理论知识与实际操作的结合,我们进行了单片机跑马灯实训。
通过本次实训,我们深入了解了单片机的基本原理,掌握了单片机的编程方法,并能够运用所学知识解决实际问题。
二、实训目的1. 熟悉单片机的硬件结构和工作原理。
2. 掌握单片机的编程方法,包括汇编语言和C语言。
3. 学会使用单片机进行简单的外设控制。
4. 提高动手能力和团队合作能力。
三、实训内容1. 实训设备(1)8051单片机开发板(2)LED灯(3)电阻(4)电源2. 实训步骤(1)搭建电路首先,我们需要搭建跑马灯的电路。
将LED灯串联,然后连接到单片机的P1口。
在LED灯的正极和负极之间串联一个电阻,用于限流。
(2)编写程序接下来,我们需要编写跑马灯的程序。
以下是用C语言编写的跑马灯程序:```c#include <reg51.h>#define LED P1void delay(unsigned int ms) {unsigned int i, j;for (i = 0; i < ms; i++)for (j = 0; j < 1275; j++);}void main() {while (1) {LED = 0x01; // 第一个LED灯亮 delay(500); // 延时LED = 0x02; // 第二个LED灯亮 delay(500); // 延时LED = 0x04; // 第三个LED灯亮 delay(500); // 延时LED = 0x08; // 第四个LED灯亮 delay(500); // 延时LED = 0x10; // 第五个LED灯亮 delay(500); // 延时LED = 0x20; // 第六个LED灯亮 delay(500); // 延时LED = 0x40; // 第七个LED灯亮 delay(500); // 延时LED = 0x80; // 第八个LED灯亮 delay(500); // 延时LED = 0x00; // 所有LED灯熄灭delay(500); // 延时}}```(3)编译程序将编写的程序导入到单片机开发板中,并下载到单片机中。
单片机整套实验及程序(交通灯_跑马灯等)文档

单片机整套实验及程序(交通灯_跑马灯等)文档实验1 跑马灯实验一、实验目的●初步学会Proteus ISIS和uVision2单片机集成开发环境的使用;●初步掌握采用汇编语言与C语言开发单片机系统的程序结构;●掌握80C51单片机通用I/O口的使用;●掌握单片机内部定时/计数器的使用及编程方法以及中断处理程序的编写方法。
二、实验设备及器件●硬件:PC机,HNIST-1型单片机实验系统●软件:Proteus ISIS单片机仿真环境,uVision2单片机集成开发环境三、实验内容●编写一段程序,采用P1口作为控制端口,使与P1口相接的四个发光二极管(D1、D2、D3、D4)按照一定的方式点亮。
如点亮方式为:先点亮D1,延时一段时间,再顺序点亮D2……D4,然后又是D4……D1,同时只能有一个灯亮;然后每隔一段时间一次使相邻两个灯亮,三个灯亮,四个灯亮,最后闪烁三次,接着循环变化。
●基于Proteus ISIS仿真环境完成上述功能的仿真。
●基于uVision2单片机集成开发环境与硬件平台完成程序的脱机运行。
四、实验原理图图3.1 跑马灯实验电路原理图电路原理图如上图3.1所示,AT89S52的P1.0~P1.3控制4个发光二极管,发光二极管按照一定次序发光,相邻发光二极管的发光时间间隔可以通过定时器控制,还可以通过软件延时实现。
五、软件流程图与参考程序● 主程序流程图如下:● 参考程序#include#include#define uchar unsigned char#define uint unsigned intuchar aa ,num ,speed ,flag;uchar code table[]={0x0e ,0x0d ,0x0b ,0x07};uchar code table1[]={0x0a ,0x05,0x09,0x06};uchar codetable2[]={0x0c ,0x09,0x03,0x08,0x01,0x0e ,0x0c ,0x08,0x00}; void delay(uint z)//延时函数uint x;uchar y;for(x=z;x>0;x--)for(y=200;y>0;y--);}void init()//条件初始化函数{ flag=0;speed=10;//控制跑马灯流水速度TMOD=0x01;//中断方式开始初始化(定时器、中断、标志位设置) Flag=1? 流水灯操作结束 Y NTH0=(65535-50000)/256;TL0=(65536-50000)%256;//初值EA=1;//打开总中断ET0=1;//打开外中断0TR0=1;}void main(){init();//调用初始化函数while(1){if(flag){delay(2000);//调用延时函数for(num=0;num<4;num++)//从左至右间隔一个依次闪烁{P1=table[num];delay(2000);for(num=3;num>0;num--)//从左至右间隔一个依次闪烁{P1=table[num];delay(2000);}for(num=0;num<4;num++)//从左至右间隔两个依次闪烁{P1=table1[num];delay(2000);}for(num=3;num>0;num--)//从左至右间隔两个依次闪烁{P1=table1[num];delay(2000);}for(num=0;num<6;num++)//两个,三个,四个跑马灯依次闪烁{P1=table2[num];delay(2000);}for(num=0;num<5;num++)//闪烁5次{P1=0xff;//全暗delay(2000);P1=0X00;//全亮delay(2000);}speed=speed-3;//变速if(speed==4){speed=10;}}}}void timer0() interrupt 1//中断函数{TH0=(65535-50000)/256;TL0=(65536-50000)%256;aa++;if(aa==speed){aa=0;flag=1;}}六、实验思考题●请用汇编指令完成本实验内容,深刻理解汇编语言程序设计结构。
单片机 跑马灯实验精选全文

可编辑修改精选全文完整版实验一跑马灯实验一、实验内容1、基本的流水灯根据图1电路,编写一段程序,使8个发光二极管D1、D2、D3、D4、D5、D6、D7、D8顺序(正序)点亮:先点亮D1,再点亮D2、D3……D8、D1……,循环点亮。
每点亮一个LED,采用软件延时一段时间。
2、简单键控的流水灯不按键,按正序点亮流水灯;按下K1不松手,按倒序点亮流水灯,即先点亮D8,再顺序点亮D7、D6……D1、D8……。
松手后,又按正序点亮流水灯。
3、键控的流水灯上电,不点亮LED,按一下K1键,按正序点亮流水灯。
按一下K2键,按倒序点亮流水灯,按一下K3键,全部关闭LED。
二、实验方案1、总体方案设计考虑到K4键未被使用,所以将实验内容中的三项合并到一个主函数中:K4键代替实验内容第二项中的K1键;单片机一开机即执行实验内容第一项;K1、K2、K3键实现实验内容第三项。
所用硬件:AT89C52、BUTTON、LED-BLUE、电源输入:P2.0-K1;P2.1-K2;P2.2-K3;P2.3-K4。
低电平有效输出:P0.0~P0.7-D0~D7。
LED组连线采用共阳极,低电平有效软件设计:软件延时采用延时函数delay(t),可调整延迟时间:void delay(uint t){uint i;while(t--)for(i=0;i<1000;i++){if(P2!=oldK&&P2!=K[0])break;//按下了其他键退出循环}}由于涉及到按键变化所以要设置一个变量oldK保留按键键值,要在延时程序中检测是否按键,当按键后立即设置oldK的值。
按键判断采用在while循环中利用条件语句判断P2的值然后执行该键对应的代码段,达到相应的响应。
为了让K4键的效果优化,即状态变化从当前已亮灯开始顺序点亮或逆序点亮,利用全局变量n来记录灯号,利用算法即可实现。
主要算法:1、全局变量的定义:uchar D[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0X7f};//单个LED亮uchar AllOff=0xff;//LED全灭uchar AllOn=0x00;//LED全亮uchar K[]={0xff,0xfe,0xfd,0xfb,0xf7};//按键开关uchar oldK;//记录已按键int n;2、顺序、逆序点亮流水灯:void forward(){for(n=0;n<=7;n++){out=D[n];delay(15);if(P2!=oldK&&P2!=K[0])break;}out=AllOff;}void backward(){for(n=7;n>=0;n--){out=D[n];delay(15);if(P2!=oldK&&P2!=K[0])break;}out=AllOff;}3、实验内容第二项流水灯灯亮顺序变换:void hold(){n=8;while(1){if(P2==K[4]){//一直按着K4键,逆序点亮跑马灯oldK=K[4];if(n==-1)n=7; //D0灯亮后点亮D7while(n>=0){out=D[n];n--;if(delay4(15))break;}}if(P2==K[0]){//未按下K4键,一直正序点亮跑马灯oldK=K[0];if(n==8)n=0;//D7灯亮后点亮D0while(n<=7){out=D[n];n++;if(delay4(15))break;}}if(P2!=K[4]&&P2!=K[0]){//按下了其他键,退出hold函数break;}}}4、对应实验内容第一项,开机顺序点亮流水灯:while(1){//开机即正序点亮流水灯forward();if(P2!=K[0]){break;}}2、实验原理图图2-1 实验原理图3、程序流程图图2-2 程序流程图三、源程序#include"reg51.h"#define uchar unsigned char#define uint unsigned int#define out P0uchar D[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0X7f};//单个LED亮uchar AllOff=0xff;//LED全灭uchar AllOn=0x00;//LED全亮uchar K[]={0xff,0xfe,0xfd,0xfb,0xf7};//按键开关uchar oldK;//记录已按键int n;//记录当前亮的灯号void delay(uint t){uint i;while(t--)for(i=0;i<1000;i++){if(P2!=oldK&&P2!=K[0])break;//按下了其他键退出循环}}void delay10ms(){uint i;for(i=0;i<10000;i++);}void forward(){for(n=0;n<=7;n++){out=D[n];delay(15);if(P2!=oldK&&P2!=K[0])break;}out=AllOff;}void backward(){for(n=7;n>=0;n--){out=D[n];delay(15);if(P2!=oldK&&P2!=K[0])break;}out=AllOff;}int delay4(uint t){uint i;while(t--)for(i=0;i<1000;i++){if(P2!=oldK){ //按键变化退出循环return 1;}}return 0;}void hold(){n=8;while(1){if(P2==K[4]){//一直按着K4键,逆序点亮跑马灯oldK=K[4];if(n==-1)n=7; //D0灯亮后点亮D7while(n>=0){n--;if(delay4(15))break;}}if(P2==K[0]){//未按下K4键,一直正序点亮跑马灯oldK=K[0];if(n==8)n=0;//D7灯亮后点亮D0while(n<=7){out=D[n];n++;if(delay4(15))break;}}if(P2!=K[4]&&P2!=K[0]){//按下了其他键,退出hold函数break;}}}void main(){oldK=K[0];while(1){//开机即正序点亮流水灯forward();if(P2!=K[0]){break;}}while(1){out=AllOff;if((P2&0x0f)!=0x0f){//检测有键按下delay10ms();//延时10ms再去检测//P2.0_K1键按下正序点亮流水灯if(P2==K[1]){oldK=K[1];while(1){forward();if(P2!=K[1]&&P2!=K[0]){//按下了其他键,退出break;}}}//P2.1_K2键按下逆序点亮流水灯if(P2==K[2]){while(1){backward();if(P2!=K[2]&&P2!=K[0]){//按下了其他键,退出break;}}}//P2.2_K3键按下关闭全部LEDif(P2==K[3]){oldK=K[3];out=AllOff;}//P2.3_K4键按下长按逆序点亮流水灯,不按正序点亮流水灯,直到其他键按下停止if(P2==K[4]){hold();}}}}四、实验结果1、基本的流水灯:开机后即重复顺序点亮流水灯,等待其他按键。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
void hold(){
n=8;
while(1){
if(P2==K[4]){//一直按着K4键,逆序点亮跑马灯
oldK=K[4];
if(n==-1)n=7;//D0灯亮后点亮D7
while(n>=0){
out=D[n];
n--;
if(delay4(15))break;
}
}
if(P2==K[0]){//未按下K4键,一直正序点亮跑马灯
void hold(){
n=8;
while(1){
if(P2==K[4]){//一直按着K4键,逆序点亮跑马灯
oldK=K[4];
if(n==-1)n=7;//D0灯亮后点亮D7
while(n>=0){
out=D[n];
n--;
if(delay4(15))break;
}
}
if(P2==K[0]){//未按下K4键,一直正序点亮跑马灯
图43键控的流水灯
五、实验思考题
1、采用I/O口作为输出口时要考虑哪些因素?为什么实验装置中LED要串联一个电阻?
当作为输出口时候就是单片机向外发出数据,或者再产生拉电流,单片机的拉电流一般要比灌电流小,基本上就能点亮2,3个LED,功率很有限,所以一般时候必须用驱动芯片来驱动单片机的外围器件。串联电阻是为了保护电路。
while(1){//开机即正序点亮流水灯
forward();
if(P2!=K[0]){
break;
}
}
while(1){
out=AllOff;
if((P2&0x0f)!=0x0f){//检测有键按下
delay10ms();//延时10ms再去检测
//P2.0_K1键按下正序点亮流水灯
if(P2==K[1]){
break;
}
}
}
//P2.2_K3键按下关闭全部LED
if(P2==K[3]){
oldK=K[3];
out=AllOff;
}
//P2.3_K4键按下长按逆序点亮流水灯,不按正序点亮流水灯,直到其他键按下停止
if(P2==K[4]){
hold();
}
}
}
}
四、实验结果
1、基本的流水灯:
开机后即重复顺序点亮流水灯,等待其他按键。(如图4-1)
for(i=0;i<10000;i++);
}
void forward(){
for(n=0;n<=7;n++){
out=D[n];
delay(15);
if(P2!=oldK&&P2!=K[0])
break;
}
out=AllOff;
}
void backward(){
for(n=7;n>=0;n--){
out=D[n];
为了让K4键的效果优化,即状态变化从当前已亮灯开始顺序点亮或逆序点亮,利用全局变量n来记录灯号,利用算法即可实现。
主要算法:
1、全局变量的定义:
uchar D[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0X7f};//单个LED亮
uchar AllOff=0xff;//LED全灭
delay(15);
if(P2!=oldK&&P2!=K[0])
break;
}
out=AllOff;
}
int delay4(uint t){
uint i;
while(t--)
for(i=0;i<1000;i++){
if(P2!=oldK){//按键变化退出循环
return 1;
}
}
return 0;
uint i;
while(t--)
for(i=0;i<1000;i++){
if(P2!=oldK&&P2!=K[0])break;//按下了其他键退出循环
}
}
由于涉及到按键变化所以要设置一个变量oldK保留按键键值,要在延时程序中检测是否按键,当按键后立即设置oldK的值。
按键判断采用在while循环中利用条件语句判断P2的值然后执行该键对应的代码段,达到相应的响应。
oldK=K[0];
if(n==8)n=0;//D7灯亮后点亮D0
while(n<=7){
out=D[n];
n++;
if(delay4(15))break;
}
}
if(P2!=K[4]&&P2!=K[0]){//按下了其他键,退出hold函数
break;
}
}
}
void main(){
oldK=K[0];
在调试过程中,我发现定义但未使用的变量或函数编译后会报警告,其余语法与传统C一样,因此在编程过程中并未遇到什么特别的问题,对于本实验涉及到的算法对于我来说也不是什么难事。在软件延时的函数延时方面,我发现对于不同处理函数其延时时间并不是很准确,若要满足准确的延时还需要用到定时器。
总的来说,本次实验完成地很顺利,所有实验内容也全部完成了,我也对单片机的使用及C51的编程有了很大的兴趣,期待下一次的实验也能顺利完成!
while(1){//开机即正序点亮流水灯
forward();
if(P2!=K[0]){
break;
}
}
2
图21实验原理图
3
图22程序流程图
三、源程序e uchar unsigned char
#define uint unsigned int
#define out P0
3
上电,不点亮LED,按一下K1键,按正序点亮流水灯。按一下K2键,按倒序点亮流水灯,按一下K3键,全部关闭LED。
二、实验方案
1
考虑到K4键未被使用,所以将实验内容中的三项合并到一个主函数中:K4键代替实验内容第二项中的K1键;单片机一开机即执行实验内容第一项;K1、K2、K3键实现实验内容第三项。
uchar AllOn=0x00;//LED全亮
uchar K[]={0xff,0xfe,0xfd,0xfb,0xf7};//按键开关
uchar oldK;//记录已按键
int n;
2、顺序、逆序点亮流水灯:
void forward(){
for(n=0;n<=7;n++){
out=D[n];
delay(15);
uchar oldK;//记录已按键
int n;//记录当前亮的灯号
void delay(uint t){
uint i;
while(t--)
for(i=0;i<1000;i++){
if(P2!=oldK&&P2!=K[0])break;//按下了其他键退出循环
}
}
void delay10ms(){
uint i;
可以具体事情具体处理,方便灵活的调用。
六、总结
通过本次实验,我不仅更熟悉了Protues及Keil软件的使用,对C51编程的使用也更上一层楼,对于C51的编程语句与传统的C语言编程有一些区别,其中的无符号字符型是我在C语言中从未使用过的,在C51编程中会经常用到,用来给单片机的端口赋值或判断端口的值。对于C51的编程,编译报错也与传统C不同。
图41基本的流水灯
2、简单键控的流水灯:
按下K4键即点亮D7灯,若一直按着K4键逆序点亮流水灯,松开则顺序点亮流水灯,且按键状态改变时送当前已亮的灯开始变换顺序而不是从D0或D7灯开始亮灯。(如图4-2)
图4-2简单键控的流水灯
3、键控的流水灯:
K1键按下顺序点亮流水灯,K2键按下逆序点亮流水灯,K3键按下全局灭灯。(如图4-3)
oldK=K[0];
if(n==8)n=0;//D7灯亮后点亮D0
while(n<=7){
out=D[n];
n++;
if(delay4(15))break;
}
}
if(P2!=K[4]&&P2!=K[0]){//按下了其他键,退出hold函数
break;
}
}
}
4、对应实验内容第一项,开机顺序点亮流水灯:
所用硬件:AT89C52、BUTTON、LED-BLUE、电源
输入:P2.0-K1;P2.1-K2;P2.2-K3;P2.3-K4。低电平有效
输出:P0.0~P0.7-D0~D7。LED组连线采用共阳极,低电平有效
软件设计:
软件延时采用延时函数delay(t),可调整延迟时间:
void delay(uint t){
oldK=K[1];
while(1){
forward();
if(P2!=K[1]&&P2!=K[0]){//按下了其他键,退出
break;
}
}
}
//P2.1_K2键按下逆序点亮流水灯
if(P2==K[2]){
oldK=K[2];
while(1){
backward();
if(P2!=K[2]&&P2!=K[0]){//按下了其他键,退出
uchar D[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0X7f};//单个LED亮
uchar AllOff=0xff;//LED全灭
uchar AllOn=0x00;//LED全亮
uchar K[]={0xff,0xfe,0xfd,0xfb,0xf7};//按键开关