[51单片机学习笔记FOUR]----16*16LED点阵

一、LED点阵发光原理

8*8单色单片机结构图如下:

从电路图中很简单的就可以看出来,想要点亮点阵中的某一个LED灯。只要使得那个灯所在的行输出高电平,所在列输出低电平就好。

二、点阵扫描实验

  1 /***********************************************
  2 实验名称:      点阵扫描
  3 实验说明:      扫描每个LED灯,检查点阵是否完好
  4 实验时间:      2014/12/24
  5 ***********************************************/
  6 #include <reg51.h>
  7 #include <intrins.h>
  8
  9 #define uchar unsigned char
 10 #define uint  unsigned int
 11
 12 sbit MOSIO = P3^4;//输入口
 13 sbit R_CLK = P3^5;//锁存器时钟
 14 sbit S_CLK = P3^6;//移位寄存器时钟
 15
 16 //data3:右边半块列数据;data2:左边半块列数据
 17 //data1:下边半块行数据;data0:上边半块行数据
 18 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0);
 19
 20 void main()
 21 {
 22     uint i,j;
 23     uchar d;
 24
 25     while(1)
 26     {
 27         //全亮
 28         HC595Pro(0x00,0x00,0xFF,0xFF);
 29         for(i=0;i<40000;i++);          //延时40ms
 30
 31         /*行扫描*/
 32         //上半块行扫描
 33         d = 0x01;
 34         for(i=0;i<8;i++)
 35         {
 36             HC595Pro(0x00,0x00,0x00,d);
 37             d <<= 1;
 38             for(j=0;j<20000;j++);               //延时20ms
 39         }
 40         //下半块行扫描
 41         d = 0x01;
 42         for(i=0;i<8;i++)
 43         {
 44             HC595Pro(0x00,0x00,d,0x00);
 45             d <<= 1;
 46             for(j=0;j<20000;j++);                 //延时20ms
 47         }
 48
 49         /*列扫描*/
 50         //左半快列扫描
 51         d = 0xFE;
 52         for(i=0;i<8;i++)
 53         {
 54             HC595Pro(0xFF,d,0xFF,0xFF);
 55             //如果还想用跟行扫描一样的形式,看main()最下面注释行
 56             d = _crol_(d,1);                   //循环左移
 57             for(j=0;j<20000;j++);              //延时20ms
 58         }
 59         //右半块列扫描
 60         d = 0xFE;
 61         for(i=0;i<8;i++)
 62         {
 63             HC595Pro(d,0xFF,0xFF,0xFF);
 64             d = _crol_(d,1);
 65             for(j=0;j<20000;j++);               //延时20ms
 66         }
 67         /******************************************************
 68         b1 = 0x01;
 69         for(i = 0; i<8; i++)
 70         {
 71             HC595Pro(0xFF, ~b1, 0xFF, 0xFF);
 72             b1 <<= 1;
 73             for(j=0; j<20000; j++);
 74         }
 75
 76         b1 = 0x01;
 77         for(i = 0; i<8; i++)
 78         {
 79             HC595Pro(~b1, 0xFF, 0xFF, 0xFF);
 80             b1 <<= 1;
 81             for(j=0; j<20000; j++);
 82         }
 83         ******************************************************/
 84     }
 85 }
 86
 87 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0)
 88 {
 89     uchar i;
 90     //先移入的会被后面移入的数据推移到后面的595中,所以需要先移入data3
 91     for(i=0;i<8;i++)
 92     {
 93         //先移入高位再移入低位,移位寄存器移入的第一位就是输出的最高位
 94         MOSIO = data3 >> 7;
 95         data3 <<= 1;
 96         S_CLK = 0;//给一个上升沿,移位
 97         S_CLK = 1;
 98     }
 99     for(i=0;i<8;i++)
100     {
101         MOSIO = data2 >> 7;
102         data2 <<= 1;
103         S_CLK = 0;
104         S_CLK = 1;
105     }
106     for(i=0;i<8;i++)
107     {
108         MOSIO = data1 >> 7;
109         data1 <<= 1;
110         S_CLK = 0;
111         S_CLK = 1;
112     }
113     for(i=0;i<8;i++)
114     {
115         MOSIO = data0 >> 7;
116         data0 <<= 1;
117         S_CLK = 0;
118         S_CLK = 1;
119     }
120
121     //上升沿时将移位寄存器数据移到锁存器中用于显示,平时保持低电平,数据不变
122     R_CLK = 0;
123     R_CLK = 1;
124     R_CLK = 0;
125
126 }

