效果图:

C51 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//STC12C5A60S2  @12M晶振
#include <STC12C5A60S2.H>
#include <intrins.h>

sbit R1 = P0 ^ 0;
sbit G1 = P0 ^ 1;
sbit B1 = P0 ^ 2;
sbit R2 = P0 ^ 3;
sbit G2 = P0 ^ 4;
sbit B2 = P0 ^ 5;

sbit IA = P2 ^ 7; //行控制线A
sbit IB = P2 ^ 6; //行控制线B
sbit IC = P2 ^ 5; //行控制线C
sbit ID = P2 ^ 4; //行控制线D

sbit CK = P2 ^ 2; //时钟
sbit LS = P2 ^ 1; //锁存
sbit OE = P2 ^ 0; //输出,低电平有效

#define SCAN(X) IA=(X)&1; IB=(X)&2; IC=(X)&4; ID=(X)&8;

unsigned short ms = 0;
unsigned short sec = 0;

void Delay100us() //@12.000MHz
{
unsigned char i, j;

_nop_();
_nop_();
i = 2;
j = 38;
do
{
while (--j);
} while (--i);
}

void SendRGB(int s)
{
unsigned int i;
unsigned int j;
unsigned int color;

//手上的屏 译码器是 ICN74HC138 为 LED 显示屏行选专用译码电路,不能应用于静态译码电路,
//译码器的输入 A0 必须为动态信号,并且在 50ms 内必须有 0→1 的状态出现,
//否则内部译码电路处于关闭状态,并关闭所有输出 Pin.
for(i = 0; i < 16; i++) //扫描行数
{
SCAN(i); //选择行

// 写入缓存
color = s % 7 + 1;
for(j = 0; j <= s % 64; j++) // [0 ~ 63] 右闭区间等于64
{
R1 = color & 1;
G1 = color & 2;
B1 = color & 4;

R2 = G1;
G2 = B1;
B2 = R1;

CK=1;
CK=0;
}

// 清除缓存
for(; j < 64; j++) // [0 ~ 64) 右开区间等于64
{
R1=G1=B1=R2=G2=B2=0;
CK=1;
CK=0;
}

//锁存
LS=1;
LS=0;

//显示开
OE=0;
Delay100us();
OE=1;
}
}

void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初始值
TH0 = 0xD1; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时

ET0 = 1; //定时器0中断允许
EA = 1; //开启全局中断
}

int main()
{
Timer0Init();

while(1)
{
SendRGB(sec);
}
}
void timer0 (void) interrupt 1
{
ms++;
if(ms >=1000)
{
sec++;
ms = 0;
}
}