01 蓝桥杯—流水灯

在这里插入代码片从今天起,我可以心无旁骛的准备蓝桥杯了。
首先是对入门阶段的基础知识的复习与巩固,初识单片机的我,先接触到的是流水灯的程序。
我们先看一下51单片机的样板图的一部分:

在这里插入图片描述

从中我们可以看出上面有8个LED灯,总共有8个I/o口与这8个LED灯相连,下面,我们来看一个原理图:

在这里插入图片描述

在这里面,我们可以看出8个LED 灯的位置。那么问题随之而来,我们如何将这些灯点亮呢?这需要用到数电的知识,数电中的电平特性:指的是电路中两点或几点在相同的阻抗下电量的相对比值。不要看理论这么高深,其实你只需要记住一点就可以解决问题了。数电中只有两种电平:高电平和低电平。而高电平是1,低电平是0.我们给灯一个低电平时,它才会亮。下面我会贴一个程序给大家看一下:

//  点亮一个或多个LED灯
#include<stc15f2k60s2.h>//51单片机的头文件

void main()
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;   //初始化程序,必须要写。  
	
	P00=0;P04=0;P07=0;//让第一个,第五个,第八个灯点亮。
	while(1);//这是一个死循环,目的让灯一直亮着
}

我们又会在想能不能让灯闪烁起来,答案是肯定的

  //   LED1闪烁程序
    #include<stc15f2k60s2.h>
    unsigned int i;
    void main()
    {
    	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;   //初始化程序  
    	
    	while(1)//让程序一直循环,就能实现闪烁了
    	{
    		P00=0;
    		for(i=0;i<60000;i++);//这个是让灯延时的for循环,才会有灯的闪烁
    		P00=1;	
    		for(i=0;i<60000;i++);
    	}
    }



我们在来看看简化后的程序,这需要用到单片机和数电的知识。例如:sbit  LED 1=P0^0;首先这是对寄存器中未编量的定义;^这个是异或运算,逻辑关系为:必须相同,否则就没有。这样做的好处是:可以自定义变量,在自己忘了输入口时,而不会出错。例程如下:
#include<stc15f2k60s2.h>
sbit LED1=P0^0;
void main()
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;   //初始化程序 
	
	LED1=0;
	while(1);
}


这一个灯闪烁太没有意思,那能不能多个灯交替闪烁呢?那也是可以的。
//LED1  LED2 交替闪烁程序
#include<stc15f2k60s2.h>
unsigned int i
void main()
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;   //初始化程序    
	
	while(1)
	{
		P00=0;
		for(i=0;i<60000;i++);
		P01=0;P00=1;//程序最关键的部分在这里,需要把第一个灯管了,把第二个灯打开	
		for(i=0;i<60000;i++);
		P01=1;	
	}
}

那既然叫流水灯,它肯定是可以实现8个灯依次流动的。
//流水灯程序
#include<stc15f2k60s2.h>
unsigned int i;
void main()
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;   //初始化程序  以后讲  
	
	while(1)
	{
		P00=0;P01=1;P02=1;P03=1;P04=1;P05=1;P06=1;P07=1;
		for(i=0;i<60000;i++);
		P00=1;P01=0;P02=1;P03=1;P04=1;P05=1;P06=1;P07=1;	
		for(i=0;i<60000;i++);
		P00=1;P01=1;P02=0;P03=1;P04=1;P05=1;P06=1;P07=1;
		for(i=0;i<60000;i++);
		P00=1;P01=1;P02=1;P03=0;P04=1;P05=1;P06=1;P07=1;
		for(i=0;i<60000;i++);
		P00=1;P01=1;P02=1;P03=1;P04=0;P05=1;P06=1;P07=1;
		for(i=0;i<60000;i++);
		P00=1;P01=1;P02=1;P03=1;P04=1;P05=0;P06=1;P07=1;
		for(i=0;i<60000;i++);
		P00=1;P01=1;P02=1;P03=1;P04=1;P05=1;P06=0;P07=1;	
		for(i=0;i<60000;i++);	
		P00=1;P01=1;P02=1;P03=1;P04=1;P05=1;P06=1;P07=0;	
		for(i=0;i<60000;i++);			
	}
}

这样写这个程序有些笨拙,我们又要用到数电中的知识,将程序进行简化。在这里我们需要着重掌握二进制与十六进制之间的转换关系。我们看对应的表就能一目了然。
    

我们可以根据这个图,写程序了。不过我们还需要知道一点,根据原理图,我们知道P0口控制整个LED灯,所以就只用对P0进行赋值就可以了。
我们想打开第一个灯怎么写,按照我刚才的思路:P0=0xFE;这样就打开了第一个灯了。那么后面的这是什么意思呢?F:1111  E:1110 ,这个逻辑顺序为从后往前依次是:P00到P07,P00赋值为0,所以只有一个P00灯被点亮。剩下的依次类推,程序如下:
//流水灯的简洁写法
#include<stc15f2k60s2.h>
unsigned int i;
void main()
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;   //初始化程序  以后讲  
	
	while(1)
	{
		P0=0XFE;
		for(i=0;i<60000;i++);
		P0=0XFD;//1111 1101        
		for(i=0;i<60000;i++);
		P0=0XFB;
		for(i=0;i<60000;i++);
		P0=0XF7;
		for(i=0;i<60000;i++);
P0=0XEF;        	//从这里往后有一个小窍门,剩下的四个灯只需要依照前四段,将后两位颠倒一下即可
		for(i=0;i<60000;i++);
		P0=0XDF;
		for(i=0;i<60000;i++);
		P0=0XBF;
		for(i=0;i<60000;i++);	
		P0=0X7F;
		for(i=0;i<60000;i++);			
	}
}

我们还可以讲这个程序在进行简化,只不过这次是将延时的写成一个函数。

例程如下:

//写入延时函数
#include<stc15f2k60s2.h>
void delayms(int ms);
void main()
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;   //初始化程序  以后讲  
	
	while(1)
	{
		P0=0XFE;
		delayms(1000);
		P0=0XFD;//1111 1101        
		delayms(1000);
		P0=0XFB;
		delayms(1000);
		P0=0XF7;
		delayms(1000);
		P0=0XEF;
		delayms(1000);
		P0=0XDF;
		delayms(1000);
		P0=0XBF;
		delayms(1000);
		P0=0X7F;
		delayms(1000);		
	}
}

void delayms(int ms)//这个函数为固定写法,不理解也没有关系
{
	int i,j;
	for(i=0;i<ms;i++)
		for(j=845;j>0;j--);
}

接下来我们看看有点技术含量的,事实上这个程序还可以简化,这里需要用到数电的知识。~这个是取反符,作用是将二进制数按位取反;<<这个是左移符,作用是依次向左加1。我们先看核心程序:P0=~(1<<num);逻辑顺序为:先向左加一,然后按位取反。举个栗子:原来是0000 0000,左移后为0000 0001,再进行取反为1111 1110,就能让第一个灯亮 了。例程如下:

//流水灯最简板的程序
#include<stc15f2k60s2.h>
void delayms(int ms);
unsigned char num;
void main()
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;   //初始化程序  
	while(1)
	{
		for(num=0;num<8;num++)
		{
			P0=~(1<<num);//0000 0001 --1111 1110>   0000 0001 -- 0000 0010 --- 1111 1101 逐次向左移动1位
			delayms(1000);
		}
	}
}

void delayms(int ms)
{
	int i,j;
	for(i=0;i<ms;i++)
		for(j=845;j>0;j--);
}
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值