【51单片机】心形流水灯

   日期:2020-12-30     浏览:95    评论:0    
核心提示:// 正转1圈 i = 32; a = ~(0x00000001); for(k = 0; k < i; k++) { delay(DELAY_MS / 2); a = _lrol_(a, 1); setLed(a); } // 反转1圈 i = 32; a = ~(0x80000000); for(k = 0; k < i; k++) { delay(DELAY_MS / 2); a = _lror_(a, 1);

记录一下首个独立完成的小项目(虽然没有什么技术含量)

  • 硬件方面:入门级的单片机点灯电路
  • 软件方面:主要利用了c语言的位操作

整个项目的下载链接放在了文章最后

一、成品展示

  1. 正面



  1. 反面



二、元器件清单

  • STC89C52RC(51单片机) x 1
  • 单排弯针(4Pin) x 1
  • IC插座(40Pin) x1
  • LED x 33
  • 电阻(1KΩ) x 34
  • 自锁按键 x 1
  • 电容(33P) x 2
  • 电容(104P) x 1
  • 晶振(12MB) x 1
  • 导线

三、原理图

  1. 首先是51最小系统
  2. LED 的接线方式:阳极接VCC,阴极接IO口


  3. LED 的布局

四、思路

LED 的阳极接正极,阴极接IO口,所以

  • 将对应的IO口置为低电平即可点亮 LED
  • 将对应的IO口置为高电平即可熄灭LED

只需要对一个32位无符号整数 (C51中是unsigned long) 进行操作,最后将它的值分为4组,分别赋值给P0、P1、P2、P3 IO口。

void setLed(u32 res)
{ 
	P2 = (res & 0x000000FF) >> (0*4);
	P0 = (res & 0x0000FF00) >> (2*4);
	P1 = (res & 0x00FF0000) >> (4*4);
	P3 = (res & 0xFF000000) >> (6*4);
}


一定要注意 LED 的连接顺序

五、程序

a. 程序框架



#include <reg52.h>
#include <intrins.h>


#define DELAY_MS 10

typedef unsigned long u32;

void setLed(u32 res);
void delay(u32 ms);

void main()
{ 
	u32 a = ~(0x00000001), b = 0;
	u32 k = 0, i = 0;
	while(1)
	{ 
	// 将特效代码粘贴在这里
	 
	}
}

void setLed(u32 res)
{ 
	P2 = (res & 0x000000FF) >> (0*4);
	P0 = (res & 0x0000FF00) >> (2*4);
	P1 = (res & 0x00FF0000) >> (4*4);
	P3 = (res & 0xFF000000) >> (6*4);
}

void delay(u32 n)
{ 
	u32 i = 0, j = 0;
	for (i = 0; i < n; i++)
    	for (j = 0; j < 123; j++);
}

程序说明:

  1. 宏定义 DELAY_MS 是延迟时间,单位是毫秒,可以通过它控制流水灯的频率
  2. 变量 i 是特效的执行次数,只需改变 i 的值,就能改变对应特效的持续次数和时间
  3. 变量 a 是将要操作的32位整数,改变 a 的初值,可以实现不同的特效

b. 特效代码

// 闪烁
i = 20;
a = 0;
for(k = 0; k < i; k++)
{ 
	delay(DELAY_MS * 2);
	a = ~a;
	setLed(a);
}

// 正转1圈
i = 32;
a = ~(0x00000001);
for(k = 0; k < i; k++)
{ 
	delay(DELAY_MS / 2);
	a = _lrol_(a, 1);
	setLed(a);
}

// 反转1圈
i = 32;
a = ~(0x80000000);
for(k = 0; k < i; k++)
{ 
	delay(DELAY_MS / 2);
	a = _lror_(a, 1);
	setLed(a);
}

// 逐个点亮
i = 32;
a = ~(0x00000001);
for(k = 0; k < i; k++)
{ 
	delay(DELAY_MS);
	a = a >> 1;
	setLed(a);
}

// 逐个灭掉
i = 32;
a = 0;
for(k = 0; k < i; k++)
{ 
	delay(DELAY_MS);
	a = (a + 1) << 1;
	setLed(a);
}

// 只灭一个,正转1圈
i = 32;
a = 0x00000001;
for(k = 0; k < i; k++)
{ 
	delay(DELAY_MS / 2);
	a = _lrol_(a, 1);
	setLed(a);
}

// 只灭一个,反转1圈
i = 32;
a = (0x80000000);
for(k = 0; k < i; k++)
{ 
	delay(DELAY_MS / 2);
	a = _lror_(a, 1);
	setLed(a);
}