这里我用到的是16*16的点阵。其实也就是4个8*8的小点阵组成起来的。其结构图如下:

1 2
3 4

这里只是简单示意一下。。。其中4个小块都是与一个相对应的74HC595相连。每个74HC595又是级联的,入口只有一个,我们需要输入相对应的行,列电平情况来控制LED灯的亮灭。

根据74HC595的结构可以知道,输入的数据是8位8位的输入的。最开始输入的8位数据会被后面的输入数据推移到第四个74HC595中。

所以实际输入时,是先输入2和4的列数据,再输入1和3的列数据,然后再是3和4的行数据,最后才是1和2的行数据。

三、16*16点阵倒计时

  1 /***********************************************************************
  2 实验名称:   16*16点阵数字倒计时
  3 实验时间:   2014/12/26
  4 ***********************************************************************/
  5 #include <reg51.h>
  6 #include <array.h>
  7
  8 #define uchar unsigned char
  9 #define uint  unsigned int
 10
 11 sbit MOSIO = P3^4;
 12 sbit R_CLK = P3^5;
 13 sbit S_CLK = P3^6;
 14
 15 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0);
 16
 17 void main()
 18 {
 19     uint i,c;
 20     uchar j;
 21     i = 100;
 22
 23     while(1)
 24     {
 25         //显示数字10
 26         for(c=i;c>0;c--)//延时
 27             for(j=0;j<16;j++)
 28             {
 29                 //字模取出来的数据是跟实际实际所需数据相反的,所以要取反。
 30                 //函数对应的参数分别表示列2,列1,行2,行1
 31                 HC595Pro(~tab1[2*j+1],~tab1[2*j],tab0[2*j],tab0[2*j+1]);
 32             }
 33         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 34
 35         //显示数字09
 36         for(c=i;c>0;c--)
 37             for(j=0;j<16;j++)
 38             {
 39                 HC595Pro(~tab2[2*j+1],~tab2[2*j],tab0[2*j],tab0[2*j+1]);
 40             }
 41         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 42
 43         //显示数字08
 44         for(c=i;c>0;c--)
 45             for(j=0;j<16;j++)
 46             {
 47                 HC595Pro(~tab3[2*j+1],~tab3[2*j],tab0[2*j],tab0[2*j+1]);
 48             }
 49         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 50
 51         //显示数字07
 52         for(c=i;c>0;c--)
 53             for(j=0;j<16;j++)
 54             {
 55                 HC595Pro(~tab4[2*j+1],~tab4[2*j],tab0[2*j],tab0[2*j+1]);
 56             }
 57         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 58
 59         //显示数字06
 60         for(c=i;c>0;c--)
 61             for(j=0;j<16;j++)
 62             {
 63                 HC595Pro(~tab5[2*j+1],~tab5[2*j],tab0[2*j],tab0[2*j+1]);
 64             }
 65         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 66
 67         //显示数字05
 68         for(c=i;c>0;c--)
 69             for(j=0;j<16;j++)
 70             {
 71                 HC595Pro(~tab6[2*j+1],~tab6[2*j],tab0[2*j],tab0[2*j+1]);
 72             }
 73         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 74
 75         //显示数字04
 76         for(c=i;c>0;c--)
 77             for(j=0;j<16;j++)
 78             {
 79                 HC595Pro(~tab7[2*j+1],~tab7[2*j],tab0[2*j],tab0[2*j+1]);
 80             }
 81         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 82
 83         //显示数字03
 84         for(c=i;c>0;c--)
 85             for(j=0;j<16;j++)
 86             {
 87                 HC595Pro(~tab8[2*j+1],~tab8[2*j],tab0[2*j],tab0[2*j+1]);
 88             }
 89         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 90
 91         //显示数字02
 92         for(c=i;c>0;c--)
 93             for(j=0;j<16;j++)
 94             {
 95                 HC595Pro(~tab9[2*j+1],~tab9[2*j],tab0[2*j],tab0[2*j+1]);
 96             }
 97         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 98
 99         //显示数字01
100         for(c=i;c>0;c--)
101             for(j=0;j<16;j++)
102             {
103                 HC595Pro(~tab10[2*j+1],~tab10[2*j],tab0[2*j],tab0[2*j+1]);
104             }
105         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
106
107         //显示数字00
108         for(c=i;c>0;c--)
109             for(j=0;j<16;j++)
110             {
111                 HC595Pro(~tab11[2*j+1],~tab11[2*j],tab0[2*j],tab0[2*j+1]);
112             }
113         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
114
115         //显示字母GO
116         for(c=i;c>0;c--)
117             for(j=0;j<16;j++)
118             {
119                 HC595Pro(~tab12[2*j+1],~tab12[2*j],tab0[2*j],tab0[2*j+1]);
120             }
121         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
122     }
123 }
124
125 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0)
126 {
127     uchar i;
128     //先移入的会被后面移入的数据推移到后面的595中,所以需要先移入data3
129     for(i=0;i<8;i++)
130     {
131         //先移入高位再移入低位,移位寄存器移入的第一位就是输出的最高位
132         MOSIO = data3 >> 7;
133         data3 <<= 1;
134         S_CLK = 0;//给一个上升沿,移位
135         S_CLK = 1;
136     }
137     for(i=0;i<8;i++)
138     {
139         MOSIO = data2 >> 7;
140         data2 <<= 1;
141         S_CLK = 0;
142         S_CLK = 1;
143     }
144     for(i=0;i<8;i++)
145     {
146         MOSIO = data1 >> 7;
147         data1 <<= 1;
148         S_CLK = 0;
149         S_CLK = 1;
150     }
151     for(i=0;i<8;i++)
152     {
153         MOSIO = data0 >> 7;
154         data0 <<= 1;
155         S_CLK = 0;
156         S_CLK = 1;
157     }
158
159     //上升沿时将移位寄存器数据移到锁存器中用于显示,平时保持低电平,数据不变
160     R_CLK = 0;
161     R_CLK = 1;
162     R_CLK = 0;
163 }

