C51-流水灯实验程序

C51-流水灯实验程序

注意:请结合前面已发布文章一起阅读,因为前面已经提及到的不再重复讲述。

1 项目需求

基于STC89C52单片机,使用多种方式完成流水灯实验;并扩展实现了对参与流水灯队列的led灯数量的控制。

2 LED硬件原理图分析

开发板的LED正极都是通过串联电阻与VCC相连接,负极均连接在单片机的P1寄存器上。

以LED0为例,LED0(即发光二极管D1)的负极连接在与单片机的P1.0口;正极通过串联电阻与VCC相连接;所以,当单片机的P1.0口输出低电平时,二极管D1就会导通,点亮LED0,当P1.0口输出高电平,LED0熄灭。
在这里插入图片描述

3 项目实施

3.1 项目分析

假如从D1-D8分别称为led0-led7,实现流水灯的效果就是led0亮一段时间再熄灭,然后led1亮一段时间再熄灭,。。。,led7亮一段时间再熄灭,然后循环到led0亮一段时间再熄灭。

即:led0亮->延时->led0灭且led1亮->延时->led1灭且led2亮->延时->…->延时->led6灭且led7亮->延时->led7灭且led0亮。

其中,LED的亮灭控制在上一期中已经实现了;所以还需要实现延时和流水灯策略。

对于延时分为软件延时和硬件延时:

  • 硬件延时是通过定时器来实现,较为精确,但是需要占用更多硬件资源。
  • 软件延时主要采用循环体进行延时,想要做到精确延时可借助示波器确定延时时间。

该实验中通过软件延时来实现延时功能,经典延时函数如下:内循环执行112次为1ms(通过示波器波形可以确定,每个板子存在差异),外循环通过给入时间来实现对定时时间的控制,精度为1ms;

/* ms延时函数-软件延时 */
void delay_soft_ms(unsigned int ms_time)
{
	unsigned int i = 0, j = 0;
	for(i = ms_time; i > 0; i--)
	{
		for(j = 112; j > 0; j--);
	}
}

3.2 代码编写

以下通过4种方式实现了流水灯效果,且方式2中的3种子方法可控制参与流水灯队列的led灯个数。

/************************************
功能:多种方法实现LED流水灯

作者:eCoderY  时间:2024.01.15
************************************/

#include <reg52.h>

#define SWITCH_CODER (2) /* 选择方法 */
#define SUB_SWITCH_CODER (3) /* 选择方式2中的子方法 */

#define LED P1 /* 定义LED为P1寄存器 */

#define ON_LED(led, x) do{led &= ~(1 << x);}while(0);
#define OFF_LED(led, x) do{led |= (1 << x);}while(0);


/* 函数声明 */
void delay_soft_ms(unsigned int ms_time);
void led_method1(unsigned int ms_time);
void led_method2(unsigned int ms_time, unsigned char ledNum);


void main(void)
{	
	while(1)
	{
		/* 方式1:依次对每个led进行点亮、延时、关闭操作 */
	#if(SWITCH_CODER == 1)
		led_method1(100);
	#endif
		
		/* 方式2:又可分为3种子方法 */
	#if(SWITCH_CODER == 2)
		led_method2(200, 6);
	#endif
				
	}
}


/* ms延时函数-软件延时 */
void delay_soft_ms(unsigned int ms_time)
{
	unsigned int i = 0, j = 0;
	for(i = ms_time; i > 0; i--)
	{
		for(j = 112; j > 0; j--);
	}
}

/* 方式1:依次对每个led进行点亮、延时、关闭操作 */
void led_method1(unsigned int ms_time)
{
	while(1)
	{
		/* LED0 */
		ON_LED(LED, 0)
		delay_soft_ms(ms_time);
		OFF_LED(LED, 0)
		
		/* LED1 */
		ON_LED(LED, 1)
		delay_soft_ms(ms_time);
		OFF_LED(LED, 1)
		
		/* LED2 */
		ON_LED(LED, 2)
		delay_soft_ms(ms_time);
		OFF_LED(LED, 2)
		
		/* LED3 */
		ON_LED(LED, 3)
		delay_soft_ms(ms_time);
		OFF_LED(LED, 3)
		
		/* LED4 */
		ON_LED(LED, 4)
		delay_soft_ms(ms_time);
		OFF_LED(LED, 4)
		
		/* LED5 */
		ON_LED(LED, 5)
		delay_soft_ms(ms_time);
		OFF_LED(LED, 5)
		
		/* LED6 */
		ON_LED(LED, 6)
		delay_soft_ms(ms_time);
		OFF_LED(LED, 6)
		
		/* LED7 */
		ON_LED(LED, 7)
		delay_soft_ms(ms_time);
		OFF_LED(LED, 7)
	}
}

/* 方式2:优化方式1,且可控制使用led灯的数量1~8个 */
void led_method2(unsigned int ms_time, unsigned char ledNum)
{
	unsigned char num = 0;
	
	/* 检查led灯数量是否合法 */
	if(ledNum < 1 || ledNum > 8)
	{
		/* 非法数量输入,灯全亮闪烁标识出错警告 */
		while(1)
		{
			LED = 0x0;
			delay_soft_ms(ms_time);
			LED = 0xff;
			delay_soft_ms(ms_time);
		}
	}
	
	/* 流水灯实现 */
	while(1)
	{
	#if(SUB_SWITCH_CODER == 2)
		LED = 0xfe;
	#endif
		for(num = 0; num < ledNum; num++)
		{
			/* 方式2.1:优化方式1 */
		#if(SUB_SWITCH_CODER == 1)
			ON_LED(LED, num)
			delay_soft_ms(ms_time);
			OFF_LED(LED, num)
		#endif
			
			/* 方式2.2:通过移位实现流水灯 */
		#if(SUB_SWITCH_CODER == 2)
			delay_soft_ms(ms_time);
			LED <<= 1; /* 1111 1110 << 1 = 1111 1100 */
			LED |= 0x01; /* 灭掉led0,右侧补位添的0 */
		#endif
			
			/* 方式2.3:普通位操作 */
		#if(SUB_SWITCH_CODER == 3)
			LED &= ~(1 << num); /* 亮灯 */
			delay_soft_ms(ms_time);
			LED |= (1 << num); /* 灭灯 */
		#endif
		}
	}
}

3.3 实验现象

通过更改SWITCH_CODER(1, 2)和SUB_SWITCH_CODER(1, 2, 3)的值,选择4种方式,然后编译烧录,均能达到流水灯效果,且SWITCH_CODER == 2时,3种方式均可实现对参与流水灯队列的led灯数量的控制。

EOF

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值