单片机流水灯总结_单片机流水灯用什么定时器实现流水灯的加减灯 - CSDN
  • 51单片机驱动流水灯可以更好的理解IO口,这一节就主要来用查表法和移位法来实现流水灯,首先先看电路图。  电路比较简单,发光二极管正极接5V电源,负极接470Ω限流电阻,接单片机P0口,限流电阻470Ω怎么计算?...

           51单片机驱动流水灯可以更好的理解IO口,这一节就主要来用查表法和移位法来实现流水灯,首先先看电路图。

            电路比较简单,发光二极管正极接5V电源,负极接470Ω限流电阻,接单片机P0口,限流电阻470Ω怎么计算?来看看,普通发光二极管正向饱和电压为1.6~2.1V,正向饱和电流为5~20mA,但不同颜色的发光二极管参数有所差异。这里没必要精确计算,我们取中间值电压1.8V,电流10mA。由欧姆定律,解得R=(5-1.8)/10=320Ω,图中电阻选用常用的470Ω。

            由电路图可以知道,单片机P0口只需要输出低电平,就可以点亮LED灯。图中采用低电平驱动,主要是P0口低电平驱动能力比较好。

            现在先来看个闪烁灯的程序。

    /*********************************************
    **程序名称:LED闪烁灯
    **程序功能:一个LED闪烁,频率为2HZ
    **编写:李松泽
    **时间:2014-12-25
    **********************************************/
    #include <reg52.h>
    sbit LED=P0^0;//位定义
    #define uchar unsigned char
    #define uint unsigned int
    /*********************************************
    **函数名称:void delay_ms(uint x)
    **函数功能:延时xms
    **入口参数:uint x
    **出口参数:
    *********************************************/
    void delay_ms(uint x)
    {
        uint i,j;
        for(i=x;i>0;i--)
            for(j=110;j>0;j--);
    }
    /*********************************************
    **函数名称:void main()
    **函数功能:主函数
    **入口参数:
    **出口参数:
    *********************************************/
    void main()
    {
        while(1)
        {
            LED=0;//LED亮
            delay_ms(500);
            LED=1;//LED灭
            dealy_ms(500);		
        }
    }	 

              这个程序比较简单,但同时也说明了51单片机可以对单个位定义操作,在16位MSP430单片机中就不能单独操作一个位。在程序的编写中就比较方便。       

    流水灯程序以下用两种方法,首先先看查表法,部分程序说明在代码中解释。

    /*********************************************
    **程序名称:驱动流水灯
    **程序功能:8个LED依次从左到右,从右到左点亮,频率为500ms
    **编写:李松泽
    **时间:2014-12-25
    **********************************************/
    #include <reg52.h>
    #define uchar unsigned char
    #define uint unsigned int
    uchar tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,
                 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//赋给P0口的数据
    /*********************************************
    **函数名称:void delay_ms(uint x)
    **函数功能:延时xms
    **入口参数:uint x
    **出口参数:
    *********************************************/
    void delay_ms(uint x)
    {
        uint i,j;
        for(i=x;i>0;i--)
            for(j=110;j>0;j--);
    }
    /*********************************************
    **函数名称:void main()
    **函数功能:主函数
    **入口参数:
    **出口参数:
    *********************************************/
    //查表法:
    void main()
    {
         while(1)
        {
             uchar i;
    	 for(i=0;i<16;i++)
    	 {
                 P0=tab[i];
                 delay_ms(500);
    	 }
        }
    }


    移位法:

    /*********************************************
    **程序名称:驱动流水灯
    **程序功能:8个LED依次从左到右,从右到左点亮,频率为500ms
    **编写:李松泽
    **时间:2014-12-25
    **********************************************/
    #include <reg52.h>
    #define uchar unsigned char
    #define uint unsigned int
    /*********************************************
    **函数名称:void delay_ms(uint x)
    **函数功能:延时xms
    **入口参数:uint x
    **出口参数:
    *********************************************/
    void delay_ms(uint x)
    {
        uint i,j;
        for(i=x;i>0;i--)
            for(j=110;j>0;j--);
    }
    /*********************************************
    **函数名称:void main()
    **函数功能:主函数
    **入口参数:
    **出口参数:
    *********************************************/
    //移位法:
    void main()
    {
        uchar i,j;
        while(1)
        {
            P0=0xfe;
            for(i=0;i<8;i++)
            {
                delay_ms(500);//进入循环,先延时500ms
                P0<<=1; //P0口数据左移
                P0|=0x01; //将低位置1
                }
            P0=0x7f;
            for(i=0;i<8;i++)
            {
                delay_ms(500);//进入循环,先延时500ms
                P0>>=1; //P0口数据左移
                P0|=0x80;//将高位置1	
            }
        }
    }



    展开全文
  • 51单片机流水灯原理 在实验之前必须的准备工作有: 1.单片机 STC90C51 2.编译软件keil 3.烧写软件 4.面包板 5.发光二极管 实验说明:通过单片机芯片,定时在引脚P00,P01,P02,P03循坏输出高电平,制作...

    51单片机流水灯原理

    在实验之前必须的准备工作有:

    1.单片机 STC90C51

    2.编译软件keil

    3.烧写软件

    4.面包板

    5.发光二极管

    实验说明:通过单片机芯片,定时在引脚P00,P01,P02,P03循坏输出高电平,制作流水灯效果

    重要端口:

     

    原理说明:(红色部分为该实验电路图)

    电流顺序:VCC正极进入 》 芯片P0.0触发一个高电平 》 LED0二极管 》 EA 》 GND负极流出

     

     

    C语言编程烧写代码:

    /**************************************************************************************
    *		              LED闪烁实验												  *
    实现现象:下载程序后指示灯闪烁
    注意事项:无																				  
    ***************************************************************************************/
    
    #include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
    typedef unsigned int u16;	  //对数据类型进行声明定义
    typedef unsigned char u8;
    
    
    sbit led0=P0^0;		 //将单片机的P0.0端口定义为led
    sbit led1=P0^1;
    sbit led2=P0^2;
    sbit led3=P0^3;
    /*******************************************************************************
    * 函 数 名         : delay
    * 函数功能		   : 延时函数,i=1时,大约延时10us
    *******************************************************************************/
    void delay(u16 i)
    {
    	while(i--);	
    }
    
    /*******************************************************************************
    * 函 数 名       : main
    * 函数功能		 : 主函数
    * 输    入       : 无
    * 输    出    	 : 无
    *******************************************************************************/
    void main()
    {
    	while(1)
    	{
    		led0=0;
    		delay(50000); //大约延时450ms
    		led0=1;
    		delay(50000); //大约延时450ms
    		led1=0;
    		delay(50000); //大约延时450ms
    		led1=1;
    		delay(50000); //大约延时450ms
    		led2=0;
    		delay(50000); //大约延时450ms
    		led2=1;
    		delay(50000); //大约延时450ms
    		led3=0;
    		delay(50000); //大约延时450ms
    		led3=1;
    		delay(50000); //大约延时450ms	
    	}		
    }
    

     

     

     

    总结不好多多担待,文章只单纯个人总结,如不好勿喷,技术有限,有错漏麻烦指正提出。本人QQ:373965070

     

    展开全文
  • 嵌入式 51单片机 流水灯原理详解

    流水灯基本原理:

     

    实验所需:

    语言:C     芯片:STC90C51    板子:51单片机

     

     

     

     

     

    电路图(局部就是电阻和灯)


    流水灯运作原理:STC90C51芯片通过操作导致指定引脚释放出高电平,所对应的灯接收到闭合电路产生电流导致LED等闪亮。

     

    以上是8个灯的简单视图,要启动对应灯,必须在以上接口提供高电平且形成闭合电路

     

    芯片操作:操作利用的是引脚4组随机一组,我使用的是P0口,通过烧写把代码烧进flash内存,代码如下:

     

    #include <reg51.h>	    //导入库文件,芯片公司写好的库文件方便调用
    
    
    
    void Delay10ms(unsigned int c);   //延迟10MS
    
    
    void main()
    { 
    	while(1)
    	{
    
    		P0  = 0x00;  //00000000   所有灯电平为低电平
    		
    		Delay10ms(100); 
    		  
    		P0  = 0xff;   //11111111   所有灯电平为高电平
    				
    		Delay10ms(100); 
    		
    	}
    
    }
    
    //通过循环的执行时间来延迟
    void Delay10ms(unsigned int c)   
    {
        unsigned char a, b;
    
        for (;c>0;c--)
    	{
    		for (b=38;b>0;b--)
    		{
    			for (a=130;a>0;a--);
    		}       
    	}   
    }

     

     

    扩展例子:(运作->全灭->1~8灯暗顺序单个亮->最后全亮)

     

    #include <reg51.h>	    
    
    void Delay10ms(unsigned int c);   
    
    
    void main()
    { 
    	while(1)
    	{
    
    		P0  = 0x00;  //00000000   	
    		Delay10ms(100); 
    		
    		P0  = 0x01;  //00000001   
    		Delay10ms(100); 
    	 
    	  P0  = 0x02;  //00000010  
    		Delay10ms(100); 
    		
    		P0  = 0x04;  //00000100 
    		Delay10ms(100); 
    
    		P0  = 0x08;  //00001000 
    		Delay10ms(100); 
    		
    	  P0  = 0x08;  //00001000 
    		Delay10ms(100); 
    		
    	  P0  = 0x10;  //00010000 
    		Delay10ms(100); 
    		
    		P0  = 0x20;  //00100000 
    		Delay10ms(100); 
    		
    	  P0  = 0x40;  //01000000 
    		Delay10ms(100); 
    		
    	  P0  = 0x80;  //10000000 
    		Delay10ms(100); 
    
        P0  = 0xff;  //11111111
    		Delay10ms(100);
    
    	}
    
    }
    
    
    void Delay10ms(unsigned int c)   
    {
        unsigned char a, b;
    
        for (;c>0;c--)
    	{
    		for (b=38;b>0;b--)
    		{
    			for (a=130;a>0;a--);
    		}       
    	}   
    }
    
    


    解析:以上例子已经很清楚显示出来,1为高电平,0为低电平,通过高低搭配把电压输出到引脚而使LED流水灯发亮.

     

    例如:用二进制表示八个灯情况,若只需要第3个灯亮    0000 0100  -> P0 = 0x04  二进制转换16进制输出

     

     

    总结不好多多担待,文章只单纯个人总结,如不好勿喷,技术有限,有错漏麻烦指正提出。本人QQ:373965070

    展开全文
  • 51单片机流水灯制作

    2018-10-14 17:40:04
    参加学院飞思卡尔选拔赛的复试,被要求完成一个基于51单片机流水灯项目。现实版实现了流水灯以及三角形波的呼吸灯以及一个随机点亮。理想版的自然是想实现流水灯、三角形波呼吸灯以及正弦波呼吸灯

    51单片机流水灯制作

    我不得不承认自己的毅力实在是太差了,原先准备一星期写一篇博客的目标一致没有实现,挺惭愧的。前几日忙着参加学院里面关于飞思卡尔竞赛的选拔赛,被要求制作一个用51单片机实现的流水灯和呼吸灯,耗费了我不少时间。现将其记录于此。

    初试与复试

    初试

    原本我是不打算参加初试的,让我朋友参加,积累经验,我专心鼓捣制作机器人,但我的朋友说我应该试试,耗费时间,但有利于我实现制作机器人的计划。
    初试还算简单, 主要考察了数电模电以及c语音和飞思卡尔小车的实现思路等。我两手空空就去了考场,遭到了朋友的笑话,说我要是能入选就奇了怪了。因为开卷,所以基本上数电模电翻书找即可,实现思路之类的只好跟朋友共享其事先打印的资料了。好在脸皮厚,成功抵挡了无数白眼。c语言部分也不算难,有个位移的还算有趣,就是对<<符号的考察。
    初试结果自然出乎我朋友的意料,我通过了,而两位朋友成功落选。我自然很是得意。不过他们向组织方表达了自己对飞思卡尔的向往后,还是被允许参加复试了。

    复试

    任务:

    • 设计并制作基于 51 单片机的流水灯,通过按键实现 LED 灯点亮模
      式的切换。
    • 用 DXP 画出附录原理图, 并保存为.SchDoc 格式。

    要求

    • 基本要求:( 80 分)
    • 所搭建的板子至少 8 个 LED 灯, 4 个按键,可实现至少四种 LED
      点亮模式的变换。( 50 分)
    • 上交一份设计报告, 报告内容包括组元分工、硬件及软件设计,另需在附录附上完整程序。( 20 分)
    • 上交附录原理图。( 10 分)
    • 发挥部分:( 20 分)
    • 电路布局美观, 无虚焊, 焊点光度锥度好。
    • 程序运行稳定。
    • 其他。

    制作

    分工

    我为队长,其他两人分别攻硬件DXP与软件编程。
    先期我们的主要任务是了解51单片机的大致流程,求广,防止方向的选择错误。

    制作之硬件

    后来因为大家事都挺忙的,我就扛起了大梁。
    在网上买了所需的东西后,我便照着葫芦画瓢,在面包板上搭建电路。第一次是在晚上11点左右,果不其然的搭建错了。没有考虑面包板的结构。后来就改正了。
    在网上买的PL2303的USB转ttl线出了问题,刚开始是引脚缺杜邦头,后来我自己想办法给焊上去个杜邦头,还是不能用,貌似其内部短路,向周围的人借,也没有借到。只好从网上买了个ch340的usb转ttl线,谢天谢地,这个很好用。usb转ttl线就这样耽误了一个星期。在此处记录一下,usb转ttl线需要驱动,通过该线向单片机里烧录程序需要另外的软件,我用的是STC-ISP(竟然有个每次下载前都重新装载目标文件选项,坑死我了,不知有多少回我忘记点这个选项而没有装载修改后的hex文件去烧录,看着不能按照预期工作的单片机,又投入到keil中,好悲惨的回忆)。
    吐槽一下硬件,好多坑啊。电烙铁用到还行,因为没有买用来飞线的导线,用心疼焊锡,只好把排针上金属针拔下来一个一个的焊当导线,好悲催啊。中间好几回虚焊漏焊,其中艰难不足为外人道也。

    制作之软件

    因为负责软件工作的同学比较忙,所以我接手了程序的开发。他只完成了基本的流水灯部分,而且冗余的代码超多,我又优化了一番。比如说对开关引脚的判断,竟然用了4个if语句,还没有考虑全,我简单几句就搞定了,还有对开关变化的判断。然后开始添加新功能。
    因为我觉得单个的呼吸灯可能会比较没有竞争力,所以准备不光实现灯的强度在时间维度上呈三角波,还要实现灯的强度在空间维度上呈三角波,甚至要实现灯的强度在时间、空间上同时呈三角波(就是初相位相差一定值的平行三角波),想想就美好。不光要有三角波,还要有正弦波,再多加个强度相差一定值的正弦波(感觉这个比初相位相差一定知道正弦波计算量小些)。
    需求想好了,就该实现了。我需要手动完成PWM。总结了一下实现PWM的几种思路:

    • 用一个定时器定时,如以100μs为一个小周期,然后以100个小周期为一个PWM周期(10ms),频率为100Hz(1s / 10 ms)。在定时器中断处理函数里直接输出buffer中的数据,或者在处理函数中处理判断后输出数据。
    • 用一个定时器定时,比如给通电时间(占空比 * PWM周期)定时,然后在中断处理函数中启动不通电时间(PWM周期 - 通电时间)的定时,可用原来的定时器也可用其他的定时器。
    • 用一个定时器给PWM周期定时,然后用另外一个定时器给通电时间(也可以是不通电时间)定时。
      综合考虑后我选择第一种方法,噩梦才刚刚开始。
      如何实现不同相位的多个平行正弦波的呼吸灯?使用小周期只是提供了实现的可能而已,还不够。后来在操场上散步时,才想明白了实现方式。我靠自己想明白了单极性脉宽调制的原理,相当激动啊。换句话说,我是使用单极性脉宽调制来实现想法的。设置一个数组来存储八个LED的占空比,占空比在时间维度上不断的沿正弦函数变化,在每个小周期的定时器中断时通过占空比与小周期计数的大小比较来确定引脚输出
      然而实际效果不尽人意,几乎就是随意的亮灭。后来我通过keil的仿真是才发现,51单片机的计算能力太差,中断处理函数结束时,下一次中断几乎就出来了。对八个占空比的处理不能在完整的一次完成。几天的努力还是没能实现的自己当初的想法,有些失落,虽然自己收获了不少,特别是感觉自己对c语言小技巧的使用(有些自大啦啦啦)。
      后来也就没办法,只好不用正弦波,只用三角波了。三角波也能玩出新花样。比如两排强度互补的呼吸灯。其实就是在传统意义上的不通电时间时输出对在通电时期输出数据的取反,比如在通电时间是输出0x00,在不通电时间输出0xFF。

    总结

    其他的好像也没什么可以说的了。好不容易能沉下心写会技术博客的感觉真好!!!

    附录:

    程序之现实版

    #include <STC89C5xRC.H>
    #include<intrins.h>
    #include<math.h>
    #include<stdlib.h>
    
    
    /*************全局常量***********/
    #define uchar unsigned char 
    #define uint unsigned int
    #define LED P1
    
    /*****************全局变量**********************************/
    uchar changed, status_switch = 0x00, status_switch_pre = 0x00;	//status_switch记录当前开关状态,status_switch_pre记录此前开关状态,changed记录开关状态是否变化
    uchar counter_PWM = 0, length_PWM = 100;	//定时器0的两次中断时间为一小周期,length_PWM个小周期组成一个PWM大周期,counter_PWM负责计数,表示进行到了PWM大周期中的第counter_PWM个小周期
    uchar duty_cycle, buffer;	//duty_cycle是占空比,buffer缓冲LED点亮信息
    
    uchar i, j;
    float f;
    
    /*******************部分流水灯模式所需信息**************/
    uchar code table1[]={0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfc,0xff};
    		//0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f	左移
    uchar code table2[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf}; 
    uchar code table3[]={0x7e,0xbd,0xdb,0xe7,0xff};
    uchar code table4[]={0xaa,0x55};
    
    /*********函数声明********************/
    void delay1ms();
    void delay(uint x);
    void keyscan();
    void close_int();
    void init_pwm();
    void timer0_init(void);
    
    
    /********主函数****************************/
    void main()
    {
    	while(1) {
    		keyscan(); 
    
    		switch (status_switch) {	//根据status_switch选择灯的点亮模式
    		case 0x00:
    			LED = 0xFF;
    			break;
    		case 0x01:
    			for (i=0;i<16;i++) { 
    				LED=table1[i];     
    				delay(200);
    				keyscan();     
    				if (changed)
    					break;   
    			}   
    			break; 
    		case 0x02:
    			for(i=0;i<14;i++) { 
    				LED=table2[i];     
    				delay(300);
    				keyscan();     
    				if (changed)
    					break;   
    			}
    			break;			
    		case 0x03:
    			for(i=0;i<5;i++) {
    				LED=table3[i];     
    				delay(250);
    				keyscan();     
    				if (changed)
    					break;   
    			}
    			break; 			
    		case 0x04:
    			for(i=0;i<2;i++){
    				LED=table4[i];     
    				delay(3000);
    				keyscan();     
    				if (changed)
    					break;      
    			}
    			break;			
    		case 0x05:
    			for (i=0;i<16;i++) { 
    				LED=~table1[i];     
    				delay(200);
    				keyscan();     
    				if (changed)
    					break;   
    			}   
    			break; 
    			
    		case 0x06:
    			for(i=0;i<14;i++) { 
    				LED=~table2[i];     
    				delay(500);
    				keyscan();     
    				if (changed)
    					break;   
    			}
    			break;		 
    		case 0x07:
    			for(i=0;i<5;i++) {
    				LED=~table3[i];     
    				delay(250);
    				keyscan();     
    				if (changed)
    					break;   
    			}
    			break; 
    
    		case 0x08:
    		case 0x09:
    		case 0x0A:
    		case 0x0B:
    			timer0_init();
    			while (1) {
    				init_pwm();		
            		for (i = 100; i > 0; i-=5) {
                		duty_cycle = i;				//改变占空比		
             			delay(25);
    					keyscan();					//开关检测
    					if (changed) {
    						close_int();			//关闭定时器
    						break;					//退出for语句
    					}
            		}
    				break;							//退出switch语句
    				for (i = 0; i < 100; i+=5) {
                		duty_cycle = i;
              			delay(25);
    					keyscan();					//在该case语句中设置两个keyscan是为了更快的对开关变化做出响应
    					if (changed) {
    						close_int();
    						break;
    					}
            		}
    				break;		
    			}
    			break;
    
    		case 0x0C:			
    		case 0x0D:
    			timer0_init();
    			while (1) {
    				init_pwm();       			
             		delay(250);			//因为不需要改变有时间维度上的变化,所以没有占空比的改变,只需延时即可
    
    				keyscan();
    				if (changed) {
    					close_int();
    					break;
    				}
    			}
    			break;
    			 
    		case 0x0E:
    			srand(counter_PWM);	 //设置随机数种子
    			while(1) {
    				LED = rand() % 256;		//保证随机数在0与255之间
    				delay(200);
    				
    				keyscan();
    				if (changed)
    					break;	
    			}
    
    			break; 
    		case 0x0F:	
    			LED = 0x00;
    			break;
    		} 
    	}
    }
    
    /*****************延时1ms*************/
    void delay1ms()		//@11.0592MHz
    {
    	unsigned char i, j;
    
    	_nop_();
    	i = 2;
    	j = 199;
    	do
    	{
    		while (--j);
    	} while (--i);
    }   
    
    /**********延时x毫秒***********/
    void delay(uint x)
    {   uchar k;
    	for(k=x; k>0; k--)
    		delay1ms();
    }
    
    /****开关检测。修改开关状态(status_switch)以及更改标志(changed)****/
    void keyscan()  
    { 
    	status_switch_pre = status_switch;			//记录此前的开关状态
    	P2 = 0xFF;									//准备读取P2
    	status_switch = (~P2) & 0x0F;				//读取P2并提取有用信息
    	changed = (status_switch != status_switch_pre);			//判断是否改变 
    }  
    
    /*****关闭定时器0***********************/
    void close_int()
    {
        TR0 = 0;//关闭Timer0
        ET0 = 0;//关闭T0中断
        LED = 0xFF;//PWM输出高电平
    }
    
    /*************PWM的初始化******/
    void init_pwm()
    {
    	buffer = 0x00;		//清空缓存区
    
    	duty_cycle = 0;		//归零占空比
    }
    
    /*****************定时器0************************/
    void timer0_init(void)		//100微秒@11.0592MHz
    {
    	AUXR &= 0x7F;		//定时器时钟12T模式
    	TMOD &= 0xF0;		//设置定时器模式
    	TMOD |= 0x02;		//设置定时器模式
    	TL0 = 0xA4;		//设置定时初值
    	TH0 = 0xA4;		//设置定时重载值
    	TF0 = 0;		//清除TF0标志
    	TR0 = 1;		//定时器0开始计时
    
    	ET0=1;			//开启T0中断
    	EA=1;			//开总中断
    }
    
    /*************定时中断1处理程序****************/
    void timer0_int(void) interrupt 1	
    {
    	
    	switch (status_switch) {
    	case 0x08:
    /**********单个灯光强度在时间维度上呈三角形波*********/
    		buffer = 0x00;
    		buffer |= (counter_PWM < duty_cycle) << 0;
    		break;	 
    	case 0x09:
    /*****两半灯光强度在空间维度上呈互补三角形波**************************/
    		if (counter_PWM < duty_cycle)
    			buffer = 0xF0;
    		else
    			buffer = 0x0F;
    		break;
    	case 0x0A:
    /*****交叉灯的灯光强度在空间维度上呈互补三角形波**************************/
    		if (counter_PWM < duty_cycle)
    			buffer = 0x55;
    		else
    			buffer = 0xAA;
    		break;
    	case 0x0B:
    /*****全部灯光强度在时间维度上呈三角形波***************/
    		if (counter_PWM < duty_cycle)
    			buffer = 0xFF;
    		else
    			buffer = 0x00; 
    		break;
    
    	case 0x0C:
    /***************灯光强度在空间维度上呈中凸三角形波************/
     		if (counter_PWM < 5)				//原谅我不是完美的三角形波
    			buffer = 0xFF;
    		else if (counter_PWM < 20)
    			buffer = 0x7E;
    		else if (counter_PWM <45)
    			buffer = 0x3C;
    		else
    			buffer = 0x18;
    		break;
    	case 0x0D:
    /********灯光强度在空间维度上呈中凹三角形波******************/
     		if (counter_PWM < 5)
    			buffer = _crol_(0xFF, 4);
    		else if (counter_PWM < 20)
    			buffer = _crol_(0x7E, 4);
    		else if (counter_PWM <45)
    			buffer = _crol_(0x3C, 4);
    		else
    			buffer = _crol_(0x18, 4);
    		break;			
    	}
    		
    	LED = ~buffer;					//引脚的1代表灯灭,所以反转一下
    
    	if (counter_PWM >= length_PWM)	
    		counter_PWM = 0;			//将counter_PWM限制在0到length_PWM之间
    	counter_PWM++;
    }
    

    程序之理想版

    #include <STC89C5xRC.H>
    #include<intrins.h>
    #include<math.h>
    
    /*************全局常量***********/
    #define uchar unsigned char 
    #define uint unsigned int
    #define LED P1
    #define PI 3.1415926
    
    uchar i, j;
    float f;
    
    /*****************全局变量**********************************/
    uchar changed, status_switch = 0x00, status_switch_pre = 0x00;
    uchar counter_PWM = 0, length_PWM = 100, buffer;
    uchar duty_cycles[8];
    
    /*******************部分流水灯模式所需信息**************/
    uchar code table1[]={0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfc,0xff};
    		//0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f	左移
    uchar code table2[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf}; 
    uchar code table3[]={0x7e,0xbd,0xdb,0xe7,0xff};
    uchar code table4[]={0xaa,0x55};
    
    /*********函数声明********************/
    void delay1ms();
    void delay(uint x);
    void keyscan();
    void close_int();
    void init_pwm();
    void timer0_init(void);
    
    
    
    
    
    /********主函数*************/
    void main()
    {
    	while(1) {
    		keyscan(); 
    
    		switch (status_switch) {
    		case 0x00:
    			LED = 0xFF;
    			break;
    		case 0x01:
    			for (i=0;i<16;i++) { 
    				LED=table1[i];     
    				delay(200);
    				keyscan();     
    				if (changed)
    					break;   
    			}   
    			break; 
    		case 0x02:
    			for(i=0;i<14;i++) { 
    				LED=table2[i];     
    				delay(300);
    				keyscan();     
    				if (changed)
    					break;   
    			}
    			break;			
    		case 0x03:
    			for(i=0;i<5;i++) {
    				LED=table3[i];     
    				delay(250);
    				keyscan();     
    				if (changed)
    					break;   
    			}
    			break; 			
    		case 0x04:
    			for(i=0;i<2;i++){
    				LED=table4[i];     
    				delay(300);
    				keyscan();     
    				if (changed)
    					break;      
    			}
    			break; 			
    		case 0x05:
    			for (i=0;i<16;i++) { 
    				LED=~table1[i];     
    				delay(200);
    				keyscan();     
    				if (changed)
    					break;   
    			}   
    			break; 
    			
    		case 0x06:
    			for(i=0;i<14;i++) { 
    				LED=~table2[i];     
    				delay(300);
    				keyscan();     
    				if (changed)
    					break;   
    			}
    			break;
    		 
    		case 0x07:
    			for(i=0;i<5;i++) {
    				LED=~table3[i];     
    				delay(250);
    				keyscan();     
    				if (changed)
    					break;   
    			}
    			break; 
    			 
    		case 0x08:
    /**********灯光强度在时间维度上呈三角形波*********/			
    			timer0_init();
    			while (1) {
    				init_pwm();
    												
            		for (i = 100; i > 0; i--) {
                		duty_cycles[j] = i;
    					buffer |= ((counter_PWM < duty_cycles[j]) << j);   //j代表第几盏灯,第一盏灯时j=0,因为没有指明j,所以每次都有不同的灯作为呼吸灯亮      		
             			delay(50);
    					keyscan();
    					if (changed) {			 //在此插入changed的判断语句是为了更好的对开关变化做出响应
    						close_int();
    						break;
    					}
    				}
    				for (i = 0; i < 100; i++) {
                		duty_cycles[j] = i;
    					buffer |= ((counter_PWM < duty_cycles[j]) << j);   //j代表第几盏灯,第一盏灯时j=0;      		
    					delay(50);
    					keyscan();
    					if (changed) {
    						close_int();
    						break;
    					}
    				}
    			}
    			break; 		 
    		case 0x09:
    /***************灯光强度在空间维度上呈三角形波************/
    			timer0_init();
    			for (j = 0; j < 4; j++)
    				duty_cycles[j] = 25 * j;
    			for (j = 4; j < 8; j++)
    				duty_cycles[j] = 25 * (8 - j);
    			 
    			while (1) {
    				init_pwm();				
    				for (j = 0; j < 8; j++) {
    					buffer |= ((counter_PWM < duty_cycles[j]) << j);         		
    				}
    // 					if (counter_PWM < 25)
    //						buffer = 0xFF;
    //					else if (counter_PWM < 50)
    //						buffer = 0x7E;
    //					else if (counter_PWM < 75)
    //						buffer = 0x3C;
    //					else
    //						buffer = 0x18;
    				delay(100);
            		
    				keyscan();
    				if (changed) {
    					close_int();
    					break;
    				}		
    			}
    			break;			
    		case 0x0A:
    /********灯光强度在时间、空间维度上呈三角形波******************/
    			timer0_init();
    			while (1) {
    				init_pwm();
    				for (i = 0; i < 100; i++) {				       		
    					for (j = 0; j < 4; j++)
    						duty_cycles[j] = (25 * j + i) % 100;
    					for (j = 4; j < 8; j++)
    						duty_cycles[j] = (25 * (8 - j) + i) % 100;	
    					for (j = 0; j < 8; j++)
    						buffer |= ((counter_PWM < duty_cycles[j]) << j);         			
             			delay(50);
    
    					keyscan();
    					if (changed) {
    						close_int();
    						break;
    					}
    				}
    				for (i = 100; i > 0; i--) {				       		
    					for (j = 0; j < 4; j++)
    						duty_cycles[j] = (25 * j + i) % 100;
    					for (j = 4; j < 8; j++)
    						duty_cycles[j] = (25 * (8 - j) + i) % 100;	
    					for (j = 0; j < 8; j++)
    						buffer |= ((counter_PWM < duty_cycles[j]) << j);  
              			delay(50);
    
    					keyscan();
    					if (changed) {
    						close_int();
    						break;
    					}
    				}
    			}
    			break; 
    		case 0x0B:
    /*****灯光强度在时间维度上呈正弦***************/
    			timer0_init();
    			while (1) {
    				init_pwm();	
    								
    				for (i = 0; i < 180; i++) {
    					duty_cycles[j] = (uchar)(sin(PI * i / 180) * 100);	//j号灯为呼吸灯
              			buffer |= ((counter_PWM < duty_cycles[j]) << j); 
    					delay(50);
            		
    					keyscan();
    					if (changed) {
    						close_int();
    						break;
    					}
    				}
    			}
    			break;
    		case 0x0C:
    /*****灯光强度在空间维度上呈正弦波**************************/
    			timer0_init();
    			while (1) {				
    				init_pwm();
    				for (j = 0; j < 8; j++) {
    					duty_cycles[j] = (uchar)(sin(PI * ((int)(i + 22.5 * j) % 180) /180) * 100);
    					buffer |= (counter_PWM < duty_cycles[j]) << j;
              		}
    				delay(100); 
    				   		
    				keyscan();
    				if (changed) {
    					close_int();
    					break;
    				}
    			}
    			break; 
    		case 0x0D:
    /**灯光强度在时间维度上呈三角形波,空间上为相位相差22.5度的数个平行正弦波**/
    			timer0_init();
    			while (1) {
    				init_pwm();				
    				for (i = 0; i < 180; i++) {
    					buffer = 0x00;
    					for (j = 0; j < 8; j++) {
    						duty_cycles[j] = (uchar)(sin(PI * ((int)(i + 22.5 * j) % 180) /180) * 100);
    						buffer |= (counter_PWM < duty_cycles[j]) << j;
              			}
    					delay(10);
            		
    					keyscan();
    					if (changed) {
    						close_int();
    						break;
    					}
    				}
    			}
    			break;
    		case 0x0E:
    /*灯光强度在时间维度上呈正弦波,空间上为强度相差22级的平行正弦波*/
    			timer0_init();
    			while (1) {				
    				for (i = 0; i < 180; i++) {
    					buffer = 0x00;
    					for (j = 0; j < 8; j++) {
    //						duty_cycles[j] = (uchar)((int)(sin(PI * i / 180) * 100 + 22) % 100);
    						duty_cycles[j] = (uchar)(sin(PI * i / 180) * 100 + 22);
    
    						buffer |= (counter_PWM < duty_cycles[j]) << j;
              			}
    					delay(10);
            		
    					keyscan();
    					if (changed) {
    						close_int();
    						break;
    					}
    				}
    			}
    			break;
    		case 0x0F:	
    			LED = 0x00;
    			break;
    		} 
    	}
    }
    
    /*****************延时1ms*************/
    void delay1ms()		//@11.0592MHz
    {
    	unsigned char i, j;
    
    	_nop_();
    	i = 2;
    	j = 199;
    	do
    	{
    		while (--j);
    	} while (--i);
    }   
    
    /**********延时x毫秒***********/
    void delay(uint x)
    {   uchar k;
    	for(k=x; k>0; k--)
    		delay1ms();
    }
    
    /****开关检测。修改开关状态(status_switch)以及更改标志(changed)****/
    void keyscan()  
    { 
    	status_switch_pre = status_switch;
    	P2 = 0xFF;
    	status_switch = (~P2) & 0x0F;	
    	changed = (status_switch != status_switch_pre); 
    }  
    
    /*****关闭定时器0***********************/
    void close_int()
    {
        TR0 = 0;//关闭Timer0
        ET0 = 0;//关闭T0中断
        LED = 0xFF;//PWM输出高电平
    }
    
    /*************PWM的初始化******/
    void init_pwm()
    {
    	uchar k;
    
    	buffer = 0x00;
    	for (k = 0; k < 8; k++)
    		duty_cycles[k] = 0;
    }
    
    /*****************定时器0************************/
    void timer0_init(void)		//100微秒@11.0592MHz
    {
    	AUXR &= 0x7F;		//定时器时钟12T模式
    	TMOD &= 0xF0;		//设置定时器模式
    	TMOD |= 0x02;		//设置定时器模式
    	TL0 = 0xA4;		//设置定时初值
    	TH0 = 0xA4;		//设置定时重载值
    	TF0 = 0;		//清除TF0标志
    	TR0 = 1;		//定时器0开始计时
    
    	ET0=1;			//开启T0中断
    	EA=1;			//开总中断
    }
    
    /*************定时中断1处理程序****************/
    void timer0_int(void) interrupt 1	
    {	
    	LED = ~buffer;					//引脚的1代表灯灭,所以反转一下
    
    	if (counter_PWM >= length_PWM)
    		counter_PWM = 0;			//将counter_PWM限制在0到length_PWM之间
    	counter_PWM++;
    }
    
    展开全文
  • 单片机的仿真实验——流水灯和逐一闪烁灯(输入与输出) 在进行仿真实验前必须先装了软件,一个是单片机仿真软件(ISIS 7 Professional)和单片机写程序的软件(Keil uVision4),一个写程序一个烧程序。如果没装的...
  • 单片机实现按钮控制LED灯流水灯作业和闪烁
  • 1、通过对P1口地址的操作实现流水灯 #include<reg51.h> //包含单片机寄存器的头文件 //要点sfr! sfr x=0xb0; //P1口在存储器中的地址是90H,通过sfr可定义8051内核单片机 //的所有内部8位特殊功能寄存器...
  • 流水灯实验报告

    2020-07-30 23:30:05
    本程序是C语言编写的单片机程序。主要包括定时器的使用,以及流水灯的设置
  • 单片机流水灯

    2016-10-25 23:40:47
     对周六周日的单片机做一部分的总结,周六大自了解了偱迹小车的一部分原理,偱迹小车有二驱和四驱之分,说白了就是有几个轮子是有驱动能力的,四驱的当然比二驱的跑得快,小车前面还有一个万向轮,可以360度旋转,...
  • 流水灯流水灯流水灯流水灯流水灯流水灯流水灯流水灯流水灯流水灯流水灯流水灯流水灯流水灯流水灯流水灯流水灯流水灯流水灯
  • 51单片机 流水灯

    2020-01-03 21:37:10
    ##51单片机 流水灯 上图即为流水灯的模块电路,具体连线如下,强调一下程序段用的是单片机的JP00端口与J12(8个并行排线)相连。初级阶段 模块电路中的74HC245可简单理解为一个通透的驱动电路,输入低电平(高电平...
  • 摘要:利用AT89C51单片机进行流水灯的控制。单片机的P0^0端口到P0^7端口接8个LED灯。LED灯采用共阳接法。
  • 而SW3处于ON状态时,流水灯处于流动状态。导航按键S2被按下后,LED流动方向是从上到下(D9到D2方向);导航按键S3被按下后,LED流动方向是从下到上(D2到D9)。 这里面用到了拨码开关,按键,以及led灯,那么我把...
  • 一、LED闪烁  /***************************************************************** LED闪烁的简单试验 *****************************************************************/ ...
  • 通过外部中断(exti)控制流水灯的简单实验和通过主函数(main)的中断控制流水灯的初步程序的认识、学习【适合初学stm32开发板】
  • void main(void) { while (1) { gLed1 = 0; // 点亮LED Delay(); // 延时一段时间 gLed1 = 1; // 熄灭LED Delay(); // 延时一段时间 } } ... // 0b01111111,左边数第1颗...
  • 常见LED模块一共有八位,如果二极管的负极接VCC,正极接51芯片引脚,则给引脚输入低电平,LED亮。如果二极管负极接GND,则高电平有效。 #include &amp;lt;reg52.h&amp;gt; #include &amp;lt;...
  • stm32流水灯

    2018-03-24 10:50:29
    这篇的博客的任务主要是用来记录如何写一个stm32的程序,这次要写的程序是最基本的流水灯程序。按照课程上讲的来说,要想使用stm32的部件(led灯部件)需要经过下面三个步骤:1.开启外设时钟,后来我才发现其实是...
  • zigbee,流水灯实验,CC2530。通过实验掌握 CC2530 芯片 GPIO 的配置方法,掌握 Led 驱动电路及开关 Led 的原理 。
  • 若干灯泡有规律依次点亮或依次熄灭称为流水灯,它用在夜间建筑物装饰方面。例如在建筑物的棱角上装上流水灯,可起到变换闪烁、美不胜收的效果。 二、实验环境 Proteus 7.8,Keil5 三、电路图 四、实验步骤 从...
1 2 3 4 5 ... 20
收藏数 497
精华内容 198
关键字:

单片机流水灯总结