array.h头文件如下:

 1 //点阵显示数组
 2 //用于行扫描
 3 unsigned char code tab0[] = {0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80,
 4                              0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00};
 5 //1数字10的字模
 6 unsigned char code tab1[] = {0, 0, 0, 0, 0, 0, 8, 24, 14, 36, 8, 66, 8, 66, 8, 66,
 7                               8, 66, 8, 66, 8, 66, 8, 36, 62, 24, 0, 0, 0, 0, 0, 0};
 8 //数字09的字模
 9 unsigned char code tab2[] = {0, 0, 0, 0, 0, 0, 24, 24, 36, 36, 66, 66, 66, 66, 66,
10                              66, 66, 100, 66, 88, 66, 64, 66, 64, 36, 36, 24, 28, 0, 0, 0, 0} ;
11 //数字08的字模
12 unsigned char code tab3[] = {0, 0, 0, 0, 0, 0, 24, 60, 36, 66, 66, 66, 66, 66, 66, 36,
13                              66, 24, 66, 36, 66, 66, 66, 66, 36, 66, 24, 60, 0, 0, 0, 0};
14 //数字07的字模
15 unsigned char code tab4[] = {0, 0, 0, 0, 0, 0, 24, 126, 36, 34, 66, 34, 66, 16, 66, 16,
16                              66, 8, 66, 8, 66, 8, 66, 8, 36, 8, 24, 8, 0, 0, 0, 0};
17 //数字06的字模
18 unsigned char code tab5[] = {0, 0, 0, 0, 0, 0, 24, 56, 36, 36, 66, 2, 66, 2, 66, 26, 66,
19                              38, 66, 66, 66, 66, 66, 66, 36, 36, 24, 24, 0, 0, 0, 0};
20 //数字05的字模
21 unsigned char code tab6[] = {0, 0, 0, 0, 0, 0, 24, 126, 36, 2, 66, 2, 66, 2, 66, 26, 66,
22                              38, 66, 64, 66, 64, 66, 66, 36, 34, 24, 28, 0, 0, 0, 0};
23 //数字04的字模
24 unsigned char code tab7[] = {0, 0, 0, 0, 0, 0, 24, 32, 36, 48, 66, 40, 66, 36, 66, 36, 66,
25                              34, 66, 34, 66, 126, 66, 32, 36, 32, 24, 120, 0, 0, 0, 0};
26 //数字03的字模
27 unsigned char code tab8[] = {0, 0, 0, 0, 0, 0, 24, 60, 36, 66, 66, 66, 66, 32, 66, 24, 66,
28                              32, 66, 64, 66, 64, 66, 66, 36, 34, 24, 28, 0, 0, 0, 0};
29 //数字02的字模
30 unsigned char code tab9[] = {0, 0, 0, 0, 0, 0, 24, 60, 36, 66, 66, 66, 66, 66, 66, 32, 66,
31                              32, 66, 16, 66, 8, 66, 4, 36, 66, 24, 126, 0, 0, 0, 0};
32 //数字01的字模
33 unsigned char code tab10[] = {0, 0, 0, 0, 0, 0, 24, 8, 36, 14, 66, 8, 66, 8, 66, 8, 66, 8, 66,
34                               8, 66, 8, 66, 8, 36, 8, 24, 62, 0, 0, 0, 0};
35 //数字00的字模
36 unsigned char code tab11[] = {0, 0, 0, 0, 0, 0, 24, 24, 36, 36, 66, 66, 66, 66, 66, 66, 66, 66,
37                               66, 66, 66, 66, 66, 66, 36, 36, 24, 24, 0, 0, 0, 0};
38 //数字GO的字模
39 unsigned char code tab12[] = {0, 0, 0, 0, 0, 0, 60, 28, 34, 34, 34, 65, 1, 65, 1, 65, 1, 65, 113,
40                               65, 33, 65, 34, 65, 34, 34, 28, 28, 0, 0, 0, 0};

