【造物笔记】基于51单片机的心形流水灯

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

  • 硬件方面:入门级的单片机点灯电路
  • 软件方面:主要利用了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. 程序框架

/**
 * Author:BY @ DLU Intelligent Control
 * Time: 2020-12-13
 * Version: 1.0
 */

#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. 完整的程序

/**
 * Author:BY @ DLU Intelligent Control
 * Time: 2020-12-13
 * Version: 1.0
 */

#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)





板子焊完了

程序写出来了

就等国家分配对象了

  • 64
    点赞
  • 429
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值