// 两边逐个点亮
i = 16;
a = ~(0xFFFF0001);
b = ~(0xFFFF8000);
for(k = 0; k < i; k++)
{ 
	delay(DELAY_MS);
	a = a << 1;
	b = b >> 1;
	setLed((a << 16) | b);
}

// 循环闪烁(只灭8个)
i = 100;
a = (0x11111111);
for(k = 0; k < i; k++)
{ 
	delay(DELAY_MS);
	a = _lrol_(a, 1);
	setLed(a);
}

// 循环闪烁(只亮8个)
i = 100;
a = ~(0x11111111);
for(k = 0; k < i; k++)
{ 
	delay(DELAY_MS);
	a = _lrol_(a, 1);
	setLed(a);
}

特效当然不只这么多,你可以自己思考一下,做出更多有意思的特效

c. 完整的程序



#include <reg52.h>
#include <intrins.h>


#define DELAY_MS 10

typedef unsigned long u32;

void setLed(u32 res);
void delay(u32 ms);

void main()
{ 
	u32 a = ~(0x00000001), b = 0;
	u32 k = 0, i = 320;
	while(1)
	{ 
		// 正转1圈
		i = 32;
		a = ~(0x00000001);
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS / 2);
			a = _lrol_(a, 1);
			setLed(a);
		}
		
		// 反转1圈
		i = 32;
		a = ~(0x80000000);
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS / 2);
			a = _lror_(a, 1);
			setLed(a);
		}
	
		// 逐个点亮
		i = 32;
		a = ~(0x00000001);
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS);
			a = a >> 1;
			setLed(a);
		}
		
		// 逐个灭掉
		i = 32;
		a = 0;
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS);
			a = (a + 1) << 1;
			setLed(a);
		}
		
		// 逐个点亮
		i = 32;
		a = ~(0x00000001);
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS);
			a = a >> 1;
			setLed(a);
		}
		
		// 闪烁几下
		i = 20;
		a = 0;
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS * 2);
			a = ~a;
			setLed(a);
		}
		
		// 只灭一个,正转1圈
		i = 32;
		a = 0x00000001;
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS / 2);
			a = _lrol_(a, 1);
			setLed(a);
		}
		
		// 只灭一个,反转1圈
		i = 32;
		a = (0x80000000);
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS / 2);
			a = _lror_(a, 1);
			setLed(a);
		}
	
		
		// 两边逐个点亮
		i = 16;
		a = ~(0xFFFF0001);
		b = ~(0xFFFF8000);
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS);
			a = a << 1;
			b = b >> 1;
			setLed((a << 16) | b);
		}
		
		// 两边逐个点亮
		i = 16;
		a = ~(0xFFFF0001);
		b = ~(0xFFFF8000);
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS);
			a = a << 1;
			b = b >> 1;
			setLed((a << 16) | b);
		}
		
		
		// 循环闪烁(只灭8个)
		i = 100;
		a = (0x11111111);
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS);
			a = _lrol_(a, 1);
			setLed(a);
		}
		
		// 两边逐个点亮
		i = 16;
		a = ~(0xFFFF0001);
		b = ~(0xFFFF8000);
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS);
			a = a << 1;
			b = b >> 1;
			setLed((a << 16) | b);
		}
		
		// 两边逐个点亮
		i = 16;
		a = ~(0xFFFF0001);
		b = ~(0xFFFF8000);
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS);
			a = a << 1;
			b = b >> 1;
			setLed((a << 16) | b);
		}
		
		// 闪几下
		i = 20;
		a = 0;
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS * 2);
			a = ~a;
			setLed(a);
		}
		
		// 循环闪烁(只亮8个)
		i = 100;
		a = ~(0x11111111);
		for(k = 0; k < i; k++)
		{ 
			delay(DELAY_MS);
			a = _lrol_(a, 1);
			setLed(a);
		}
		 
	}
}

void setLed(u32 res)
{ 
	P2 = (res & 0x000000FF) >> (0*4);
	P0 = (res & 0x0000FF00) >> (2*4);
	P1 = (res & 0x00FF0000) >> (4*4);
	P3 = (res & 0xFF000000) >> (6*4);
}

void delay(u32 n)
{ 
	u32 i = 0, j = 0;
	for (i = 0; i < n; i++)
    	for (j = 0; j < 123; j++);
}

六、扩展

1、还可以利用PWM做出呼吸灯的效果

2、可以使用下面这种彩色的 LED ,效果会更好

七、完整项目下载

点击下载完整项目(基于Keil)




板子焊完了

程序写出来了

就等国家分配对象了

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服