头文件的数据是通过字模软件得出的。字模软件的工作原理就是对于一个点阵,你想要什么样的图像,然后就在相应位置数据为1。然后再通过从左到右,从上到下的顺序,组成一个个8位数据。

这些8位数据就是头文件的内容。

由此我们就可以知道,通过字模取出来的数据,而我们实际运用过程中对于列来说是相反的。

因为我们想要点亮对应的LED灯是将它所在行输出高电平,所在列输出低电平。所以取出来的字模数据作为列的值的话是相反的。所以这里用了取反。

四、显示汉字

  1 #include <reg51.h>
  2 #include <array.h>
  3
  4 #define uchar unsigned char
  5 #define uint  unsigned int
  6
  7 sbit MOSIO = P3^4;
  8 sbit R_CLK = P3^5;
  9 sbit S_CLK = P3^6;
 10
 11 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0);
 12
 13 void main()
 14 {
 15     uint i,c;
 16     uchar j;
 17     i = 100;
 18
 19     while(1)
 20     {
 21         //显示“我”
 22         for(c=i;c>0;c--)//延时
 23             for(j=0;j<16;j++)
 24             {
 25                 //字模取出来的数据是跟实际实际所需数据相反的,所以要取反。
 26                 //函数对应的参数分别表示列2,列1,行2,行1
 27                 HC595Pro(~tab1[2*j+1],~tab1[2*j],tab0[2*j],tab0[2*j+1]);
 28             }
 29         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 30
 31         //显示“叫”
 32         for(c=i;c>0;c--)
 33             for(j=0;j<16;j++)
 34             {
 35                 HC595Pro(~tab2[2*j+1],~tab2[2*j],tab0[2*j],tab0[2*j+1]);
 36             }
 37         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 38
 39         //显示“做”
 40         for(c=i;c>0;c--)
 41             for(j=0;j<16;j++)
 42             {
 43                 HC595Pro(~tab3[2*j+1],~tab3[2*j],tab0[2*j],tab0[2*j+1]);
 44             }
 45         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 46
 47         //显示“大”
 48         for(c=i;c>0;c--)
 49             for(j=0;j<16;j++)
 50             {
 51                 HC595Pro(~tab4[2*j+1],~tab4[2*j],tab0[2*j],tab0[2*j+1]);
 52             }
 53         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 54
 55         //显示“熙”
 56         for(c=i;c>0;c--)
 57             for(j=0;j<16;j++)
 58             {
 59                 HC595Pro(~tab5[2*j+1],~tab5[2*j],tab0[2*j],tab0[2*j+1]);
 60             }
 61         for(c=i;c>0;c--)
 62             {
 63                 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 64             }
 65
 66         //显示“熙”
 67         for(c=i;c>0;c--)
 68             for(j=0;j<16;j++)
 69             {
 70                 HC595Pro(~tab6[2*j+1],~tab6[2*j],tab0[2*j],tab0[2*j+1]);
 71             }
 72         HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
 73     }
 74 }
 75
 76 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0)
 77 {
 78     uchar i;
 79     //先移入的会被后面移入的数据推移到后面的595中,所以需要先移入data3
 80     for(i=0;i<8;i++)
 81     {
 82         //先移入高位再移入低位,移位寄存器移入的第一位就是输出的最高位
 83         MOSIO = data3 >> 7;
 84         data3 <<= 1;
 85         S_CLK = 0;//给一个上升沿,移位
 86         S_CLK = 1;
 87     }
 88     for(i=0;i<8;i++)
 89     {
 90         MOSIO = data2 >> 7;
 91         data2 <<= 1;
 92         S_CLK = 0;
 93         S_CLK = 1;
 94     }
 95     for(i=0;i<8;i++)
 96     {
 97         MOSIO = data1 >> 7;
 98         data1 <<= 1;
 99         S_CLK = 0;
100         S_CLK = 1;
101     }
102     for(i=0;i<8;i++)
103     {
104         MOSIO = data0 >> 7;
105         data0 <<= 1;
106         S_CLK = 0;
107         S_CLK = 1;
108     }
109
110     //上升沿时将移位寄存器数据移到锁存器中用于显示,平时保持低电平,数据不变
111     R_CLK = 0;
112     R_CLK = 1;
113     R_CLK = 0;
114 }

