51单片机实现流水呼吸灯

写在前面

  这篇博客介绍下用定时器来产生占空比不同的方波,完成了呼吸灯的效果,同时可以实现多个led灯同时呼吸形成类似流水的效果。
  主要用到定时器0来形成一个1ms的中断,每次进入中断服务程序会让小灯当前处于的周期加1,用这个周期与设定的亮x个周期对比,这样就可以让小灯占空比改变,让这个x改变就可以让小灯形成呼吸效果。
  MCU:STC12C5A60S2 平台:普中HC6800-ES V2.0
  所有代码如下:

/**************************************************************************************
*		             		 流动呼吸灯												  *
实现现象:上电之后,每个LED小灯都在以不同的占空比在呼吸,每个小灯的占空比差是10%
		  
注意事项:																				  
***************************************************************************************/
#include <reg52.h>

typedef unsigned char uint8;
typedef	unsigned int uint16;
//************************************************端口声明
sbit led1 = P2^0;
sbit led2 = P2^1;
sbit led3 = P2^2;
sbit led4 = P2^3;
sbit led5 = P2^4;
sbit led6 = P2^5;
sbit led7 = P2^6;
sbit led8 = P2^7;
//************************************************变量
uint8 all_round,change_time;
uint8 duty=1,duty1=2,duty2=3,duty3=4,duty4=5,duty5=6,duty6=7,duty7=8;
bit flag,flag1,flag2,flag3,flag4,flag5,flag6,flag7;

//************************************************初始化中断、中断服务函数
void timer0_init(){
	EA = 0;										//关闭总中断
	TR0 = 0;									//关闭定时器
	TMOD = 0X01;						
	TH0 = 0XFC;									//1MS中断一次
	TL0 = 0X67;						
							
	ET0 = 1;									//允许定时器0中断
	EA = 1;										//开总中断
	TR0 = 1;									//开定时器
}

void isr_timer0 () interrupt 1 using 0{
	TMOD = 0X01;
	TH0 = 0XFC;									//1MS中断一次
	if(++all_round > 10){					
		all_round = 0;							//LED当前的周期,1MS自增1,到10清零,共10个周期
	}
	if(++change_time > 80){						//80MS改变一次占空比
		change_time = 0;
		if(!flag) {								//flag=0 从暗变亮
			if(++duty > 10) {					//duty每10个周期改变flag的值
				flag = 1;
			}
		}
		else{
			if(--duty < 2){						//flag=1 从亮变暗
				flag = 0;						//duty如果等与0,小灯会灭,即0%占空比,所以这里让duty=1时就改变方向
			}
		}
//******************************************************************//		
		if(!flag1) {							//同flag
			if(++duty1 > 10) {
				flag1 = 1;
			}
		}
		else{
			if(--duty1 < 2){
				flag1 = 0;
			}
		}
//******************************************************************//
		if(!flag2) {
			if(++duty2 > 10) {
				flag2 = 1;
			}
		}
		else{
			if(--duty2 < 2){
				flag2 = 0;
			}
		}
//******************************************************************//		
		if(!flag3) {
			if(++duty3 > 10) {
				flag3 = 1;
			}
		}
		else{
			if(--duty3 < 2){
				flag3 = 0;
			}
		}
//******************************************************************//		
		if(!flag4) {
			if(++duty4 > 10) {
				flag4 = 1;
			}
		}
		else{
			if(--duty4 < 2){
				flag4 = 0;
			}
		}
//******************************************************************//		
		if(!flag5) {
			if(++duty5 > 10) {
				flag5 = 1;
			}
		}
		else{
			if(--duty5 < 2){
				flag5 = 0;
			}
		}
//******************************************************************//		
		if(!flag6) {
			if(++duty6 > 10) {
				flag6 = 1;
			}
		}
		else{
			if(--duty6 < 2){
				flag6 = 0;
			}
		}
//******************************************************************//		
		if(!flag7) {
			if(++duty7 > 10) {
				flag7 = 1;
			}
		}
		else{
			if(--duty7 < 2){
				flag7 = 0;
			}
		}
	}
}
/*******************************************************************************
* 函数名         : display()
* 函数功能		 : 
* 输入           : 无
* 输出         	 : 无
* 备注           : 
*******************************************************************************/
void display(){
	if(all_round < duty){				//让当前周期与设定的占空比比较
		led1 = 0;						//当前周期小于设定的占空比就让小灯亮
	}
	else{
		led1 = 1;
	}
//******************************************************************//	
	if(all_round < duty1){				//同led1,但是duty1比duty多1
		led2 = 0;						//
		
	}
	else{
		led2 = 1;
	}
//******************************************************************//	
	if(all_round < duty2){
		led3 = 0;
	}
	else{
		led3 = 1;
	}
//******************************************************************//	
	if(all_round < duty3){
		led4 = 0;
	}
	else{
		led4 = 1;
	}
//******************************************************************//	
	if(all_round < duty4){
		led5 = 0;
	}
	else{
		led5 = 1;
	}
//******************************************************************//	
	if(all_round < duty5){
		led6 = 0;
	}
	else{
		led6 = 1;
	}
//******************************************************************//	
	if(all_round < duty6){
		led7 = 0;
	}
	else{
		led7 = 1;
	}
//******************************************************************//	
	if(all_round < duty7){
		led8 = 0;
	}
	else{
		led8 = 1;
	}	
}

void main(){
	timer0_init();
	while(1){
		display();
	}
}

  all_round代表当前处于的周期,duty代表设定的占空比高电平的值。初始状态duty-duty7分别是1-8,all_round每1ms加1,则初始时led1会亮1ms,灭9ms,占空比就是10%。保持60ms相同的占空比运行之后,duty会加1,led1的占空比就会变成20%。以此类推,当duty增加到10的时候,led1的占空比就变为了100%。然后duty会开始递减,灯的占空比也相应递减,当duty减到1的时候又会重新把flag清零进入递增的程序。
  其他led的情况跟led1类似,只不过初始给这些led赋的初始占空比都相邻递增,所以当中断开起来之后,duty-duty7是同步递增的,这些灯的相邻占空比也一直保持10%的差距,形成了流水的效果。

  • 25
    点赞
  • 125
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值