记录一下首个独立完成的小项目(虽然没有什么技术含量)
- 硬件方面:入门级的单片机点灯电路
- 软件方面:主要利用了c语言的位操作
整个项目的下载链接放在了文章最后
一、成品展示
- 正面
- 反面
二、元器件清单
STC89C52RC(51单片机)
x 1单排弯针(4Pin)
x 1IC插座(40Pin)
x1LED
x 33电阻(1KΩ)
x 34自锁按键
x 1电容(33P)
x 2电容(104P)
x 1晶振(12MB)
x 1导线
三、原理图
- 首先是
51最小系统
- LED 的接线方式:阳极接
VCC
,阴极接IO口
- 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++);
}
程序说明:
- 宏定义
DELAY_MS
是延迟时间,单位是毫秒,可以通过它控制流水灯的频率- 变量
i
是特效的执行次数,只需改变i
的值,就能改变对应特效的持续次数和时间- 变量
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)
板子焊完了
程序写出来了
就等国家分配对象了