array.h头文件如下:

 1 //点阵显示数组
 2 //用于行扫描
 3 unsigned char code tab0[] = {0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80,
 4                              0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00};
 5 // 我
 6 unsigned char code tab1[] ={96,2,28,10,16,18,16,2,254,63,16,2,16,18,112,18,24,10,22,10,16,36,16,42,16,49,156,32,0,0,0,0};
 7 // 叫
 8 unsigned char code tab2[] ={0,16,0,16,158,16,146,16,146,16,146,16,146,24,146,22,146,17,158,16,18,16,0,16,0,16,0,16,0,0,0,0};
 9 // 做
10 unsigned char code tab3[] ={80,2,80,2,72,2,232,62,76,17,74,18,232,18,168,18,168,10,168,10,168,4,232,10,40,17,136,32,0,0,0,0};
11 // 大
12 unsigned char code tab4[] ={128,0,128,0,128,0,128,0,254,63,128,0,64,1,64,1,64,1,32,2,32,2,16,4,8,8,6,48,0,0,0,0};
13 // 熙
14 unsigned char code tab5[] ={252,62,36,34,36,34,244,34,148,62,148,2,244,2,36,34,36,34,252,60,0,0,36,17,68,34,66,34,0,0,0,0};
15 // 熙
16 unsigned char code tab6[] ={252,62,36,34,36,34,244,34,148,62,148,2,244,2,36,34,36,34,252,60,0,0,36,17,68,34,66,34,0,0,0,0};

汉字输出显示其实跟数字没什么差别,这里不做累赘讲述了。

五、用指针方式显示汉字

 1 #include <reg51.h>
 2 #include <array.h>
 3
 4 #define uchar unsigned char
 5 #define uint  unsigned int
 6
 7 sbit MOSIO = P3^4;
 8 sbit R_CLK = P3^5;
 9 sbit S_CLK = P3^6;
10
11 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0);
12
13 void main()
14 {
15     uchar *p[] = {tab1, tab2, tab3, tab4, tab5, tab6};
16
17     uint i,j,c,k;
18     i = 100;
19
20     while(1)
21     {
22         //分别显示“我叫做大熙熙”
23         for(k=0;k<6;k++)//一共六个字
24         {
25             for(c=i;c>0;c--)//延时
26             {
27                 for(j=0;j<16;j++)
28                 {
29                     //p[k]+2*j+1就是p[k][2*j+1], p[k]+2*j就是p[k][2*j]
30                     HC595Pro(~(*(p[k]+2*j+1)),~(*(p[k]+2*j)),tab0[2*j],tab0[2*j+1]);
31                 }
32                 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
33             }
34         }
35     }
36 }
37
38 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0)
39 {
40     uchar i;
41     for(i=0;i<8;i++)
42     {
43         MOSIO = data3 >> 7;
44         data3 <<= 1;
45         S_CLK = 0;
46         S_CLK = 1;
47     }
48     for(i=0;i<8;i++)
49     {
50         MOSIO = data2 >> 7;
51         data2 <<= 1;
52         S_CLK = 0;
53         S_CLK = 1;
54     }
55     for(i=0;i<8;i++)
56     {
57         MOSIO = data1 >> 7;
58         data1 <<= 1;
59         S_CLK = 0;
60         S_CLK = 1;
61     }
62     for(i=0;i<8;i++)
63     {
64         MOSIO = data0 >> 7;
65         data0 <<= 1;
66         S_CLK = 0;
67         S_CLK = 1;
68     }
69
70     R_CLK = 0;
71     R_CLK = 1;
72     R_CLK = 0;
73 }

array.h头文件如下:

 1 //点阵显示数组
 2 //用于行扫描
 3 unsigned char code tab0[] = {0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80,
 4                              0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00};
 5 //  我
 6 unsigned char code tab1[] ={96,2,28,10,16,18,16,2,254,63,16,2,16,18,112,18,24,10,22,10,16,36,16,42,16,49,156,32,0,0,0,0};
 7 //  叫
 8 unsigned char code tab2[] ={0,16,0,16,158,16,146,16,146,16,146,16,146,24,146,22,146,17,158,16,18,16,0,16,0,16,0,16,0,0,0,0};
 9 //  做
10 unsigned char code tab3[] ={80,2,80,2,72,2,232,62,76,17,74,18,232,18,168,18,168,10,168,10,168,4,232,10,40,17,136,32,0,0,0,0};
11 //  大
12 unsigned char code tab4[] ={128,0,128,0,128,0,128,0,254,63,128,0,64,1,64,1,64,1,32,2,32,2,16,4,8,8,6,48,0,0,0,0};
13 //  熙
14 unsigned char code tab5[] ={252,62,36,34,36,34,244,34,148,62,148,2,244,2,36,34,36,34,252,60,0,0,36,17,68,34,66,34,0,0,0,0};
15 //  熙
16 unsigned char code tab6[] ={252,62,36,34,36,34,244,34,148,62,148,2,244,2,36,34,36,34,252,60,0,0,36,17,68,34,66,34,0,0,0,0};

这里需要注意的一点就是数组指针的用法。明白那个之后整个程序就很容易了。

六、汉字纵向移屏

 1 #include <REG51.H>
 2 #include "array.h"
 3
 4 #define uchar unsigned char
 5 #define uint  unsigned int
 6
 7 //--定义SPI要使用的 IO--//
 8 sbit MOSIO = P3^4;
 9 sbit R_CLK = P3^5;
10 sbit S_CLK = P3^6;
11
12 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0);
13
14 void main(void)
15 {
16     int k, j, ms;
17
18     //--定义一个指针数组指向每个汉字--//
19     uchar *p[] = {tab8, tab1, tab2, tab3, tab4, tab5, tab6, tab7};
20     while(1)
21     {
22
23         for(ms = 20; ms > 0; ms--)    //移动定格时间设置
24         {
25             for(k = 0; k < 16; k++)
26             {
27                 //因为字模软件取的数组是高电平有效,所以列要取反
28                 HC595Pro(~(*(p[0] + 2*(k+j) + 1)),~(*(p[0] + 2*(k+j) )),tab0[2*k],tab0[2*k + 1]);
29             }
30
31             HC595Pro(0xFF,0xFF,0x00,0x00);//清屏
32         }
33         j++;
34         if(j == (7*16) )
35         {
36             j = 0;
37         }
38
39     }
40 }
41
42
43 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0)
44 {
45     uchar i;
46     for(i=0;i<8;i++)
47     {
48         MOSIO = data3 >> 7;
49         data3 <<= 1;
50         S_CLK = 0;
51         S_CLK = 1;
52     }
53     for(i=0;i<8;i++)
54     {
55         MOSIO = data2 >> 7;
56         data2 <<= 1;
57         S_CLK = 0;
58         S_CLK = 1;
59     }
60     for(i=0;i<8;i++)
61     {
62         MOSIO = data1 >> 7;
63         data1 <<= 1;
64         S_CLK = 0;
65         S_CLK = 1;
66     }
67     for(i=0;i<8;i++)
68     {
69         MOSIO = data0 >> 7;
70         data0 <<= 1;
71         S_CLK = 0;
72         S_CLK = 1;
73     }
74
75     R_CLK = 0;
76     R_CLK = 1;
77     R_CLK = 0;
78 }

array.h头文件如下:

//点阵显示数组
//用于行扫描
unsigned char code tab0[] = {0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80,
                             0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00};
//全灭
unsigned char code tab8[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//  我
unsigned char code tab1[] ={96,2,28,10,16,18,16,2,254,63,16,2,16,18,112,18,24,10,22,10,16,36,16,42,16,49,156,32,0,0,0,0};
//  叫
unsigned char code tab2[] ={0,16,0,16,158,16,146,16,146,16,146,16,146,24,146,22,146,17,158,16,18,16,0,16,0,16,0,16,0,0,0,0};
//  做
unsigned char code tab3[] ={80,2,80,2,72,2,232,62,76,17,74,18,232,18,168,18,168,10,168,10,168,4,232,10,40,17,136,32,0,0,0,0};
//  大
unsigned char code tab4[] ={128,0,128,0,128,0,128,0,254,63,128,0,64,1,64,1,64,1,32,2,32,2,16,4,8,8,6,48,0,0,0,0};
//  熙
unsigned char code tab5[] ={252,62,36,34,36,34,244,34,148,62,148,2,244,2,36,34,36,34,252,60,0,0,36,17,68,34,66,34,0,0,0,0};
//  熙
unsigned char code tab6[] ={252,62,36,34,36,34,244,34,148,62,148,2,244,2,36,34,36,34,252,60,0,0,36,17,68,34,66,34,0,0,0,0};
//全灭
unsigned char code tab7[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

主函数中的*(p[0] + 2*(k+j) + 1)就是P[0][2(k+j)+1],*(p[0] + 2*(k+j))就是P[0][2(k+j)],就是P数组的第0行。

我们先来看看怎么纵向显示汉字。纵向移动就可以理解为一开始是有一个无限大的点阵是让你放你想要的内容的。加入你一开始放好了。但是一开始只显示一个汉字,然后隔一段时间,整个向上移一行,再显示一张图像。以此循环,直到整个全部显示完。

就是通过这个原理,实现纵向移动的。

至于j的值怎么判断,我是这么理解的:

“我叫做大熙熙”一共六个字,然后加上最前面和最后的全灭,一共是8*32位。

所以整个数组最大为P[0][255](根据所指向的位置分析,P[0][32]就是P[1][0])。

所以这里j取7*16时,数组最大为P[0][255],最后一位没读,但是数组本身存的值为0,取反之后就是1,列为高电平的话就算不读也是灭的。

相反,但是如果取8*16的话,数组最大为P[0][287],多出来的几位因为数组没初始化过,所以不知道相对应的地址会是什么值。所以可能会造成有点地方亮,影响最终效果。

总而言之,最后的判断值越接近实际数组大小越好。

个人意见,解析也不是很专业,不过希望能看懂。。哈哈。。

结语:对于纵向移动的话采用的是行扫描法,然后显示信息放在列中。横向移动的话就采用列扫描法,显示信息放在行中。

这里具体的就不呈现了,因为都差不多啦。

时间: 2024-11-07 15:21:28

[51单片机学习笔记FOUR]----16*16LED点阵的相关文章

[51单片机学习笔记ONE]-----LED灯的多种使用方法

一.交替闪烁8个LED灯,时间间隔为1s 1 /****************************************************** 2 实验名称: 交替闪烁8个LED灯,时间间隔1s 3 实验时间: 2014年12月2日 4 ******************************************************/ 5 6 #include <reg51.h> 7 8 void delay(unsigned char a); 9 10 void m

[51单片机学习笔记TWO]----蜂鸣器

蜂鸣器音乐播放实验 首先应该了解一下蜂鸣器音乐播放的原理,在这里我只讲一下电磁式蜂鸣器驱动原理(还有一种是压电式蜂鸣器): 电磁式蜂鸣器驱动原理: 蜂鸣器发声原理是电流通过电磁线圈,使电磁圈产生磁场来驱动振动膜发声的.因此需要一定的电流才能驱动它,而单片机I/O引脚输出的电压较小.单片机输出的TTLK电平基本驱动不了蜂鸣器,因需要增加一个放大电路.这里用三极管作为放大电路.下面是原理图: 我这里的J8端是跟芯片的P1^5端口相连,当P1^5输出高电平时,三极管截止,蜂鸣器不发声,反之,输出低电平

51单片机学习笔记【五】——1602液晶屏

一.1602液晶屏基础 1.LCD1602简介 1602液晶也叫1602字符型液晶,它是一种专门用来显示字母.数字.符号的点阵型液晶模块.它是由若干个5x7或者5x11的点阵字符位组成,每个点阵字符位都可以用显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此,所以它不能很好的显示图片.本次使用型号为SMC1602A LCM的液晶屏. 2.LCD1602接口信号说明 3.控制接口说明 4.指令说明 二.实验例程 1.电路原理图 2.实验说明 本实验通

51单片机学习笔记【0】——基础知识

一.单片机三大资源 1.Flash--程序存储空间 相当于计算机的硬盘,可实现断电后数据不丢失. 2.RAM--数据存储空间 相当于计算机的内存,用来存储程序运行过程中产生和需要的数据,断电后数据丢失,优点是读取速度快,可无限次写入. 3.SFR--特殊功能寄存器 单片机每个功能都对应一个 多个SFR,用户通过对SFR的读写来实现单片机的功能. 二.单片机的最小系统 1.电源 主流单片机采用5V和3.3V的电压,供电电路40引脚接+5V,通常也成为VCC或VDD,代表电源正极:20引脚接GND,

[51单片机学习笔记FIVE]----独立按键

一.8个按键控制8个LED灯 1 /******************************************************************************* 2 实验名称: 8个独立按键控制8盏LED灯(按下哪个键,那个键对应的LED亮) 3 实验时间: 2015/1/20 4 *******************************************************************************/ 5 #include

[51单片机学习笔记THREE]----继电器

继电器是一种电控制器件,它是当输入量(如电压,电流,温度等)达到规定值时,使得被控量发生阶跃性变化的一种电器. 比如说:我们只需要用一个12V,0.1A的参数量去控制一个继电器,然后让继电器去充当几百万伏特,几百万安培的设备的开关. 无论在什么地方,如果想让控制者处于安全的环境中,就可以用继电器.让我们去接触安全的一边,让继电器去接触危险的一边,我们只要控制继电器的动作,继电器就会帮助我们连接我们不想亲自去碰的一些线路. 继电器的分类千千万,这里就不多说了. 最近因为好像没什么地方要用到,这里先

51单片机学习笔记【六】——串口通信实验

一.串口通信基础 1.串行通信 串行通信将数据字节分成一位一位的形式在一条传输线上逐个传送.单片机采用串行通信.特点是:传输线少,长距离传送成本低,但数据传送控制复杂. 串行通信的传输的传输方向:单工(数据传输只能沿一个方向),办双工(传输数据和接受数据分布进行),全双工(传输和接受同步进行). 单片机采用异步通信,发送和接受设备使用各自的时钟频率,容易实现,但传输效率不高,数据格式 2.MAX232 实验通过MAX232电平转换芯片,可把计算机串口电平(-12V~+12V)转换为单片及TTL电

51单片机学习笔记【八】——步进电机

一.步进电机基础 1.定义 步进电机是将电脉冲转化为角位移的执行机构,主要使用永磁性步进电机,本实验使用的步进电机为四线双性步进电机: 步进电机的相数指产生不同极性N,S磁场的激磁线圈对数,常用m表示: 步进电机的拍数指完成一个磁场周期性变化所需脉冲数,以四线二相电机为例: 单向四拍:A/-B-A-B/ 双向四拍:A/B-AB-AB/-A/B/ 单&双八拍:A/-A/B-B-AB-C-A-AB/-B/-A/B/ 步进角指定子没改变一次通电状态,转子转过的角度,与磁极数,定子相数,通电方式节拍成负

51单片机学习笔记【九】——红外通信实验

一.红外通信基础 1.红外线原理 红外线是波长在760nm~1mm之间的非可见光.红外通信装置由红外发射管和红外接受管组成,红外发射管是能发射出红外线的发光二极管,发射强度随着电流的增大而增大:红外接受管是一个具有红外光敏感特征的PN节的光敏二极管,只对红外线有反应,产生光电流. 2.信号调制原理 基带信号:从信号源发出没有经过调制的原始信号,特点是频率较低,信号频率从0开始,频谱较宽. 调制:就是用待传送信号去控制某个高频信号的幅度.相位.频率等参量变化的过程,即用一个信号去装载另一个信号.